toastify-pro 1.6.0 → 1.7.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 +143 -845
- package/assets/screenshots/desktop-demo.png +0 -0
- package/dist/toastify-pro.esm.js +824 -43
- package/dist/toastify-pro.esm.js.map +1 -1
- package/dist/toastify-pro.umd.js +824 -43
- package/dist/toastify-pro.umd.js.map +1 -1
- package/dist/toastify-pro.umd.min.js +5 -3
- package/dist/toastify-pro.umd.min.js.map +1 -1
- package/package.json +5 -2
- package/src/toastify-pro.js +824 -43
- package/assets/site/site.webmanifest +0 -217
package/dist/toastify-pro.esm.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* - Responsive design for mobile devices
|
|
15
15
|
* - Framework agnostic (works with React, Vue, Angular, etc.)
|
|
16
16
|
* - Confirmation dialogs with customizable buttons and callbacks
|
|
17
|
+
* - Input prompts with validation and async support
|
|
17
18
|
* - Confirmation overlay with blur effect for focus
|
|
18
19
|
* - Center position support for enhanced focus
|
|
19
20
|
* - Independent positioning for confirmations
|
|
@@ -21,9 +22,10 @@
|
|
|
21
22
|
* - Pause on hover functionality
|
|
22
23
|
* - Queue management (maxToasts, newestOnTop)
|
|
23
24
|
* - Full accessibility support (ARIA, keyboard navigation, reduced motion)
|
|
24
|
-
* - Focus management for confirmation dialogs
|
|
25
|
+
* - Focus management for confirmation and input dialogs
|
|
26
|
+
* - Improved dismiss handling (no hover interference)
|
|
25
27
|
*
|
|
26
|
-
* @version 1.
|
|
28
|
+
* @version 1.7.0
|
|
27
29
|
* @author ToastifyPro Team
|
|
28
30
|
* @license MIT
|
|
29
31
|
*/
|
|
@@ -264,19 +266,19 @@ class ToastifyPro {
|
|
|
264
266
|
@keyframes airdropPop {
|
|
265
267
|
0% {
|
|
266
268
|
opacity: 0;
|
|
267
|
-
transform: scale(0.
|
|
269
|
+
transform: scale(0.5) rotateY(-15deg) translateY(20px);
|
|
268
270
|
}
|
|
269
|
-
|
|
270
|
-
opacity: 0.
|
|
271
|
-
transform: scale(1.
|
|
271
|
+
50% {
|
|
272
|
+
opacity: 0.95;
|
|
273
|
+
transform: scale(1.03) rotateY(5deg) translateY(-3px);
|
|
272
274
|
}
|
|
273
|
-
|
|
275
|
+
75% {
|
|
274
276
|
opacity: 1;
|
|
275
|
-
transform: scale(0.
|
|
277
|
+
transform: scale(0.99) rotateY(-1deg) translateY(1px);
|
|
276
278
|
}
|
|
277
279
|
100% {
|
|
278
280
|
opacity: 1;
|
|
279
|
-
transform: scale(1) rotateY(0deg);
|
|
281
|
+
transform: scale(1) rotateY(0deg) translateY(0);
|
|
280
282
|
}
|
|
281
283
|
}
|
|
282
284
|
|
|
@@ -285,13 +287,13 @@ class ToastifyPro {
|
|
|
285
287
|
opacity: 1;
|
|
286
288
|
transform: scale(1) translateY(0);
|
|
287
289
|
}
|
|
288
|
-
|
|
290
|
+
12% {
|
|
289
291
|
opacity: 1;
|
|
290
|
-
transform: scale(1.
|
|
292
|
+
transform: scale(1.015) translateY(-6px);
|
|
291
293
|
}
|
|
292
294
|
100% {
|
|
293
295
|
opacity: 0;
|
|
294
|
-
transform: scale(0.
|
|
296
|
+
transform: scale(0.85) translateY(150px);
|
|
295
297
|
}
|
|
296
298
|
}
|
|
297
299
|
|
|
@@ -300,13 +302,13 @@ class ToastifyPro {
|
|
|
300
302
|
opacity: 1;
|
|
301
303
|
transform: scale(1) translateY(0);
|
|
302
304
|
}
|
|
303
|
-
|
|
305
|
+
12% {
|
|
304
306
|
opacity: 1;
|
|
305
|
-
transform: scale(1.
|
|
307
|
+
transform: scale(1.015) translateY(6px);
|
|
306
308
|
}
|
|
307
309
|
100% {
|
|
308
310
|
opacity: 0;
|
|
309
|
-
transform: scale(0.
|
|
311
|
+
transform: scale(0.85) translateY(-150px);
|
|
310
312
|
}
|
|
311
313
|
}
|
|
312
314
|
|
|
@@ -315,13 +317,13 @@ class ToastifyPro {
|
|
|
315
317
|
opacity: 1;
|
|
316
318
|
transform: scale(1) translateX(0);
|
|
317
319
|
}
|
|
318
|
-
|
|
320
|
+
12% {
|
|
319
321
|
opacity: 1;
|
|
320
|
-
transform: scale(1.
|
|
322
|
+
transform: scale(1.015) translateX(6px);
|
|
321
323
|
}
|
|
322
324
|
100% {
|
|
323
325
|
opacity: 0;
|
|
324
|
-
transform: scale(0.
|
|
326
|
+
transform: scale(0.85) translateX(-250px);
|
|
325
327
|
}
|
|
326
328
|
}
|
|
327
329
|
|
|
@@ -330,13 +332,13 @@ class ToastifyPro {
|
|
|
330
332
|
opacity: 1;
|
|
331
333
|
transform: scale(1) translateX(0);
|
|
332
334
|
}
|
|
333
|
-
|
|
335
|
+
12% {
|
|
334
336
|
opacity: 1;
|
|
335
|
-
transform: scale(1.
|
|
337
|
+
transform: scale(1.015) translateX(-6px);
|
|
336
338
|
}
|
|
337
339
|
100% {
|
|
338
340
|
opacity: 0;
|
|
339
|
-
transform: scale(0.
|
|
341
|
+
transform: scale(0.85) translateX(250px);
|
|
340
342
|
}
|
|
341
343
|
}
|
|
342
344
|
|
|
@@ -345,13 +347,13 @@ class ToastifyPro {
|
|
|
345
347
|
opacity: 1;
|
|
346
348
|
transform: scale(1) translateY(0);
|
|
347
349
|
}
|
|
348
|
-
|
|
350
|
+
12% {
|
|
349
351
|
opacity: 1;
|
|
350
|
-
transform: scale(1.
|
|
352
|
+
transform: scale(1.015) translateY(-4px);
|
|
351
353
|
}
|
|
352
354
|
100% {
|
|
353
355
|
opacity: 0;
|
|
354
|
-
transform: scale(0.
|
|
356
|
+
transform: scale(0.7) translateY(120px);
|
|
355
357
|
}
|
|
356
358
|
}
|
|
357
359
|
|
|
@@ -388,7 +390,7 @@ class ToastifyPro {
|
|
|
388
390
|
.toastify-pro.show {
|
|
389
391
|
opacity: 1;
|
|
390
392
|
transform: scale(1);
|
|
391
|
-
animation: airdropPop 0.
|
|
393
|
+
animation: airdropPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
392
394
|
}
|
|
393
395
|
|
|
394
396
|
.toastify-pro.success {
|
|
@@ -467,9 +469,9 @@ class ToastifyPro {
|
|
|
467
469
|
}
|
|
468
470
|
|
|
469
471
|
@keyframes iconBounce {
|
|
470
|
-
0% { transform: scale(0.
|
|
471
|
-
|
|
472
|
-
70% { transform: scale(0.
|
|
472
|
+
0% { transform: scale(0.3) rotate(-10deg); opacity: 0; }
|
|
473
|
+
50% { transform: scale(1.1) rotate(5deg); opacity: 1; }
|
|
474
|
+
70% { transform: scale(0.97) rotate(-2deg); }
|
|
473
475
|
100% { transform: scale(1) rotate(0deg); }
|
|
474
476
|
}
|
|
475
477
|
|
|
@@ -478,12 +480,12 @@ class ToastifyPro {
|
|
|
478
480
|
transform: scale(1) rotate(0deg);
|
|
479
481
|
opacity: 1;
|
|
480
482
|
}
|
|
481
|
-
|
|
482
|
-
transform: scale(1.
|
|
483
|
-
opacity: 0.
|
|
483
|
+
25% {
|
|
484
|
+
transform: scale(1.08) rotate(-8deg);
|
|
485
|
+
opacity: 0.85;
|
|
484
486
|
}
|
|
485
487
|
100% {
|
|
486
|
-
transform: scale(0.
|
|
488
|
+
transform: scale(0.4) rotate(120deg);
|
|
487
489
|
opacity: 0;
|
|
488
490
|
}
|
|
489
491
|
}
|
|
@@ -492,6 +494,11 @@ class ToastifyPro {
|
|
|
492
494
|
0% { transform: rotate(0deg); }
|
|
493
495
|
100% { transform: rotate(360deg); }
|
|
494
496
|
}
|
|
497
|
+
|
|
498
|
+
@keyframes spinFast {
|
|
499
|
+
0% { transform: rotate(0deg); }
|
|
500
|
+
100% { transform: rotate(360deg); }
|
|
501
|
+
}
|
|
495
502
|
|
|
496
503
|
.toastify-pro .toast-icon svg {
|
|
497
504
|
width: 18px;
|
|
@@ -816,7 +823,7 @@ class ToastifyPro {
|
|
|
816
823
|
.toast-btn-confirm .btn-spinner svg {
|
|
817
824
|
width: 25px;
|
|
818
825
|
height: 25px;
|
|
819
|
-
animation:
|
|
826
|
+
animation: spinFast 0.5s linear infinite;
|
|
820
827
|
color: currentColor;
|
|
821
828
|
}
|
|
822
829
|
|
|
@@ -952,6 +959,11 @@ class ToastifyPro {
|
|
|
952
959
|
animation-play-state: paused;
|
|
953
960
|
}
|
|
954
961
|
|
|
962
|
+
/* Progress restart - used after hover to restart progress bar only */
|
|
963
|
+
.toastify-pro.progress-restart::after {
|
|
964
|
+
animation: none;
|
|
965
|
+
}
|
|
966
|
+
|
|
955
967
|
/* Focus styles for accessibility */
|
|
956
968
|
.toastify-pro .close-btn:focus,
|
|
957
969
|
.toastify-pro .toast-action:focus,
|
|
@@ -977,6 +989,240 @@ class ToastifyPro {
|
|
|
977
989
|
border: 0;
|
|
978
990
|
}
|
|
979
991
|
|
|
992
|
+
/* ===== INPUT TOAST STYLES ===== */
|
|
993
|
+
.toastify-pro.input-toast {
|
|
994
|
+
min-width: 340px;
|
|
995
|
+
max-width: 450px;
|
|
996
|
+
padding: 24px 24px 20px;
|
|
997
|
+
flex-direction: column;
|
|
998
|
+
align-items: stretch;
|
|
999
|
+
gap: 16px;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
.toastify-pro.input-toast .toast-input-wrapper {
|
|
1003
|
+
display: flex;
|
|
1004
|
+
flex-direction: column;
|
|
1005
|
+
gap: 16px;
|
|
1006
|
+
width: 100%;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
.toastify-pro.input-toast .toast-input-header {
|
|
1010
|
+
display: flex;
|
|
1011
|
+
align-items: flex-start;
|
|
1012
|
+
gap: 12px;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
.toastify-pro.input-toast .toast-input {
|
|
1016
|
+
width: 100%;
|
|
1017
|
+
padding: 12px 16px;
|
|
1018
|
+
border: 1.5px solid rgba(255, 255, 255, 0.2);
|
|
1019
|
+
border-radius: 12px;
|
|
1020
|
+
background: rgba(255, 255, 255, 0.08);
|
|
1021
|
+
backdrop-filter: blur(12px);
|
|
1022
|
+
color: inherit;
|
|
1023
|
+
font-family: inherit;
|
|
1024
|
+
font-size: 14px;
|
|
1025
|
+
font-weight: 450;
|
|
1026
|
+
outline: none;
|
|
1027
|
+
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
|
1028
|
+
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
.toastify-pro.input-toast .toast-input::placeholder {
|
|
1032
|
+
color: rgba(255, 255, 255, 0.5);
|
|
1033
|
+
font-weight: 400;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
.toastify-pro.input-toast .toast-input:focus {
|
|
1037
|
+
border-color: rgba(255, 255, 255, 0.45);
|
|
1038
|
+
background: rgba(255, 255, 255, 0.12);
|
|
1039
|
+
box-shadow:
|
|
1040
|
+
inset 0 1px 2px rgba(0, 0, 0, 0.1),
|
|
1041
|
+
0 0 0 3px rgba(255, 255, 255, 0.08);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
.toastify-pro.input-toast .toast-input:hover:not(:focus) {
|
|
1045
|
+
border-color: rgba(255, 255, 255, 0.3);
|
|
1046
|
+
background: rgba(255, 255, 255, 0.1);
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
.toastify-pro.input-toast.light .toast-input {
|
|
1050
|
+
border-color: rgba(15, 23, 42, 0.15);
|
|
1051
|
+
background: rgba(15, 23, 42, 0.04);
|
|
1052
|
+
box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.06);
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
.toastify-pro.input-toast.light .toast-input::placeholder {
|
|
1056
|
+
color: rgba(15, 23, 42, 0.45);
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
.toastify-pro.input-toast.light .toast-input:focus {
|
|
1060
|
+
border-color: rgba(15, 23, 42, 0.35);
|
|
1061
|
+
background: rgba(15, 23, 42, 0.06);
|
|
1062
|
+
box-shadow:
|
|
1063
|
+
inset 0 1px 2px rgba(15, 23, 42, 0.06),
|
|
1064
|
+
0 0 0 3px rgba(15, 23, 42, 0.06);
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
.toastify-pro.input-toast.light .toast-input:hover:not(:focus) {
|
|
1068
|
+
border-color: rgba(15, 23, 42, 0.25);
|
|
1069
|
+
background: rgba(15, 23, 42, 0.06);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
.toastify-pro.input-toast .toast-input-actions {
|
|
1073
|
+
display: flex;
|
|
1074
|
+
gap: 10px;
|
|
1075
|
+
justify-content: flex-end;
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
.toastify-pro.input-toast .input-btn {
|
|
1079
|
+
padding: 10px 20px;
|
|
1080
|
+
border-radius: 10px;
|
|
1081
|
+
font-size: 14px;
|
|
1082
|
+
font-weight: 550;
|
|
1083
|
+
cursor: pointer;
|
|
1084
|
+
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
1085
|
+
border: 1.5px solid transparent;
|
|
1086
|
+
position: relative;
|
|
1087
|
+
overflow: hidden;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
.toastify-pro.input-toast .input-btn-cancel {
|
|
1091
|
+
background: rgba(255, 255, 255, 0.1);
|
|
1092
|
+
color: rgba(255, 255, 255, 0.9);
|
|
1093
|
+
border-color: rgba(255, 255, 255, 0.2);
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
.toastify-pro.input-toast .input-btn-cancel:hover {
|
|
1097
|
+
background: rgba(255, 255, 255, 0.18);
|
|
1098
|
+
border-color: rgba(255, 255, 255, 0.3);
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
.toastify-pro.input-toast .input-btn-submit {
|
|
1102
|
+
background: linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.85) 100%);
|
|
1103
|
+
color: #1e293b;
|
|
1104
|
+
border-color: rgba(255, 255, 255, 0.4);
|
|
1105
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
.toastify-pro.input-toast .input-btn-submit:hover {
|
|
1109
|
+
background: linear-gradient(135deg, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0.95) 100%);
|
|
1110
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
|
|
1111
|
+
transform: translateY(-1px);
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
.toastify-pro.input-toast .input-btn-submit:active {
|
|
1115
|
+
transform: translateY(0);
|
|
1116
|
+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
.toastify-pro.input-toast.light .input-btn-cancel {
|
|
1120
|
+
background: rgba(15, 23, 42, 0.06);
|
|
1121
|
+
color: rgba(15, 23, 42, 0.85);
|
|
1122
|
+
border-color: rgba(15, 23, 42, 0.15);
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
.toastify-pro.input-toast.light .input-btn-cancel:hover {
|
|
1126
|
+
background: rgba(15, 23, 42, 0.1);
|
|
1127
|
+
border-color: rgba(15, 23, 42, 0.25);
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
.toastify-pro.input-toast.light .input-btn-submit {
|
|
1131
|
+
background: linear-gradient(135deg, #1e293b 0%, #334155 100%);
|
|
1132
|
+
color: white;
|
|
1133
|
+
border-color: rgba(15, 23, 42, 0.3);
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
.toastify-pro.input-toast.light .input-btn-submit:hover {
|
|
1137
|
+
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
|
|
1138
|
+
box-shadow: 0 4px 16px rgba(15, 23, 42, 0.25);
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
/* Input toast loading state */
|
|
1142
|
+
.toastify-pro.input-toast .input-btn-submit.loading {
|
|
1143
|
+
opacity: 0.7;
|
|
1144
|
+
cursor: not-allowed;
|
|
1145
|
+
pointer-events: none;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
.toastify-pro.input-toast .input-btn-submit .btn-spinner {
|
|
1149
|
+
display: none;
|
|
1150
|
+
align-items: center;
|
|
1151
|
+
justify-content: center;
|
|
1152
|
+
margin-left: 6px;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
.toastify-pro.input-toast .input-btn-submit .btn-spinner svg {
|
|
1156
|
+
width: 16px;
|
|
1157
|
+
height: 16px;
|
|
1158
|
+
animation: spinFast 0.5s linear infinite;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
.toastify-pro.input-toast .input-btn-submit.loading .btn-spinner {
|
|
1162
|
+
display: inline-flex;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
.toastify-pro.input-toast .input-btn-submit.loading .btn-text {
|
|
1166
|
+
opacity: 0.7;
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
/* Input validation error state */
|
|
1170
|
+
.toastify-pro.input-toast .toast-input.error {
|
|
1171
|
+
border-color: rgba(239, 68, 68, 0.6);
|
|
1172
|
+
background: rgba(239, 68, 68, 0.08);
|
|
1173
|
+
animation: inputShake 0.4s cubic-bezier(0.36, 0.07, 0.19, 0.97);
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
.toastify-pro.input-toast .toast-input-error {
|
|
1177
|
+
color: #f87171;
|
|
1178
|
+
font-size: 12px;
|
|
1179
|
+
font-weight: 450;
|
|
1180
|
+
margin-top: -8px;
|
|
1181
|
+
opacity: 0;
|
|
1182
|
+
transform: translateY(-4px);
|
|
1183
|
+
transition: all 0.2s ease;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
.toastify-pro.input-toast .toast-input-error.visible {
|
|
1187
|
+
opacity: 1;
|
|
1188
|
+
transform: translateY(0);
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
.toastify-pro.input-toast.light .toast-input.error {
|
|
1192
|
+
border-color: rgba(239, 68, 68, 0.5);
|
|
1193
|
+
background: rgba(239, 68, 68, 0.06);
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
.toastify-pro.input-toast.light .toast-input-error {
|
|
1197
|
+
color: #dc2626;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
@keyframes inputShake {
|
|
1201
|
+
0%, 100% { transform: translateX(0); }
|
|
1202
|
+
20%, 60% { transform: translateX(-6px); }
|
|
1203
|
+
40%, 80% { transform: translateX(6px); }
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
/* Hide progress bar for input toasts */
|
|
1207
|
+
.toastify-pro.input-toast::after {
|
|
1208
|
+
display: none;
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
@media (max-width: 640px) {
|
|
1212
|
+
.toastify-pro.input-toast {
|
|
1213
|
+
min-width: 280px;
|
|
1214
|
+
max-width: calc(100vw - 32px);
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
.toastify-pro.input-toast .toast-input-actions {
|
|
1218
|
+
flex-direction: column;
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
.toastify-pro.input-toast .input-btn {
|
|
1222
|
+
width: 100%;
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
|
|
980
1226
|
/* Reduced motion support */
|
|
981
1227
|
@media (prefers-reduced-motion: reduce) {
|
|
982
1228
|
.toastify-pro {
|
|
@@ -1019,7 +1265,7 @@ class ToastifyPro {
|
|
|
1019
1265
|
}
|
|
1020
1266
|
|
|
1021
1267
|
.btn-spinner svg {
|
|
1022
|
-
animation:
|
|
1268
|
+
animation: spinFast 0.5s linear infinite !important;
|
|
1023
1269
|
}
|
|
1024
1270
|
}
|
|
1025
1271
|
`;
|
|
@@ -1165,7 +1411,8 @@ class ToastifyPro {
|
|
|
1165
1411
|
timeout: null,
|
|
1166
1412
|
remainingTime: options.timeout,
|
|
1167
1413
|
startTime: null,
|
|
1168
|
-
isPaused: false
|
|
1414
|
+
isPaused: false,
|
|
1415
|
+
isRemoving: false // Flag to prevent hover interference during removal
|
|
1169
1416
|
};
|
|
1170
1417
|
this.activeToasts.push(toastData);
|
|
1171
1418
|
|
|
@@ -1182,6 +1429,8 @@ class ToastifyPro {
|
|
|
1182
1429
|
// Pause on hover functionality
|
|
1183
1430
|
if (options.pauseOnHover && options.timeout > 0) {
|
|
1184
1431
|
toast.addEventListener('mouseenter', () => {
|
|
1432
|
+
// Don't pause if toast is being removed
|
|
1433
|
+
if (toastData.isRemoving) return;
|
|
1185
1434
|
if (toastData.timeout) {
|
|
1186
1435
|
clearTimeout(toastData.timeout);
|
|
1187
1436
|
toastData.isPaused = true;
|
|
@@ -1191,17 +1440,19 @@ class ToastifyPro {
|
|
|
1191
1440
|
});
|
|
1192
1441
|
|
|
1193
1442
|
toast.addEventListener('mouseleave', () => {
|
|
1443
|
+
// Don't restart timer if toast is being removed
|
|
1444
|
+
if (toastData.isRemoving) return;
|
|
1194
1445
|
if (toastData.isPaused && toastData.remainingTime > 0) {
|
|
1195
1446
|
toastData.isPaused = false;
|
|
1196
1447
|
toastData.startTime = Date.now();
|
|
1197
1448
|
toast.classList.remove('paused');
|
|
1198
1449
|
// Update CSS variable for remaining progress
|
|
1199
1450
|
toast.style.setProperty('--duration', `${toastData.remainingTime}ms`);
|
|
1200
|
-
// Restart the progress animation
|
|
1201
|
-
|
|
1202
|
-
toast.
|
|
1451
|
+
// Restart the progress bar animation only (not the main toast animation)
|
|
1452
|
+
// Using class toggle to reset pseudo-element animation without affecting main element
|
|
1453
|
+
toast.classList.add('progress-restart');
|
|
1203
1454
|
void toast.offsetHeight; // Force reflow
|
|
1204
|
-
toast.
|
|
1455
|
+
toast.classList.remove('progress-restart');
|
|
1205
1456
|
|
|
1206
1457
|
toastData.timeout = setTimeout(() => this.removeToast(toast), toastData.remainingTime);
|
|
1207
1458
|
}
|
|
@@ -1275,16 +1526,25 @@ class ToastifyPro {
|
|
|
1275
1526
|
}
|
|
1276
1527
|
|
|
1277
1528
|
try {
|
|
1278
|
-
// Remove from active toasts tracking
|
|
1529
|
+
// Remove from active toasts tracking and set removal flag
|
|
1279
1530
|
const toastIndex = this.activeToasts.findIndex(t => t.element === toast);
|
|
1280
1531
|
if (toastIndex > -1) {
|
|
1281
1532
|
const toastData = this.activeToasts[toastIndex];
|
|
1533
|
+
// Prevent hover events from interfering during removal
|
|
1534
|
+
toastData.isRemoving = true;
|
|
1282
1535
|
if (toastData.timeout) {
|
|
1283
1536
|
clearTimeout(toastData.timeout);
|
|
1284
1537
|
}
|
|
1285
1538
|
this.activeToasts.splice(toastIndex, 1);
|
|
1286
1539
|
}
|
|
1287
1540
|
|
|
1541
|
+
// Mark the toast element as removing to prevent double-removal
|
|
1542
|
+
if (toast.dataset.removing === 'true') return;
|
|
1543
|
+
toast.dataset.removing = 'true';
|
|
1544
|
+
|
|
1545
|
+
// Disable pointer events during exit animation to prevent hover issues
|
|
1546
|
+
toast.style.pointerEvents = 'none';
|
|
1547
|
+
|
|
1288
1548
|
// Detect position to choose the right swipe direction
|
|
1289
1549
|
const container = toast.parentNode;
|
|
1290
1550
|
const position = container.className.split(' ')[1]; // get position class
|
|
@@ -1305,12 +1565,12 @@ class ToastifyPro {
|
|
|
1305
1565
|
}
|
|
1306
1566
|
|
|
1307
1567
|
// Apply fast car swipe animation with improved easing
|
|
1308
|
-
toast.style.animation = `${swipeAnimation} 0.
|
|
1568
|
+
toast.style.animation = `${swipeAnimation} 0.35s cubic-bezier(0.55, 0.0, 0.85, 0.36) forwards`;
|
|
1309
1569
|
|
|
1310
1570
|
// Add spinning icon animation for extra polish
|
|
1311
1571
|
const icon = toast.querySelector('.toast-icon');
|
|
1312
1572
|
if (icon) {
|
|
1313
|
-
icon.style.animation = 'iconCarExit 0.
|
|
1573
|
+
icon.style.animation = 'iconCarExit 0.35s cubic-bezier(0.55, 0.0, 0.85, 0.36) forwards';
|
|
1314
1574
|
}
|
|
1315
1575
|
|
|
1316
1576
|
// Remove element after animation completes
|
|
@@ -1318,7 +1578,7 @@ class ToastifyPro {
|
|
|
1318
1578
|
if (toast.parentNode) {
|
|
1319
1579
|
toast.remove();
|
|
1320
1580
|
}
|
|
1321
|
-
},
|
|
1581
|
+
}, 350);
|
|
1322
1582
|
} catch (error) {
|
|
1323
1583
|
console.error('ToastifyPro: Error removing toast:', error);
|
|
1324
1584
|
// Fallback: remove immediately if animation fails
|
|
@@ -2174,6 +2434,527 @@ class ToastifyPro {
|
|
|
2174
2434
|
confirm(message, descriptionOrCallback, callback) {
|
|
2175
2435
|
return this.conf(message, descriptionOrCallback, callback);
|
|
2176
2436
|
}
|
|
2437
|
+
|
|
2438
|
+
/**
|
|
2439
|
+
* Shows an input prompt toast with a text field
|
|
2440
|
+
* @param {string} message - Main prompt question
|
|
2441
|
+
* @param {string|Function|Object} descriptionOrCallback - Description text, callback function, or options object
|
|
2442
|
+
* @param {Function} callback - Callback function (if description provided)
|
|
2443
|
+
* @returns {Object} Control object with element, close, setValue, getValue methods
|
|
2444
|
+
*
|
|
2445
|
+
* Options object:
|
|
2446
|
+
* - description: {string} Optional description text
|
|
2447
|
+
* - placeholder: {string} Input placeholder text (default: 'Enter your response...')
|
|
2448
|
+
* - submitText: {string} Submit button text (default: 'Submit')
|
|
2449
|
+
* - cancelText: {string} Cancel button text (default: 'Cancel')
|
|
2450
|
+
* - defaultValue: {string} Default input value
|
|
2451
|
+
* - required: {boolean} Whether input is required (default: true)
|
|
2452
|
+
* - type: {string} Input type: 'text', 'email', 'number', 'password', 'url' (default: 'text')
|
|
2453
|
+
* - validate: {Function} Custom validation function (receives value, returns true or error string)
|
|
2454
|
+
* - onSubmit: {Function} Called when user submits (receives value, control object)
|
|
2455
|
+
* - onCancel: {Function} Called when user cancels
|
|
2456
|
+
* - theme: {string} Toast theme: 'dark' or 'light' (default: 'dark')
|
|
2457
|
+
* - position: {string} Override default position
|
|
2458
|
+
* - overlay: {boolean} Show overlay behind toast (default: true)
|
|
2459
|
+
* - primaryColor: {string} Custom primary color
|
|
2460
|
+
* - secondaryColor: {string} Custom secondary color for gradient
|
|
2461
|
+
*
|
|
2462
|
+
* @example
|
|
2463
|
+
* // Simple usage
|
|
2464
|
+
* toast.input('What is your name?', (value) => console.log(value));
|
|
2465
|
+
*
|
|
2466
|
+
* // With description
|
|
2467
|
+
* toast.input('Enter your email', 'We will send you updates', (value) => {...});
|
|
2468
|
+
*
|
|
2469
|
+
* // Full options
|
|
2470
|
+
* toast.input('Enter password', {
|
|
2471
|
+
* type: 'password',
|
|
2472
|
+
* placeholder: 'Minimum 8 characters',
|
|
2473
|
+
* validate: (val) => val.length >= 8 || 'Password must be at least 8 characters',
|
|
2474
|
+
* onSubmit: (value) => { ... },
|
|
2475
|
+
* theme: 'light'
|
|
2476
|
+
* });
|
|
2477
|
+
*/
|
|
2478
|
+
input(message, descriptionOrCallback, callback) {
|
|
2479
|
+
try {
|
|
2480
|
+
// Parse arguments like confirm method
|
|
2481
|
+
let description = '';
|
|
2482
|
+
let options = {};
|
|
2483
|
+
let resultCallback = null;
|
|
2484
|
+
|
|
2485
|
+
if (typeof descriptionOrCallback === 'string') {
|
|
2486
|
+
description = descriptionOrCallback;
|
|
2487
|
+
if (typeof callback === 'function') {
|
|
2488
|
+
resultCallback = callback;
|
|
2489
|
+
} else if (typeof callback === 'object') {
|
|
2490
|
+
options = callback || {};
|
|
2491
|
+
resultCallback = options.onSubmit || null;
|
|
2492
|
+
}
|
|
2493
|
+
} else if (typeof descriptionOrCallback === 'function') {
|
|
2494
|
+
resultCallback = descriptionOrCallback;
|
|
2495
|
+
} else if (typeof descriptionOrCallback === 'object') {
|
|
2496
|
+
options = descriptionOrCallback || {};
|
|
2497
|
+
description = options.description || '';
|
|
2498
|
+
resultCallback = options.onSubmit || null;
|
|
2499
|
+
}
|
|
2500
|
+
|
|
2501
|
+
// Default options
|
|
2502
|
+
const inputOptions = {
|
|
2503
|
+
placeholder: options.placeholder || 'Enter your response...',
|
|
2504
|
+
submitText: options.submitText || 'Submit',
|
|
2505
|
+
cancelText: options.cancelText || 'Cancel',
|
|
2506
|
+
defaultValue: options.defaultValue || '',
|
|
2507
|
+
required: options.required !== false, // default true
|
|
2508
|
+
type: options.type || 'text',
|
|
2509
|
+
validate: options.validate || null,
|
|
2510
|
+
onCancel: options.onCancel || null,
|
|
2511
|
+
theme: options.theme || 'dark',
|
|
2512
|
+
position: options.position || this.defaultOptions.position,
|
|
2513
|
+
overlay: options.overlay !== false, // default true
|
|
2514
|
+
primaryColor: options.primaryColor || null,
|
|
2515
|
+
secondaryColor: options.secondaryColor || null,
|
|
2516
|
+
};
|
|
2517
|
+
|
|
2518
|
+
// Validate input type
|
|
2519
|
+
const validTypes = ['text', 'email', 'number', 'password', 'url', 'tel'];
|
|
2520
|
+
if (!validTypes.includes(inputOptions.type)) {
|
|
2521
|
+
inputOptions.type = 'text';
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2524
|
+
// Create or get container for the specified position
|
|
2525
|
+
let inputContainer;
|
|
2526
|
+
const positionClass = inputOptions.position.replace(' ', '-');
|
|
2527
|
+
const existingContainer = document.querySelector(
|
|
2528
|
+
`.toastify-pro-container.${positionClass}`
|
|
2529
|
+
);
|
|
2530
|
+
|
|
2531
|
+
if (existingContainer) {
|
|
2532
|
+
inputContainer = existingContainer;
|
|
2533
|
+
} else {
|
|
2534
|
+
inputContainer = document.createElement("div");
|
|
2535
|
+
inputContainer.className = `toastify-pro-container ${positionClass}`;
|
|
2536
|
+
document.body.appendChild(inputContainer);
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2539
|
+
// Create overlay if enabled
|
|
2540
|
+
let overlay = null;
|
|
2541
|
+
if (inputOptions.overlay) {
|
|
2542
|
+
overlay = document.createElement("div");
|
|
2543
|
+
overlay.className = "toastify-pro-overlay";
|
|
2544
|
+
document.body.appendChild(overlay);
|
|
2545
|
+
setTimeout(() => overlay.classList.add("visible"), 10);
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2548
|
+
// Create input toast element
|
|
2549
|
+
const toast = document.createElement("div");
|
|
2550
|
+
toast.className = `toastify-pro input-toast ${inputOptions.theme}`;
|
|
2551
|
+
toast.setAttribute('role', 'dialog');
|
|
2552
|
+
toast.setAttribute('aria-modal', 'true');
|
|
2553
|
+
toast.setAttribute('aria-labelledby', 'toast-input-title');
|
|
2554
|
+
|
|
2555
|
+
// Track state
|
|
2556
|
+
let isLoading = false;
|
|
2557
|
+
let isClosed = false;
|
|
2558
|
+
let inputElement = null;
|
|
2559
|
+
let submitBtnElement = null;
|
|
2560
|
+
let cancelBtnElement = null;
|
|
2561
|
+
let errorElement = null;
|
|
2562
|
+
|
|
2563
|
+
// Helper: Check if a color is light or dark
|
|
2564
|
+
const isLightColor = (color) => {
|
|
2565
|
+
if (!color) return false;
|
|
2566
|
+
const hex = color.replace('#', '');
|
|
2567
|
+
if (hex.length === 3) {
|
|
2568
|
+
const r = parseInt(hex[0] + hex[0], 16);
|
|
2569
|
+
const g = parseInt(hex[1] + hex[1], 16);
|
|
2570
|
+
const b = parseInt(hex[2] + hex[2], 16);
|
|
2571
|
+
return (r * 299 + g * 587 + b * 114) / 1000 > 128;
|
|
2572
|
+
}
|
|
2573
|
+
const r = parseInt(hex.substr(0, 2), 16);
|
|
2574
|
+
const g = parseInt(hex.substr(2, 2), 16);
|
|
2575
|
+
const b = parseInt(hex.substr(4, 2), 16);
|
|
2576
|
+
return (r * 299 + g * 587 + b * 114) / 1000 > 128;
|
|
2577
|
+
};
|
|
2578
|
+
|
|
2579
|
+
// Apply custom colors
|
|
2580
|
+
let textColor = inputOptions.theme === 'light' ? '#1e293b' : 'white';
|
|
2581
|
+
if (inputOptions.primaryColor) {
|
|
2582
|
+
const primary = inputOptions.primaryColor;
|
|
2583
|
+
const secondary = inputOptions.secondaryColor;
|
|
2584
|
+
|
|
2585
|
+
if (secondary) {
|
|
2586
|
+
toast.style.background = `linear-gradient(135deg, ${primary} 0%, ${secondary} 100%)`;
|
|
2587
|
+
} else {
|
|
2588
|
+
toast.style.background = `linear-gradient(135deg, ${primary} 0%, ${primary}dd 100%)`;
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
textColor = isLightColor(primary) ? '#1e293b' : 'white';
|
|
2592
|
+
toast.style.color = textColor;
|
|
2593
|
+
|
|
2594
|
+
const borderOpacity = isLightColor(primary) ? '0.2' : '0.15';
|
|
2595
|
+
toast.style.borderColor = `rgba(255, 255, 255, ${borderOpacity})`;
|
|
2596
|
+
}
|
|
2597
|
+
|
|
2598
|
+
// Set loading state
|
|
2599
|
+
const setLoading = (loading) => {
|
|
2600
|
+
isLoading = loading;
|
|
2601
|
+
if (submitBtnElement) {
|
|
2602
|
+
if (loading) {
|
|
2603
|
+
submitBtnElement.classList.add('loading');
|
|
2604
|
+
} else {
|
|
2605
|
+
submitBtnElement.classList.remove('loading');
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
if (cancelBtnElement) {
|
|
2609
|
+
cancelBtnElement.disabled = loading;
|
|
2610
|
+
cancelBtnElement.style.opacity = loading ? '0.5' : '1';
|
|
2611
|
+
cancelBtnElement.style.cursor = loading ? 'not-allowed' : 'pointer';
|
|
2612
|
+
}
|
|
2613
|
+
if (inputElement) {
|
|
2614
|
+
inputElement.disabled = loading;
|
|
2615
|
+
inputElement.style.opacity = loading ? '0.6' : '1';
|
|
2616
|
+
}
|
|
2617
|
+
};
|
|
2618
|
+
|
|
2619
|
+
// Close the input toast
|
|
2620
|
+
const closeInput = () => {
|
|
2621
|
+
if (isClosed) return;
|
|
2622
|
+
isClosed = true;
|
|
2623
|
+
|
|
2624
|
+
// Remove overlay
|
|
2625
|
+
if (overlay) {
|
|
2626
|
+
overlay.classList.remove("visible");
|
|
2627
|
+
setTimeout(() => overlay.remove(), 300);
|
|
2628
|
+
}
|
|
2629
|
+
|
|
2630
|
+
// Exit animation
|
|
2631
|
+
toast.style.pointerEvents = 'none';
|
|
2632
|
+
toast.style.animation = 'carSwipeCenter 0.35s cubic-bezier(0.55, 0.0, 0.85, 0.36) forwards';
|
|
2633
|
+
|
|
2634
|
+
const icon = toast.querySelector('.toast-icon');
|
|
2635
|
+
if (icon) {
|
|
2636
|
+
icon.style.animation = 'iconCarExit 0.35s cubic-bezier(0.55, 0.0, 0.85, 0.36) forwards';
|
|
2637
|
+
}
|
|
2638
|
+
|
|
2639
|
+
setTimeout(() => {
|
|
2640
|
+
if (toast.parentNode) {
|
|
2641
|
+
toast.remove();
|
|
2642
|
+
}
|
|
2643
|
+
}, 350);
|
|
2644
|
+
|
|
2645
|
+
// Restore focus
|
|
2646
|
+
if (previouslyFocused && typeof previouslyFocused.focus === 'function') {
|
|
2647
|
+
setTimeout(() => previouslyFocused.focus(), 100);
|
|
2648
|
+
}
|
|
2649
|
+
|
|
2650
|
+
// Cleanup keyboard handler
|
|
2651
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
2652
|
+
};
|
|
2653
|
+
|
|
2654
|
+
// Validate input
|
|
2655
|
+
const validateInput = (value) => {
|
|
2656
|
+
// Required check
|
|
2657
|
+
if (inputOptions.required && !value.trim()) {
|
|
2658
|
+
return 'This field is required';
|
|
2659
|
+
}
|
|
2660
|
+
|
|
2661
|
+
// Type-specific validation
|
|
2662
|
+
if (value.trim()) {
|
|
2663
|
+
if (inputOptions.type === 'email') {
|
|
2664
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
2665
|
+
if (!emailRegex.test(value)) {
|
|
2666
|
+
return 'Please enter a valid email address';
|
|
2667
|
+
}
|
|
2668
|
+
} else if (inputOptions.type === 'url') {
|
|
2669
|
+
try {
|
|
2670
|
+
new URL(value);
|
|
2671
|
+
} catch {
|
|
2672
|
+
return 'Please enter a valid URL';
|
|
2673
|
+
}
|
|
2674
|
+
} else if (inputOptions.type === 'number') {
|
|
2675
|
+
if (isNaN(Number(value))) {
|
|
2676
|
+
return 'Please enter a valid number';
|
|
2677
|
+
}
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
|
|
2681
|
+
// Custom validation
|
|
2682
|
+
if (inputOptions.validate) {
|
|
2683
|
+
const customResult = inputOptions.validate(value);
|
|
2684
|
+
if (customResult !== true && customResult) {
|
|
2685
|
+
return customResult;
|
|
2686
|
+
}
|
|
2687
|
+
}
|
|
2688
|
+
|
|
2689
|
+
return null; // Valid
|
|
2690
|
+
};
|
|
2691
|
+
|
|
2692
|
+
// Show error message
|
|
2693
|
+
const showError = (message) => {
|
|
2694
|
+
if (errorElement) {
|
|
2695
|
+
errorElement.textContent = message;
|
|
2696
|
+
errorElement.classList.add('visible');
|
|
2697
|
+
inputElement.classList.add('error');
|
|
2698
|
+
}
|
|
2699
|
+
};
|
|
2700
|
+
|
|
2701
|
+
// Clear error message
|
|
2702
|
+
const clearError = () => {
|
|
2703
|
+
if (errorElement) {
|
|
2704
|
+
errorElement.classList.remove('visible');
|
|
2705
|
+
inputElement.classList.remove('error');
|
|
2706
|
+
}
|
|
2707
|
+
};
|
|
2708
|
+
|
|
2709
|
+
// Handle submit
|
|
2710
|
+
const handleSubmit = async () => {
|
|
2711
|
+
if (isLoading || isClosed) return;
|
|
2712
|
+
|
|
2713
|
+
const value = inputElement.value;
|
|
2714
|
+
const error = validateInput(value);
|
|
2715
|
+
|
|
2716
|
+
if (error) {
|
|
2717
|
+
showError(error);
|
|
2718
|
+
inputElement.focus();
|
|
2719
|
+
return;
|
|
2720
|
+
}
|
|
2721
|
+
|
|
2722
|
+
clearError();
|
|
2723
|
+
|
|
2724
|
+
if (resultCallback) {
|
|
2725
|
+
const result = resultCallback(value, { setLoading, close: closeInput, setValue: (v) => inputElement.value = v });
|
|
2726
|
+
|
|
2727
|
+
// Handle async callbacks
|
|
2728
|
+
if (result && typeof result.then === 'function') {
|
|
2729
|
+
setLoading(true);
|
|
2730
|
+
try {
|
|
2731
|
+
await result;
|
|
2732
|
+
if (!isClosed) {
|
|
2733
|
+
closeInput();
|
|
2734
|
+
}
|
|
2735
|
+
} catch (err) {
|
|
2736
|
+
setLoading(false);
|
|
2737
|
+
if (err && typeof err === 'string') {
|
|
2738
|
+
showError(err);
|
|
2739
|
+
} else if (err && err.message) {
|
|
2740
|
+
showError(err.message);
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
} else if (!isLoading) {
|
|
2744
|
+
closeInput();
|
|
2745
|
+
}
|
|
2746
|
+
} else {
|
|
2747
|
+
closeInput();
|
|
2748
|
+
}
|
|
2749
|
+
};
|
|
2750
|
+
|
|
2751
|
+
// Handle cancel
|
|
2752
|
+
const handleCancel = () => {
|
|
2753
|
+
if (isLoading || isClosed) return;
|
|
2754
|
+
|
|
2755
|
+
if (inputOptions.onCancel) {
|
|
2756
|
+
inputOptions.onCancel();
|
|
2757
|
+
}
|
|
2758
|
+
closeInput();
|
|
2759
|
+
};
|
|
2760
|
+
|
|
2761
|
+
// Store previously focused element
|
|
2762
|
+
const previouslyFocused = document.activeElement;
|
|
2763
|
+
|
|
2764
|
+
// Keyboard handler
|
|
2765
|
+
const handleKeyDown = (e) => {
|
|
2766
|
+
if (isClosed) return;
|
|
2767
|
+
|
|
2768
|
+
if (e.key === 'Escape' && !isLoading) {
|
|
2769
|
+
handleCancel();
|
|
2770
|
+
} else if (e.key === 'Enter' && e.target === inputElement && !isLoading) {
|
|
2771
|
+
e.preventDefault();
|
|
2772
|
+
handleSubmit();
|
|
2773
|
+
}
|
|
2774
|
+
};
|
|
2775
|
+
|
|
2776
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
2777
|
+
|
|
2778
|
+
// Build toast content
|
|
2779
|
+
// Header with icon and content
|
|
2780
|
+
const headerWrapper = document.createElement("div");
|
|
2781
|
+
headerWrapper.className = "toast-input-header";
|
|
2782
|
+
|
|
2783
|
+
// Icon
|
|
2784
|
+
const iconWrapper = document.createElement("div");
|
|
2785
|
+
iconWrapper.className = "toast-icon";
|
|
2786
|
+
iconWrapper.setAttribute('aria-hidden', 'true');
|
|
2787
|
+
iconWrapper.innerHTML = `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2788
|
+
<path d="M11 4H4C3.46957 4 2.96086 4.21071 2.58579 4.58579C2.21071 4.96086 2 5.46957 2 6V20C2 20.5304 2.21071 21.0391 2.58579 21.4142C2.96086 21.7893 3.46957 22 4 22H18C18.5304 22 19.0391 21.7893 19.4142 21.4142C19.7893 21.0391 20 20.5304 20 20V13" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
2789
|
+
<path d="M18.5 2.50001C18.8978 2.10219 19.4374 1.87869 20 1.87869C20.5626 1.87869 21.1022 2.10219 21.5 2.50001C21.8978 2.89784 22.1213 3.43739 22.1213 4.00001C22.1213 4.56262 21.8978 5.10219 21.5 5.50001L12 15L8 16L9 12L18.5 2.50001Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
2790
|
+
</svg>`;
|
|
2791
|
+
if (inputOptions.primaryColor) {
|
|
2792
|
+
iconWrapper.style.color = textColor;
|
|
2793
|
+
}
|
|
2794
|
+
headerWrapper.appendChild(iconWrapper);
|
|
2795
|
+
|
|
2796
|
+
// Content wrapper
|
|
2797
|
+
const contentWrapper = document.createElement("div");
|
|
2798
|
+
contentWrapper.className = "toast-content";
|
|
2799
|
+
|
|
2800
|
+
// Message
|
|
2801
|
+
const messageElement = document.createElement("div");
|
|
2802
|
+
messageElement.className = "toast-message";
|
|
2803
|
+
messageElement.id = "toast-input-title";
|
|
2804
|
+
messageElement.textContent = message.substring(0, this.defaultOptions.maxLength);
|
|
2805
|
+
if (inputOptions.primaryColor) {
|
|
2806
|
+
messageElement.style.color = textColor;
|
|
2807
|
+
}
|
|
2808
|
+
contentWrapper.appendChild(messageElement);
|
|
2809
|
+
|
|
2810
|
+
// Description
|
|
2811
|
+
if (description) {
|
|
2812
|
+
const descriptionElement = document.createElement("div");
|
|
2813
|
+
descriptionElement.className = "toast-description";
|
|
2814
|
+
descriptionElement.id = "toast-input-desc";
|
|
2815
|
+
descriptionElement.textContent = description.substring(0, this.defaultOptions.maxLength * 2);
|
|
2816
|
+
if (inputOptions.primaryColor) {
|
|
2817
|
+
descriptionElement.style.color = textColor;
|
|
2818
|
+
}
|
|
2819
|
+
contentWrapper.appendChild(descriptionElement);
|
|
2820
|
+
toast.setAttribute('aria-describedby', 'toast-input-desc');
|
|
2821
|
+
}
|
|
2822
|
+
|
|
2823
|
+
headerWrapper.appendChild(contentWrapper);
|
|
2824
|
+
|
|
2825
|
+
// Input wrapper
|
|
2826
|
+
const inputWrapper = document.createElement("div");
|
|
2827
|
+
inputWrapper.className = "toast-input-wrapper";
|
|
2828
|
+
inputWrapper.appendChild(headerWrapper);
|
|
2829
|
+
|
|
2830
|
+
// Input field
|
|
2831
|
+
inputElement = document.createElement("input");
|
|
2832
|
+
inputElement.className = "toast-input";
|
|
2833
|
+
inputElement.type = inputOptions.type;
|
|
2834
|
+
inputElement.placeholder = inputOptions.placeholder;
|
|
2835
|
+
inputElement.value = inputOptions.defaultValue;
|
|
2836
|
+
inputElement.setAttribute('aria-label', message);
|
|
2837
|
+
|
|
2838
|
+
if (inputOptions.primaryColor) {
|
|
2839
|
+
const isLight = isLightColor(inputOptions.primaryColor);
|
|
2840
|
+
inputElement.style.borderColor = isLight ? 'rgba(15, 23, 42, 0.2)' : 'rgba(255, 255, 255, 0.2)';
|
|
2841
|
+
inputElement.style.background = isLight ? 'rgba(15, 23, 42, 0.06)' : 'rgba(255, 255, 255, 0.08)';
|
|
2842
|
+
inputElement.style.color = textColor;
|
|
2843
|
+
}
|
|
2844
|
+
|
|
2845
|
+
// Clear error on input
|
|
2846
|
+
inputElement.addEventListener('input', () => {
|
|
2847
|
+
if (errorElement && errorElement.classList.contains('visible')) {
|
|
2848
|
+
clearError();
|
|
2849
|
+
}
|
|
2850
|
+
});
|
|
2851
|
+
|
|
2852
|
+
inputWrapper.appendChild(inputElement);
|
|
2853
|
+
|
|
2854
|
+
// Error message element
|
|
2855
|
+
errorElement = document.createElement("div");
|
|
2856
|
+
errorElement.className = "toast-input-error";
|
|
2857
|
+
errorElement.setAttribute('role', 'alert');
|
|
2858
|
+
inputWrapper.appendChild(errorElement);
|
|
2859
|
+
|
|
2860
|
+
// Actions wrapper
|
|
2861
|
+
const actionsWrapper = document.createElement("div");
|
|
2862
|
+
actionsWrapper.className = "toast-input-actions";
|
|
2863
|
+
|
|
2864
|
+
// Cancel button
|
|
2865
|
+
cancelBtnElement = document.createElement("button");
|
|
2866
|
+
cancelBtnElement.className = "input-btn input-btn-cancel";
|
|
2867
|
+
cancelBtnElement.type = "button";
|
|
2868
|
+
cancelBtnElement.textContent = inputOptions.cancelText;
|
|
2869
|
+
cancelBtnElement.onclick = handleCancel;
|
|
2870
|
+
|
|
2871
|
+
if (inputOptions.primaryColor) {
|
|
2872
|
+
const isLight = isLightColor(inputOptions.primaryColor);
|
|
2873
|
+
cancelBtnElement.style.background = isLight ? 'rgba(15, 23, 42, 0.08)' : 'rgba(255, 255, 255, 0.1)';
|
|
2874
|
+
cancelBtnElement.style.color = textColor;
|
|
2875
|
+
cancelBtnElement.style.borderColor = isLight ? 'rgba(15, 23, 42, 0.2)' : 'rgba(255, 255, 255, 0.2)';
|
|
2876
|
+
}
|
|
2877
|
+
|
|
2878
|
+
// Submit button
|
|
2879
|
+
submitBtnElement = document.createElement("button");
|
|
2880
|
+
submitBtnElement.className = "input-btn input-btn-submit";
|
|
2881
|
+
submitBtnElement.type = "button";
|
|
2882
|
+
|
|
2883
|
+
const textWrapper = document.createElement("span");
|
|
2884
|
+
textWrapper.className = "btn-text";
|
|
2885
|
+
textWrapper.textContent = inputOptions.submitText;
|
|
2886
|
+
submitBtnElement.appendChild(textWrapper);
|
|
2887
|
+
|
|
2888
|
+
// Spinner
|
|
2889
|
+
const spinner = document.createElement("span");
|
|
2890
|
+
spinner.className = "btn-spinner";
|
|
2891
|
+
spinner.innerHTML = `<svg width="16" height="16" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2892
|
+
<path d="M9.5 2.9375V5.5625M9.5 13.4375V16.0625M2.9375 9.5H5.5625M13.4375 9.5H16.0625" stroke="currentColor" stroke-width="1.875" stroke-linecap="round" />
|
|
2893
|
+
<path d="M4.86011 4.85961L6.71627 6.71577M12.2847 12.2842L14.1409 14.1404M4.86011 14.1404L6.71627 12.2842M12.2847 6.71577L14.1409 4.85961" stroke="currentColor" stroke-width="1.875" stroke-linecap="round" />
|
|
2894
|
+
</svg>`;
|
|
2895
|
+
submitBtnElement.appendChild(spinner);
|
|
2896
|
+
|
|
2897
|
+
submitBtnElement.onclick = handleSubmit;
|
|
2898
|
+
|
|
2899
|
+
if (inputOptions.primaryColor) {
|
|
2900
|
+
const primary = inputOptions.primaryColor;
|
|
2901
|
+
const isLight = isLightColor(primary);
|
|
2902
|
+
submitBtnElement.style.background = isLight
|
|
2903
|
+
? 'linear-gradient(135deg, #1e293b 0%, #334155 100%)'
|
|
2904
|
+
: 'linear-gradient(135deg, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0.85) 100%)';
|
|
2905
|
+
submitBtnElement.style.color = isLight ? 'white' : '#1e293b';
|
|
2906
|
+
submitBtnElement.style.borderColor = isLight ? 'rgba(15, 23, 42, 0.3)' : 'rgba(255, 255, 255, 0.4)';
|
|
2907
|
+
}
|
|
2908
|
+
|
|
2909
|
+
actionsWrapper.appendChild(cancelBtnElement);
|
|
2910
|
+
actionsWrapper.appendChild(submitBtnElement);
|
|
2911
|
+
inputWrapper.appendChild(actionsWrapper);
|
|
2912
|
+
|
|
2913
|
+
toast.appendChild(inputWrapper);
|
|
2914
|
+
inputContainer.appendChild(toast);
|
|
2915
|
+
|
|
2916
|
+
// Entrance animation
|
|
2917
|
+
setTimeout(() => {
|
|
2918
|
+
toast.classList.add("show");
|
|
2919
|
+
const icon = toast.querySelector('.toast-icon');
|
|
2920
|
+
if (icon) {
|
|
2921
|
+
icon.style.animation = 'iconBounce 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275)';
|
|
2922
|
+
}
|
|
2923
|
+
|
|
2924
|
+
// Focus input after animation
|
|
2925
|
+
setTimeout(() => {
|
|
2926
|
+
inputElement.focus();
|
|
2927
|
+
// Select default value if present
|
|
2928
|
+
if (inputOptions.defaultValue) {
|
|
2929
|
+
inputElement.select();
|
|
2930
|
+
}
|
|
2931
|
+
}, 150);
|
|
2932
|
+
}, 10);
|
|
2933
|
+
|
|
2934
|
+
// Return control object
|
|
2935
|
+
return {
|
|
2936
|
+
element: toast,
|
|
2937
|
+
close: closeInput,
|
|
2938
|
+
setLoading,
|
|
2939
|
+
getValue: () => inputElement.value,
|
|
2940
|
+
setValue: (value) => { inputElement.value = value; },
|
|
2941
|
+
setError: showError,
|
|
2942
|
+
clearError
|
|
2943
|
+
};
|
|
2944
|
+
} catch (error) {
|
|
2945
|
+
console.error('ToastifyPro: Failed to create input toast:', error);
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
|
|
2949
|
+
/**
|
|
2950
|
+
* Alias for input() method - shows an input prompt
|
|
2951
|
+
* @param {string} message - Main prompt question
|
|
2952
|
+
* @param {string|Function|Object} descriptionOrCallback - Description text, callback function, or options object
|
|
2953
|
+
* @param {Function} callback - Callback function (if description provided)
|
|
2954
|
+
*/
|
|
2955
|
+
prompt(message, descriptionOrCallback, callback) {
|
|
2956
|
+
return this.input(message, descriptionOrCallback, callback);
|
|
2957
|
+
}
|
|
2177
2958
|
}
|
|
2178
2959
|
|
|
2179
2960
|
/**
|