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