fernotify 1.2.8 → 1.2.10
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
CHANGED
|
@@ -212,6 +212,79 @@ notify.loading('Cargando...', 'Espera', {
|
|
|
212
212
|
});
|
|
213
213
|
```
|
|
214
214
|
|
|
215
|
+
### Toast — Notificaciones no bloqueantes 🍞
|
|
216
|
+
|
|
217
|
+
Los toasts aparecen en la esquina de la pantalla **sin interrumpir al usuario**, se apilan automáticamente y se cierran solos (o con el botón ×).
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
// Métodos abreviados (mismo patrón que los modales)
|
|
221
|
+
notify.toastSuccess('Cambios guardados.', 'Título opcional');
|
|
222
|
+
notify.toastError('Error al procesar.', 'Error');
|
|
223
|
+
notify.toastWarning('Revisa los datos.');
|
|
224
|
+
notify.toastInfo('Nueva versión disponible.');
|
|
225
|
+
notify.toastQuestion('Nueva solicitud pendiente.');
|
|
226
|
+
|
|
227
|
+
// Método genérico con opciones completas
|
|
228
|
+
notify.toast('Mensaje aquí', {
|
|
229
|
+
type: 'success', // 'success' | 'error' | 'warning' | 'info' | 'question' | 'loading'
|
|
230
|
+
title: 'Título opcional',
|
|
231
|
+
duration: 4000, // ms hasta auto-cierre (0 = sin auto-cierre, default: 4000)
|
|
232
|
+
position: 'top-right', // 'top-right' | 'top-left' | 'top-center' | 'bottom-right' | 'bottom-left'
|
|
233
|
+
id: 'my-toast', // ID para deduplicación (optional)
|
|
234
|
+
closeable: true // false = oculta el botón × (default: true)
|
|
235
|
+
});
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**Características:**
|
|
239
|
+
- Sin overlay — no bloquea la UI
|
|
240
|
+
- Apilables: se acumulan uno bajo otro
|
|
241
|
+
- Progress bar que indica el tiempo restante
|
|
242
|
+
- Botón × para cierre manual
|
|
243
|
+
- Animación de entrada/salida suave
|
|
244
|
+
- Soporte completo de dark mode
|
|
245
|
+
|
|
246
|
+
### Toast de carga 🔄
|
|
247
|
+
|
|
248
|
+
Muestra un toast con spinner para operaciones asíncronas. Solo puede existir uno a la vez y no se puede cerrar manualmente; ciérralo con `closeToastLoading()`.
|
|
249
|
+
|
|
250
|
+
```javascript
|
|
251
|
+
async function fetchData() {
|
|
252
|
+
notify.toastLoading('Obteniendo datos...', 'Cargando');
|
|
253
|
+
|
|
254
|
+
try {
|
|
255
|
+
const res = await fetch('/api/data');
|
|
256
|
+
const data = await res.json();
|
|
257
|
+
notify.closeToastLoading();
|
|
258
|
+
notify.toastSuccess('Datos cargados correctamente');
|
|
259
|
+
} catch {
|
|
260
|
+
notify.closeToastLoading();
|
|
261
|
+
notify.toastError('No se pudieron cargar los datos');
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
fetchData();
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
```javascript
|
|
269
|
+
// Firma completa
|
|
270
|
+
notify.toastLoading(message?, title?, options?)
|
|
271
|
+
notify.closeToastLoading()
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Deduplicación de toasts por ID
|
|
275
|
+
|
|
276
|
+
Asigna un `id` a un toast para evitar duplicados. Si ya hay un toast visible con ese ID, se resetea su cuenta regresiva en lugar de crear uno nuevo.
|
|
277
|
+
|
|
278
|
+
```javascript
|
|
279
|
+
// Aunque el usuario haga clic muchas veces, solo existe un toast
|
|
280
|
+
button.addEventListener('click', () => {
|
|
281
|
+
notify.toastError('Email o contraseña incorrectos', 'Error', {
|
|
282
|
+
id: 'login-error',
|
|
283
|
+
duration: 4000
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
```
|
|
287
|
+
|
|
215
288
|
### Personalización de Animaciones
|
|
216
289
|
|
|
217
290
|
```javascript
|
|
@@ -14,6 +14,17 @@
|
|
|
14
14
|
|
|
15
15
|
// Importar el código UMD y ejecutarlo para generar window.notify
|
|
16
16
|
"use strict";
|
|
17
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
18
|
+
var t = {};
|
|
19
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
20
|
+
t[p] = s[p];
|
|
21
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
22
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
23
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
24
|
+
t[p[i]] = s[p[i]];
|
|
25
|
+
}
|
|
26
|
+
return t;
|
|
27
|
+
};
|
|
17
28
|
(function ensureAnimeDependency() {
|
|
18
29
|
if (typeof anime !== 'undefined') {
|
|
19
30
|
initFerNotify();
|
|
@@ -33,6 +44,8 @@
|
|
|
33
44
|
this.currentNotification = null;
|
|
34
45
|
this._lastActiveElement = null;
|
|
35
46
|
this._currentLoadingPromise = null;
|
|
47
|
+
this._toastContainers = new Map();
|
|
48
|
+
this._toastInstances = new Map();
|
|
36
49
|
this.injectStyles();
|
|
37
50
|
this.loadBoxicons();
|
|
38
51
|
}
|
|
@@ -339,6 +352,152 @@
|
|
|
339
352
|
.dark .notification-loading-text {
|
|
340
353
|
color: #cbd5e1;
|
|
341
354
|
}
|
|
355
|
+
|
|
356
|
+
/* ==================== Toast ==================== */
|
|
357
|
+
.notify-toast-container {
|
|
358
|
+
position: fixed;
|
|
359
|
+
z-index: 10000;
|
|
360
|
+
display: flex;
|
|
361
|
+
flex-direction: column;
|
|
362
|
+
gap: 10px;
|
|
363
|
+
pointer-events: none;
|
|
364
|
+
width: 360px;
|
|
365
|
+
max-width: calc(100vw - 40px);
|
|
366
|
+
}
|
|
367
|
+
.notify-toast-top-right { top: 20px; right: 20px; }
|
|
368
|
+
.notify-toast-top-left { top: 20px; left: 20px; }
|
|
369
|
+
.notify-toast-top-center { top: 20px; left: 50%; transform: translateX(-50%); }
|
|
370
|
+
.notify-toast-bottom-right { bottom: 20px; right: 20px; flex-direction: column-reverse; }
|
|
371
|
+
.notify-toast-bottom-left { bottom: 20px; left: 20px; flex-direction: column-reverse; }
|
|
372
|
+
|
|
373
|
+
.notify-toast {
|
|
374
|
+
background: white;
|
|
375
|
+
border-radius: 12px;
|
|
376
|
+
padding: 14px 40px 14px 14px;
|
|
377
|
+
box-shadow: 0 4px 24px rgba(0,0,0,0.12), 0 1px 4px rgba(0,0,0,0.06);
|
|
378
|
+
display: flex;
|
|
379
|
+
align-items: flex-start;
|
|
380
|
+
gap: 12px;
|
|
381
|
+
pointer-events: auto;
|
|
382
|
+
position: relative;
|
|
383
|
+
overflow: hidden;
|
|
384
|
+
opacity: 0;
|
|
385
|
+
transform: translateX(30px);
|
|
386
|
+
transition: opacity 0.25s ease, transform 0.25s ease;
|
|
387
|
+
}
|
|
388
|
+
.notify-toast-top-left .notify-toast,
|
|
389
|
+
.notify-toast-bottom-left .notify-toast { transform: translateX(-30px); }
|
|
390
|
+
.notify-toast-top-center .notify-toast { transform: translateY(-20px); }
|
|
391
|
+
.notify-toast.notify-toast-visible {
|
|
392
|
+
opacity: 1;
|
|
393
|
+
transform: translateX(0) translateY(0) !important;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.notify-toast-icon {
|
|
397
|
+
width: 36px;
|
|
398
|
+
height: 36px;
|
|
399
|
+
border-radius: 50%;
|
|
400
|
+
display: flex;
|
|
401
|
+
align-items: center;
|
|
402
|
+
justify-content: center;
|
|
403
|
+
font-size: 20px;
|
|
404
|
+
flex-shrink: 0;
|
|
405
|
+
color: white;
|
|
406
|
+
}
|
|
407
|
+
.notify-toast-icon.success { background: linear-gradient(135deg, #10b981 0%, #059669 100%); }
|
|
408
|
+
.notify-toast-icon.error { background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); }
|
|
409
|
+
.notify-toast-icon.warning { background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); }
|
|
410
|
+
.notify-toast-icon.info { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); }
|
|
411
|
+
.notify-toast-icon.question { background: linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%); }
|
|
412
|
+
.notify-toast-icon.loading { background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%); }
|
|
413
|
+
|
|
414
|
+
.notify-toast-content { flex: 1; min-width: 0; }
|
|
415
|
+
.notify-toast-title {
|
|
416
|
+
font-size: 14px;
|
|
417
|
+
font-weight: 700;
|
|
418
|
+
color: #1f2937;
|
|
419
|
+
margin-bottom: 2px;
|
|
420
|
+
line-height: 1.3;
|
|
421
|
+
cursor: default;
|
|
422
|
+
}
|
|
423
|
+
.notify-toast-message {
|
|
424
|
+
font-size: 13px;
|
|
425
|
+
color: #6b7280;
|
|
426
|
+
line-height: 1.5;
|
|
427
|
+
cursor: default;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.notify-toast-close {
|
|
431
|
+
position: absolute;
|
|
432
|
+
top: 8px;
|
|
433
|
+
right: 8px;
|
|
434
|
+
width: 24px;
|
|
435
|
+
height: 24px;
|
|
436
|
+
border-radius: 6px;
|
|
437
|
+
border: none;
|
|
438
|
+
background: rgba(0,0,0,0.06);
|
|
439
|
+
color: #6b7280;
|
|
440
|
+
cursor: pointer;
|
|
441
|
+
font-size: 16px;
|
|
442
|
+
display: flex;
|
|
443
|
+
align-items: center;
|
|
444
|
+
justify-content: center;
|
|
445
|
+
line-height: 1;
|
|
446
|
+
padding: 0;
|
|
447
|
+
}
|
|
448
|
+
.notify-toast-close:hover { background: rgba(0,0,0,0.1); color: #374151; }
|
|
449
|
+
|
|
450
|
+
/* Sin botón de cierre: reducir padding derecho */
|
|
451
|
+
.notify-toast.notify-toast-no-close { padding-right: 14px; }
|
|
452
|
+
|
|
453
|
+
.notify-toast-progress {
|
|
454
|
+
position: absolute;
|
|
455
|
+
bottom: 0;
|
|
456
|
+
left: 0;
|
|
457
|
+
height: 3px;
|
|
458
|
+
width: 100%;
|
|
459
|
+
border-radius: 0 0 0 12px;
|
|
460
|
+
}
|
|
461
|
+
.notify-toast-progress.success { background: #10b981; }
|
|
462
|
+
.notify-toast-progress.error { background: #ef4444; }
|
|
463
|
+
.notify-toast-progress.warning { background: #f59e0b; }
|
|
464
|
+
.notify-toast-progress.info { background: #3b82f6; }
|
|
465
|
+
.notify-toast-progress.question { background: #8b5cf6; }
|
|
466
|
+
.notify-toast-progress.loading { background: #6366f1; }
|
|
467
|
+
|
|
468
|
+
/* Spinner para toast de carga */
|
|
469
|
+
.notify-toast-spinner {
|
|
470
|
+
width: 18px;
|
|
471
|
+
height: 18px;
|
|
472
|
+
border: 2.5px solid rgba(255,255,255,0.35);
|
|
473
|
+
border-top-color: white;
|
|
474
|
+
border-radius: 50%;
|
|
475
|
+
animation: notification-spin 0.8s linear infinite;
|
|
476
|
+
flex-shrink: 0;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
.dark .notify-toast { background: #0f1724; box-shadow: 0 4px 24px rgba(0,0,0,0.35); }
|
|
480
|
+
.dark .notify-toast-title { color: #e6eef8; }
|
|
481
|
+
.dark .notify-toast-message { color: #cbd5e1; }
|
|
482
|
+
.dark .notify-toast-close { background: rgba(255,255,255,0.06); color: #94a3b8; }
|
|
483
|
+
.dark .notify-toast-close:hover { background: rgba(255,255,255,0.1); color: #e2e8f0; }
|
|
484
|
+
|
|
485
|
+
/* Respeta la preferencia de movimiento reducido del sistema */
|
|
486
|
+
@media (prefers-reduced-motion: reduce) {
|
|
487
|
+
.notify-toast {
|
|
488
|
+
transition: opacity 0.1s ease !important;
|
|
489
|
+
transform: none !important;
|
|
490
|
+
}
|
|
491
|
+
.notify-toast.notify-toast-visible {
|
|
492
|
+
transform: none !important;
|
|
493
|
+
}
|
|
494
|
+
.notify-toast-spinner {
|
|
495
|
+
animation-duration: 1.5s !important;
|
|
496
|
+
}
|
|
497
|
+
.notify-toast-progress {
|
|
498
|
+
transition: none !important;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
342
501
|
`;
|
|
343
502
|
document.head.appendChild(style);
|
|
344
503
|
}
|
|
@@ -348,7 +507,8 @@
|
|
|
348
507
|
'error': '<i class="bx bx-x" aria-hidden="true"></i>',
|
|
349
508
|
'warning': '<i class="bx bx-error" aria-hidden="true"></i>',
|
|
350
509
|
'info': '<i class="bx bx-info-circle" aria-hidden="true"></i>',
|
|
351
|
-
'question': '<i class="bx bx-question-mark" aria-hidden="true"></i>'
|
|
510
|
+
'question': '<i class="bx bx-question-mark" aria-hidden="true"></i>',
|
|
511
|
+
'loading': '<div class="notify-toast-spinner" aria-hidden="true"></div>'
|
|
352
512
|
};
|
|
353
513
|
return icons[type] || icons.info;
|
|
354
514
|
}
|
|
@@ -845,6 +1005,252 @@
|
|
|
845
1005
|
const ss = (s % 60).toString().padStart(2, '0');
|
|
846
1006
|
return `${mm}:${ss}`;
|
|
847
1007
|
}
|
|
1008
|
+
showToast(message, options = {}) {
|
|
1009
|
+
var _a, _b;
|
|
1010
|
+
const type = options.type || 'info';
|
|
1011
|
+
const title = (_a = options.title) !== null && _a !== void 0 ? _a : null;
|
|
1012
|
+
const duration = typeof options.duration === 'number' ? options.duration : 4000;
|
|
1013
|
+
const position = options.position || 'top-right';
|
|
1014
|
+
const showProgress = options.showProgress !== false;
|
|
1015
|
+
const toastId = (_b = options.id) !== null && _b !== void 0 ? _b : null;
|
|
1016
|
+
const closeable = options.closeable !== false;
|
|
1017
|
+
// Deduplicación: si ya existe un toast con este ID, resetear su cuenta regresiva
|
|
1018
|
+
if (toastId !== null) {
|
|
1019
|
+
const existing = this._toastInstances.get(toastId);
|
|
1020
|
+
if (existing) {
|
|
1021
|
+
existing.reset(duration);
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
let container = this._toastContainers.get(position);
|
|
1026
|
+
if (!container || !document.body.contains(container)) {
|
|
1027
|
+
container = document.createElement('div');
|
|
1028
|
+
container.className = `notify-toast-container notify-toast-${position}`;
|
|
1029
|
+
container.setAttribute('aria-label', 'Notificaciones');
|
|
1030
|
+
document.body.appendChild(container);
|
|
1031
|
+
this._toastContainers.set(position, container);
|
|
1032
|
+
}
|
|
1033
|
+
const isBottom = position.startsWith('bottom');
|
|
1034
|
+
const isCenter = position === 'top-center';
|
|
1035
|
+
const toast = document.createElement('div');
|
|
1036
|
+
toast.className = 'notify-toast';
|
|
1037
|
+
if (!closeable) {
|
|
1038
|
+
toast.classList.add('notify-toast-no-close');
|
|
1039
|
+
}
|
|
1040
|
+
// Accesibilidad: role + aria-live según la urgencia del tipo
|
|
1041
|
+
// role="alert" implica aria-live="assertive" + aria-atomic="true" → lector lo interrumpe
|
|
1042
|
+
// role="status" implica aria-live="polite" + aria-atomic="true" → lector espera pausa
|
|
1043
|
+
if (type === 'error' || type === 'warning') {
|
|
1044
|
+
toast.setAttribute('role', 'alert');
|
|
1045
|
+
}
|
|
1046
|
+
else {
|
|
1047
|
+
toast.setAttribute('role', 'status');
|
|
1048
|
+
}
|
|
1049
|
+
toast.setAttribute('aria-atomic', 'true');
|
|
1050
|
+
toast.setAttribute('aria-live', type === 'error' || type === 'warning' ? 'assertive' : 'polite');
|
|
1051
|
+
const iconEl = document.createElement('div');
|
|
1052
|
+
iconEl.className = `notify-toast-icon ${type}`;
|
|
1053
|
+
iconEl.innerHTML = this.getIcon(type);
|
|
1054
|
+
const contentEl = document.createElement('div');
|
|
1055
|
+
contentEl.className = 'notify-toast-content';
|
|
1056
|
+
if (title) {
|
|
1057
|
+
const titleEl = document.createElement('div');
|
|
1058
|
+
titleEl.className = 'notify-toast-title';
|
|
1059
|
+
titleEl.textContent = title;
|
|
1060
|
+
contentEl.appendChild(titleEl);
|
|
1061
|
+
}
|
|
1062
|
+
const msgEl = document.createElement('div');
|
|
1063
|
+
msgEl.className = 'notify-toast-message';
|
|
1064
|
+
msgEl.textContent = message;
|
|
1065
|
+
contentEl.appendChild(msgEl);
|
|
1066
|
+
toast.appendChild(iconEl);
|
|
1067
|
+
toast.appendChild(contentEl);
|
|
1068
|
+
if (closeable) {
|
|
1069
|
+
const closeBtn = document.createElement('button');
|
|
1070
|
+
closeBtn.className = 'notify-toast-close';
|
|
1071
|
+
closeBtn.setAttribute('aria-label', 'Cerrar notificación');
|
|
1072
|
+
closeBtn.innerHTML = '×';
|
|
1073
|
+
closeBtn.addEventListener('click', removeToast);
|
|
1074
|
+
toast.appendChild(closeBtn);
|
|
1075
|
+
}
|
|
1076
|
+
let progressEl = null;
|
|
1077
|
+
if (duration > 0 && showProgress) {
|
|
1078
|
+
progressEl = document.createElement('div');
|
|
1079
|
+
progressEl.className = `notify-toast-progress ${type}`;
|
|
1080
|
+
progressEl.setAttribute('role', 'progressbar');
|
|
1081
|
+
progressEl.setAttribute('aria-hidden', 'true'); // decorativo: el timer no añade info que el usuario necesite leer
|
|
1082
|
+
toast.appendChild(progressEl);
|
|
1083
|
+
}
|
|
1084
|
+
if (isBottom || isCenter) {
|
|
1085
|
+
container.appendChild(toast);
|
|
1086
|
+
}
|
|
1087
|
+
else {
|
|
1088
|
+
container.insertBefore(toast, container.firstChild);
|
|
1089
|
+
}
|
|
1090
|
+
let dismissed = false;
|
|
1091
|
+
let timerId = null;
|
|
1092
|
+
let remaining = duration;
|
|
1093
|
+
let timerStartedAt = 0;
|
|
1094
|
+
function removeToast() {
|
|
1095
|
+
if (dismissed)
|
|
1096
|
+
return Promise.resolve();
|
|
1097
|
+
dismissed = true;
|
|
1098
|
+
// Si el foco estaba dentro del toast, sacarlo antes de que el nodo desaparezca
|
|
1099
|
+
// para evitar que el foco se pierda silenciosamente en el documento
|
|
1100
|
+
if (toast.contains(document.activeElement)) {
|
|
1101
|
+
try {
|
|
1102
|
+
document.activeElement.blur();
|
|
1103
|
+
}
|
|
1104
|
+
catch (e) { }
|
|
1105
|
+
}
|
|
1106
|
+
toast.classList.remove('notify-toast-visible');
|
|
1107
|
+
return new Promise(resolve => {
|
|
1108
|
+
setTimeout(() => {
|
|
1109
|
+
if (toast.parentNode)
|
|
1110
|
+
toast.parentNode.removeChild(toast);
|
|
1111
|
+
resolve();
|
|
1112
|
+
}, 300);
|
|
1113
|
+
});
|
|
1114
|
+
}
|
|
1115
|
+
const startCountdown = (ms) => {
|
|
1116
|
+
timerStartedAt = Date.now();
|
|
1117
|
+
timerId = setTimeout(() => {
|
|
1118
|
+
if (toastId !== null)
|
|
1119
|
+
this._toastInstances.delete(toastId);
|
|
1120
|
+
removeToast();
|
|
1121
|
+
}, ms);
|
|
1122
|
+
if (progressEl) {
|
|
1123
|
+
progressEl.style.transition = `width ${ms}ms linear`;
|
|
1124
|
+
progressEl.style.width = '0%';
|
|
1125
|
+
}
|
|
1126
|
+
};
|
|
1127
|
+
const pauseCountdown = () => {
|
|
1128
|
+
if (dismissed || timerId === null)
|
|
1129
|
+
return;
|
|
1130
|
+
clearTimeout(timerId);
|
|
1131
|
+
timerId = null;
|
|
1132
|
+
const elapsed = Date.now() - timerStartedAt;
|
|
1133
|
+
remaining = Math.max(0, remaining - elapsed);
|
|
1134
|
+
if (progressEl) {
|
|
1135
|
+
const pct = (remaining / duration) * 100;
|
|
1136
|
+
progressEl.style.transition = 'none';
|
|
1137
|
+
progressEl.style.width = `${pct}%`;
|
|
1138
|
+
}
|
|
1139
|
+
};
|
|
1140
|
+
const resumeCountdown = () => {
|
|
1141
|
+
if (dismissed || remaining <= 0)
|
|
1142
|
+
return;
|
|
1143
|
+
startCountdown(remaining);
|
|
1144
|
+
};
|
|
1145
|
+
const resetCountdown = (newDuration) => {
|
|
1146
|
+
if (dismissed)
|
|
1147
|
+
return;
|
|
1148
|
+
if (timerId !== null) {
|
|
1149
|
+
clearTimeout(timerId);
|
|
1150
|
+
timerId = null;
|
|
1151
|
+
}
|
|
1152
|
+
remaining = newDuration;
|
|
1153
|
+
if (newDuration > 0) {
|
|
1154
|
+
if (progressEl) {
|
|
1155
|
+
progressEl.style.transition = 'none';
|
|
1156
|
+
progressEl.style.width = '100%';
|
|
1157
|
+
// Forzar reflow para que la transición se aplique desde el inicio
|
|
1158
|
+
void progressEl.offsetWidth;
|
|
1159
|
+
}
|
|
1160
|
+
startCountdown(newDuration);
|
|
1161
|
+
}
|
|
1162
|
+
else if (progressEl) {
|
|
1163
|
+
progressEl.style.transition = 'none';
|
|
1164
|
+
progressEl.style.width = '100%';
|
|
1165
|
+
}
|
|
1166
|
+
};
|
|
1167
|
+
if (toastId !== null) {
|
|
1168
|
+
const silentDismiss = () => {
|
|
1169
|
+
if (dismissed)
|
|
1170
|
+
return;
|
|
1171
|
+
dismissed = true;
|
|
1172
|
+
if (timerId !== null)
|
|
1173
|
+
clearTimeout(timerId);
|
|
1174
|
+
if (toast.contains(document.activeElement)) {
|
|
1175
|
+
try {
|
|
1176
|
+
document.activeElement.blur();
|
|
1177
|
+
}
|
|
1178
|
+
catch (e) { }
|
|
1179
|
+
}
|
|
1180
|
+
if (toast.parentNode)
|
|
1181
|
+
toast.parentNode.removeChild(toast);
|
|
1182
|
+
};
|
|
1183
|
+
this._toastInstances.set(toastId, { reset: resetCountdown, dismiss: removeToast, _silentDismiss: silentDismiss });
|
|
1184
|
+
}
|
|
1185
|
+
requestAnimationFrame(() => {
|
|
1186
|
+
requestAnimationFrame(() => {
|
|
1187
|
+
toast.classList.add('notify-toast-visible');
|
|
1188
|
+
if (duration > 0) {
|
|
1189
|
+
startCountdown(duration);
|
|
1190
|
+
}
|
|
1191
|
+
});
|
|
1192
|
+
});
|
|
1193
|
+
if (duration > 0 && closeable) {
|
|
1194
|
+
toast.addEventListener('mouseenter', pauseCountdown);
|
|
1195
|
+
toast.addEventListener('mouseleave', resumeCountdown);
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
1198
|
+
toast(messageOrOptions, options = {}) {
|
|
1199
|
+
if (typeof messageOrOptions === 'string') {
|
|
1200
|
+
this.showToast(messageOrOptions, options);
|
|
1201
|
+
}
|
|
1202
|
+
else {
|
|
1203
|
+
const { message = '' } = messageOrOptions, rest = __rest(messageOrOptions, ["message"]);
|
|
1204
|
+
this.showToast(message, rest);
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
toastSuccess(message, title, options = {}) {
|
|
1208
|
+
this.showToast(message, Object.assign(Object.assign({}, options), { type: 'success', title: title !== null && title !== void 0 ? title : options.title }));
|
|
1209
|
+
}
|
|
1210
|
+
toastError(message, title, options = {}) {
|
|
1211
|
+
this.showToast(message, Object.assign(Object.assign({}, options), { type: 'error', title: title !== null && title !== void 0 ? title : options.title }));
|
|
1212
|
+
}
|
|
1213
|
+
toastWarning(message, title, options = {}) {
|
|
1214
|
+
this.showToast(message, Object.assign(Object.assign({}, options), { type: 'warning', title: title !== null && title !== void 0 ? title : options.title }));
|
|
1215
|
+
}
|
|
1216
|
+
toastInfo(message, title, options = {}) {
|
|
1217
|
+
this.showToast(message, Object.assign(Object.assign({}, options), { type: 'info', title: title !== null && title !== void 0 ? title : options.title }));
|
|
1218
|
+
}
|
|
1219
|
+
toastQuestion(message, title, options = {}) {
|
|
1220
|
+
this.showToast(message, Object.assign(Object.assign({}, options), { type: 'question', title: title !== null && title !== void 0 ? title : options.title }));
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* Muestra un toast de carga con spinner.
|
|
1224
|
+
* - No se puede cerrar manualmente (closeable: false por defecto).
|
|
1225
|
+
* - No tiene cuenta regresiva (duration: 0 por defecto).
|
|
1226
|
+
* - Solo puede existir uno a la vez (id '__loading__').
|
|
1227
|
+
* Ciérralo con notify.closeToastLoading().
|
|
1228
|
+
*/
|
|
1229
|
+
toastLoading(message = 'Cargando...', title, options = {}) {
|
|
1230
|
+
this.showToast(message, Object.assign(Object.assign({ position: 'top-right' }, options), { type: 'loading', title: title !== null && title !== void 0 ? title : options.title, id: '__loading__', closeable: false, duration: 0, showProgress: false }));
|
|
1231
|
+
}
|
|
1232
|
+
/** Cierra el toast de carga activo (si existe). Devuelve una Promise que resuelve cuando la animación de salida termina (≈300 ms). */
|
|
1233
|
+
closeToastLoading() {
|
|
1234
|
+
const entry = this._toastInstances.get('__loading__');
|
|
1235
|
+
if (entry) {
|
|
1236
|
+
this._toastInstances.delete('__loading__');
|
|
1237
|
+
return entry.dismiss();
|
|
1238
|
+
}
|
|
1239
|
+
return Promise.resolve();
|
|
1240
|
+
}
|
|
1241
|
+
/**
|
|
1242
|
+
* Reemplaza el toast de carga activo por un toast de resultado en el mismo lugar,
|
|
1243
|
+
* sin animación de salida/entrada — no hay solapamiento ni hueco visual.
|
|
1244
|
+
* Si no existe un toast de carga activo, simplemente muestra un toast normal.
|
|
1245
|
+
*/
|
|
1246
|
+
replaceToastLoading(message, options = {}) {
|
|
1247
|
+
const entry = this._toastInstances.get('__loading__');
|
|
1248
|
+
if (entry) {
|
|
1249
|
+
this._toastInstances.delete('__loading__');
|
|
1250
|
+
entry._silentDismiss();
|
|
1251
|
+
}
|
|
1252
|
+
this.showToast(message, options);
|
|
1253
|
+
}
|
|
848
1254
|
}
|
|
849
1255
|
const notifyInstance = new NotificationSystem();
|
|
850
1256
|
const w = window;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";!function(){if("undefined"!=typeof anime)n();else{const t=document.createElement("script");t.src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js",t.onload=n,t.onerror=()=>{console.error("FerNotify: No se pudo cargar anime.js. Por favor, cargalo manualmente.")},document.head.appendChild(t)}function n(){const n=new class{constructor(){this.currentNotification=null,this._lastActiveElement=null,this._currentLoadingPromise=null,this.injectStyles(),this.loadBoxicons()}loadBoxicons(){if(!document.querySelector('link[href*="boxicons"]')){const n=document.createElement("link");n.rel="stylesheet",n.href="https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css",document.head.appendChild(n)}}injectStyles(){const n=document.createElement("style");n.textContent="\n .notification-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 9999;\n opacity: 0;\n overflow: hidden;\n }\n\n .notification-box {\n background: white;\n border-radius: 16px;\n padding: 40px 30px;\n max-width: 500px;\n width: 90%;\n max-height: 80vh;\n overflow: auto;\n position: relative;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n text-align: center;\n transform: scale(0.7);\n opacity: 0;\n }\n\n .notification-content {\n text-align: left;\n margin-bottom: 18px;\n }\n\n .notification-close {\n position: absolute;\n top: 10px;\n right: 10px;\n width: 38px;\n height: 38px;\n border-radius: 8px;\n border: none;\n background: rgba(0,0,0,0.06);\n color: #111827;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 18px;\n }\n\n .notification-close:hover {\n background: rgba(0,0,0,0.09);\n }\n\n /* Form controls inside the modal */\n .notification-box input,\n .notification-box textarea,\n .notification-box select {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n background: #ffffff;\n color: #111827;\n font-size: 15px;\n box-sizing: border-box;\n transition: box-shadow 0.15s ease, border-color 0.15s ease;\n }\n\n .notification-box input:focus,\n .notification-box textarea:focus,\n .notification-box select:focus {\n outline: none;\n border-color: #6366f1;\n box-shadow: 0 6px 24px rgba(99,102,241,0.12), 0 0 0 4px rgba(99,102,241,0.06);\n }\n\n .notification-box label { display: block; margin-bottom: 6px; color: #374151; font-weight: 600; }\n\n /* Soporte para tema oscuro con clase .dark (Tailwind darkMode: 'class') */\n /* Esto tiene prioridad sobre prefers-color-scheme para respetar la elección del usuario en la web */\n .dark .notification-box { background: #0f1724 !important; color: #e6eef8 !important; }\n .dark .notification-box input,\n .dark .notification-box textarea,\n .dark .notification-box select {\n background: #0b1220 !important;\n border: 1px solid rgba(255,255,255,0.06) !important;\n color: #e6eef8 !important;\n }\n .dark .notification-box .notification-close { background: rgba(255,255,255,0.03) !important; color: #e6eef8 !important; }\n .dark .notification-overlay { background-color: rgba(0,0,0,0.6) !important; }\n .dark .notification-title { color: #e6eef8 !important; }\n .dark .notification-message { color: #cbd5e1 !important; }\n\n /* Forzar modo claro cuando NO hay clase .dark, ignorando prefers-color-scheme */\n html:not(.dark) .notification-box { background: white !important; color: #111827 !important; }\n html:not(.dark) .notification-box input,\n html:not(.dark) .notification-box textarea,\n html:not(.dark) .notification-box select {\n background: #ffffff !important;\n border: 1px solid #e5e7eb !important;\n color: #111827 !important;\n }\n html:not(.dark) .notification-box .notification-close { background: rgba(0,0,0,0.06) !important; color: #111827 !important; }\n html:not(.dark) .notification-overlay { background-color: rgba(0, 0, 0, 0.4) !important; }\n html:not(.dark) .notification-title { color: #1f2937 !important; }\n html:not(.dark) .notification-message { color: #6b7280 !important; }\n\n .notification-icon {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n margin: 0 auto 25px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 40px;\n position: relative;\n }\n\n .notification-icon::before {\n content: '';\n position: absolute;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n opacity: 0.2;\n }\n\n .notification-icon.success {\n background: linear-gradient(135deg, #10b981 0%, #059669 100%);\n color: white;\n }\n\n .notification-icon.success::before {\n background: #10b981;\n }\n\n .notification-icon.error {\n background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);\n color: white;\n }\n\n .notification-icon.error::before {\n background: #ef4444;\n }\n\n .notification-icon.warning {\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n color: white;\n }\n\n .notification-icon.warning::before {\n background: #f59e0b;\n }\n\n .notification-icon.info {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: white;\n }\n\n .notification-icon.info::before {\n background: #3b82f6;\n }\n .notification-icon.question {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: white;\n }\n\n .notification-icon.question::before {\n background: #3b82f6;\n }\n\n .notification-title {\n font-size: 24px;\n font-weight: 700;\n color: #1f2937;\n margin-bottom: 12px;\n line-height: 1.3;\n }\n\n .notification-message {\n font-size: 16px;\n color: #6b7280;\n line-height: 1.6;\n margin-bottom: 30px;\n }\n\n .notification-button {\n color: white;\n border: none;\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 16px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n }\n\n .notification-button:hover {\n transform: translateY(-2px);\n filter: brightness(1.1);\n }\n\n .notification-button:active {\n transform: translateY(0);\n }\n\n /* group container for multiple action buttons */\n .notification-button-group {\n display: flex;\n gap: 12px;\n justify-content: center;\n flex-wrap: wrap;\n margin-top: 10px;\n }\n\n .notification-icon-checkmark {\n animation: checkmark-draw 0.6s ease-in-out;\n }\n\n .notification-icon-cross {\n animation: cross-draw 0.5s ease-in-out;\n }\n\n @keyframes checkmark-draw {\n 0% {\n transform: scale(0) rotate(-45deg);\n opacity: 0;\n }\n 50% {\n transform: scale(1.2) rotate(-45deg);\n }\n 100% {\n transform: scale(1) rotate(0deg);\n opacity: 1;\n }\n }\n\n @keyframes cross-draw {\n 0% {\n transform: scale(0) rotate(-180deg);\n opacity: 0;\n }\n 50% {\n transform: scale(1.2) rotate(-90deg);\n }\n 100% {\n transform: scale(1) rotate(0deg);\n opacity: 1;\n }\n }\n\n /* Loading spinner styles */\n .notification-loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n margin: 0 auto;\n }\n\n .notification-spinner {\n width: 60px;\n height: 60px;\n border: 5px solid rgba(99, 102, 241, 0.15);\n border-top-color: #6366f1;\n border-radius: 50%;\n animation: notification-spin 1s linear infinite;\n margin: 0 auto;\n }\n\n @keyframes notification-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n .notification-loading-text {\n font-size: 14px;\n color: #6b7280;\n text-align: center;\n margin-top: 12px;\n }\n\n .dark .notification-loading-text {\n color: #cbd5e1;\n }\n ",document.head.appendChild(n)}getIcon(n){const t={success:'<i class="bx bx-check" aria-hidden="true"></i>',error:'<i class="bx bx-x" aria-hidden="true"></i>',warning:'<i class="bx bx-error" aria-hidden="true"></i>',info:'<i class="bx bx-info-circle" aria-hidden="true"></i>',question:'<i class="bx bx-question-mark" aria-hidden="true"></i>'};return t[n]||t.info}getDefaultTitle(n){return{success:"¡Éxito!",error:"Error",warning:"Advertencia",info:"Información",question:"Pregunta"}[n]||"Notificación"}getButtonGradient(n){const t={success:"linear-gradient(135deg, #10b981 0%, #059669 100%)",error:"linear-gradient(135deg, #ef4444 0%, #dc2626 100%)",warning:"linear-gradient(135deg, #f59e0b 0%, #d97706 100%)",info:"linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)",question:"linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)"};return t[n]||t.info}getButtonShadow(n){const t={success:"rgba(16, 185, 129, 0)",error:"rgba(239, 68, 68, 0)",warning:"rgba(245, 159, 11, 0)",info:"rgba(59, 131, 246, 0)",question:"rgba(108, 99, 245, 0)"};return t[n]||t.info}show(n={}){if(this.currentNotification){const n=this.currentNotification;this.currentNotification=null;try{n&&n.parentNode&&n.parentNode.removeChild(n)}catch(n){}}const{type:t="info",title:e=this.getDefaultTitle(t),message:o="",buttonText:i="OK",buttonColor:a=null,onClose:r=null,timer:c=null,allowOutsideClick:s=!0,allowEscapeKey:l=!0,hideButton:d=!1,buttons:u=null}=n,f=!0===n.showCloseButton;try{document.body.style.overflow="hidden"}catch(n){}try{document.documentElement.style.overflow="hidden"}catch(n){}const p=document.createElement("div");p.className="notification-overlay",p.tabIndex=-1,p.setAttribute("role","dialog"),p.setAttribute("aria-modal","true"),p.style.pointerEvents="auto";const m=document.createElement("div");m.className="notification-box";const b=document.createElement("div");b.className=`notification-icon ${t}`,d&&"info"===t?(b.className="notification-loading-container",b.innerHTML='<div class="notification-spinner"></div>',b.style.background="transparent",b.style.boxShadow="none",b.style.width="100px",b.style.height="100px"):b.innerHTML=this.getIcon(t);const h=document.createElement("h3");h.className="notification-title",h.textContent=e;const g=document.createElement("p");g.className="notification-message",g.textContent=o;let x=null;if(n.html||n.content)if(x=document.createElement("div"),x.className="notification-content",n.html)try{x.innerHTML=n.html}catch(t){x.textContent=n.html}else n.content&&n.content instanceof HTMLElement&&x.appendChild(n.content);const y=()=>this.close(r);let w=null,v=null;if(!d)if(Array.isArray(u)&&u.length)v=document.createElement("div"),v.className="notification-button-group",u.forEach(n=>{const e=document.createElement("button");e.className="notification-button",e.textContent=n.text||"OK";const o=n.color||this.getButtonGradient(t),i=n.shadowColor||this.getButtonShadow(t);e.style.background=o,e.style.boxShadow=`0 4px 12px ${i}`,e.addEventListener("click",t=>{t.stopPropagation(),t.preventDefault();try{y().then(()=>{if("function"==typeof n.onClick)try{const t=n.onClick();t&&"function"==typeof t.then&&t.catch(n=>console.error(n))}catch(n){console.error(n)}}).catch(()=>{})}catch(n){console.error(n)}}),e.addEventListener("mouseenter",()=>{e.style.boxShadow=`0 6px 16px ${i}`}),e.addEventListener("mouseleave",()=>{e.style.boxShadow=`0 4px 12px ${i}`}),v.appendChild(e)});else if(n.onConfirm||n.onCancel||n.confirmText||n.cancelText){v=document.createElement("div"),v.className="notification-button-group";const e=n.cancelText||"Cancelar",o=n.confirmText||"Aceptar",i=document.createElement("button");i.className="notification-button",i.textContent=e;const a=n.cancelColor||"linear-gradient(135deg, #9ca3af 0%, #6b7280 100%)",r=n.cancelShadow||"rgba(107,114,128,0.25)";i.style.background=a,i.style.boxShadow=`0 4px 12px ${r}`,i.addEventListener("click",t=>{t.stopPropagation(),t.preventDefault(),y().then(()=>{try{if("function"==typeof n.onCancel){const t=n.onCancel();t&&"function"==typeof t.then&&t.catch(n=>console.error(n))}}catch(n){console.error(n)}}).catch(()=>{})}),i.addEventListener("mouseenter",()=>{i.style.boxShadow=`0 6px 16px ${r}`}),i.addEventListener("mouseleave",()=>{i.style.boxShadow=`0 4px 12px ${r}`});const c=document.createElement("button");c.className="notification-button",c.textContent=o;const s=n.confirmColor||this.getButtonGradient(t),l=n.confirmShadow||this.getButtonShadow(t);c.style.background=s,c.style.boxShadow=`0 4px 12px ${l}`,c.addEventListener("click",async t=>{t.stopPropagation(),t.preventDefault();try{if(await y(),"function"==typeof n.onConfirm){const t=n.onConfirm();t&&"function"==typeof t.then&&await t}}catch(n){console.error(n)}}),c.addEventListener("mouseenter",()=>{c.style.boxShadow=`0 6px 16px ${l}`}),c.addEventListener("mouseleave",()=>{c.style.boxShadow=`0 4px 12px ${l}`}),v.appendChild(i),v.appendChild(c)}else if(i){w=document.createElement("button"),w.className="notification-button",w.textContent=i;const n=a||this.getButtonGradient(t),e=this.getButtonShadow(t);w.style.background=n,w.style.boxShadow=`0 4px 12px ${e}`}let k=null;if(f&&(k=document.createElement("button"),k.setAttribute("aria-label","Cerrar"),k.className="notification-close",k.innerHTML="×",k.addEventListener("click",n=>{n.stopPropagation(),y()})),m.appendChild(b),x){const n="notify-desc-"+Date.now();x.id=n,p.setAttribute("aria-describedby",n),m.appendChild(x)}else m.appendChild(h),m.appendChild(g);k&&m.appendChild(k),v?m.appendChild(v):w&&m.appendChild(w),p.appendChild(m),document.body.appendChild(p);const E=p,C=new Promise(n=>{try{E._externalResolve=n}catch(n){}});try{const n=document.getElementById("notify-live");n&&(n.textContent=`${e}: ${o}`)}catch(n){}try{this._lastActiveElement=document.activeElement}catch(n){this._lastActiveElement=null}this.currentNotification=p;try{const n=m.querySelectorAll('a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])');n&&n.length?n[0].focus():w?w.focus():p.focus()}catch(n){try{p.focus()}catch(n){}}const S=n=>{if("Tab"!==n.key)return;const t=Array.from(m.querySelectorAll('a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])')).filter(n=>n instanceof HTMLElement&&null!==n.offsetParent);if(!t.length)return void n.preventDefault();const e=t[0],o=t[t.length-1];n.shiftKey||document.activeElement!==o?n.shiftKey&&document.activeElement===e&&(n.preventDefault(),o.focus()):(n.preventDefault(),e.focus())};E._focusTrap=S,document.addEventListener("keydown",S);const N=n.anim||{},L="number"==typeof N.overlayDuration?N.overlayDuration:150,T=N.overlayEasing||"easeOutQuad",D="number"==typeof N.boxDuration?N.boxDuration:200,_="number"==typeof N.boxDelay?N.boxDelay:50,j=N.boxEasing||"easeOutBack",A="number"==typeof N.boxStartScale?N.boxStartScale:.8,$="number"==typeof N.iconDuration?N.iconDuration:250,B="number"==typeof N.iconDelay?N.iconDelay:100,q="number"==typeof N.iconRotate?N.iconRotate:"success"===t?-90:"error"===t?90:0;if("number"==typeof N.overlayOpacity&&(p.style.backgroundColor=`rgba(0,0,0,${N.overlayOpacity})`),anime({targets:p,opacity:[0,1],duration:L,easing:T}),anime({targets:m,scale:[A,1],opacity:[0,1],duration:D,easing:j,delay:_}),anime({targets:b,scale:[0,1],rotate:[q,0],duration:$,easing:j,delay:B}),w){const n=this.getButtonShadow(t);w.addEventListener("mouseenter",()=>{w.style.boxShadow=`0 6px 16px ${n}`}),w.addEventListener("mouseleave",()=>{w.style.boxShadow=`0 4px 12px ${n}`}),w.addEventListener("click",n=>{n.stopPropagation(),n.preventDefault(),y().catch(()=>{})})}if(s&&p.addEventListener("click",n=>{m.contains(n.target)||y()}),c&&setTimeout(()=>{y()},c),l){const n=t=>{"Escape"===t.key&&(y(),document.removeEventListener("keydown",n))};E._escHandler=n,document.addEventListener("keydown",n)}return C}close(n=null){if(!this.currentNotification)return Promise.resolve();const t=this.currentNotification,e=t,o=t.querySelector(".notification-box");return this.currentNotification=null,anime({targets:o,scale:.8,opacity:0,duration:100,easing:"easeInQuad"}),new Promise(o=>{anime({targets:t,opacity:0,duration:100,easing:"easeInQuad",complete:()=>{try{e&&e._escHandler&&(document.removeEventListener("keydown",e._escHandler),e._escHandler=void 0)}catch(n){}try{e&&e._focusTrap&&(document.removeEventListener("keydown",e._focusTrap),e._focusTrap=void 0)}catch(n){}try{if(e&&"function"==typeof e._externalResolve){try{e._externalResolve()}catch(n){}e._externalResolve=void 0}}catch(n){}try{t&&t.parentNode&&t.parentNode.removeChild(t)}catch(n){try{t.remove()}catch(n){}}if(!this.currentNotification){try{document.body.style.overflow=""}catch(n){}try{document.documentElement.style.overflow=""}catch(n){}}try{this._lastActiveElement&&"function"==typeof this._lastActiveElement.focus&&this._lastActiveElement.focus()}catch(n){}this._lastActiveElement=null,n&&n(),o()}})})}success(n,t=null,e={}){this.show(Object.assign({type:"success",title:t||this.getDefaultTitle("success"),message:n},e))}error(n,t=null,e={}){this.show(Object.assign({type:"error",title:t||this.getDefaultTitle("error"),message:n},e))}warning(n,t=null,e={}){this.show(Object.assign({type:"warning",title:t||this.getDefaultTitle("warning"),message:n},e))}question(n,t=null,e={}){this.show(Object.assign({type:"question",title:t||this.getDefaultTitle("question"),message:n},e))}info(n,t=null,e={}){this.show(Object.assign({type:"info",title:t||this.getDefaultTitle("info"),message:n},e))}loading(n="Cargando...",t="Espera",e={}){const o=Object.assign({type:"info",title:t,message:n,hideButton:!0,allowOutsideClick:!1,allowEscapeKey:!1},e),i=this.show(o);return this._currentLoadingPromise=i,i}closeLoading(n=null){return this._currentLoadingPromise=null,this.close(n)}hide(n=null){return this.close(n)}hiden(n=null){return this.close(n)}_formatTime(n){const t=Math.max(0,Math.floor(n));return`${Math.floor(t/60).toString().padStart(2,"0")}:${(t%60).toString().padStart(2,"0")}`}},t=window;t.notify=n,t.Notification=n}}();const NotificationSystem=window.notify?.constructor||function(){throw new Error("NotificationSystem no se pudo cargar. Verifica que anime.js esté disponible.")};export default NotificationSystem;export{NotificationSystem};
|
|
1
|
+
"use strict";var __rest=this&&this.__rest||function(t,n){var e={};for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&n.indexOf(o)<0&&(e[o]=t[o]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(o=Object.getOwnPropertySymbols(t);i<o.length;i++)n.indexOf(o[i])<0&&Object.prototype.propertyIsEnumerable.call(t,o[i])&&(e[o[i]]=t[o[i]])}return e};!function(){if("undefined"!=typeof anime)t();else{const n=document.createElement("script");n.src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js",n.onload=t,n.onerror=()=>{console.error("FerNotify: No se pudo cargar anime.js. Por favor, cargalo manualmente.")},document.head.appendChild(n)}function t(){const t=new class{constructor(){this.currentNotification=null,this._lastActiveElement=null,this._currentLoadingPromise=null,this._toastContainers=new Map,this._toastInstances=new Map,this.injectStyles(),this.loadBoxicons()}loadBoxicons(){if(!document.querySelector('link[href*="boxicons"]')){const t=document.createElement("link");t.rel="stylesheet",t.href="https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css",document.head.appendChild(t)}}injectStyles(){const t=document.createElement("style");t.textContent="\n .notification-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 9999;\n opacity: 0;\n overflow: hidden;\n }\n\n .notification-box {\n background: white;\n border-radius: 16px;\n padding: 40px 30px;\n max-width: 500px;\n width: 90%;\n max-height: 80vh;\n overflow: auto;\n position: relative;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n text-align: center;\n transform: scale(0.7);\n opacity: 0;\n }\n\n .notification-content {\n text-align: left;\n margin-bottom: 18px;\n }\n\n .notification-close {\n position: absolute;\n top: 10px;\n right: 10px;\n width: 38px;\n height: 38px;\n border-radius: 8px;\n border: none;\n background: rgba(0,0,0,0.06);\n color: #111827;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 18px;\n }\n\n .notification-close:hover {\n background: rgba(0,0,0,0.09);\n }\n\n /* Form controls inside the modal */\n .notification-box input,\n .notification-box textarea,\n .notification-box select {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n background: #ffffff;\n color: #111827;\n font-size: 15px;\n box-sizing: border-box;\n transition: box-shadow 0.15s ease, border-color 0.15s ease;\n }\n\n .notification-box input:focus,\n .notification-box textarea:focus,\n .notification-box select:focus {\n outline: none;\n border-color: #6366f1;\n box-shadow: 0 6px 24px rgba(99,102,241,0.12), 0 0 0 4px rgba(99,102,241,0.06);\n }\n\n .notification-box label { display: block; margin-bottom: 6px; color: #374151; font-weight: 600; }\n\n /* Soporte para tema oscuro con clase .dark (Tailwind darkMode: 'class') */\n /* Esto tiene prioridad sobre prefers-color-scheme para respetar la elección del usuario en la web */\n .dark .notification-box { background: #0f1724 !important; color: #e6eef8 !important; }\n .dark .notification-box input,\n .dark .notification-box textarea,\n .dark .notification-box select {\n background: #0b1220 !important;\n border: 1px solid rgba(255,255,255,0.06) !important;\n color: #e6eef8 !important;\n }\n .dark .notification-box .notification-close { background: rgba(255,255,255,0.03) !important; color: #e6eef8 !important; }\n .dark .notification-overlay { background-color: rgba(0,0,0,0.6) !important; }\n .dark .notification-title { color: #e6eef8 !important; }\n .dark .notification-message { color: #cbd5e1 !important; }\n\n /* Forzar modo claro cuando NO hay clase .dark, ignorando prefers-color-scheme */\n html:not(.dark) .notification-box { background: white !important; color: #111827 !important; }\n html:not(.dark) .notification-box input,\n html:not(.dark) .notification-box textarea,\n html:not(.dark) .notification-box select {\n background: #ffffff !important;\n border: 1px solid #e5e7eb !important;\n color: #111827 !important;\n }\n html:not(.dark) .notification-box .notification-close { background: rgba(0,0,0,0.06) !important; color: #111827 !important; }\n html:not(.dark) .notification-overlay { background-color: rgba(0, 0, 0, 0.4) !important; }\n html:not(.dark) .notification-title { color: #1f2937 !important; }\n html:not(.dark) .notification-message { color: #6b7280 !important; }\n\n .notification-icon {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n margin: 0 auto 25px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 40px;\n position: relative;\n }\n\n .notification-icon::before {\n content: '';\n position: absolute;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n opacity: 0.2;\n }\n\n .notification-icon.success {\n background: linear-gradient(135deg, #10b981 0%, #059669 100%);\n color: white;\n }\n\n .notification-icon.success::before {\n background: #10b981;\n }\n\n .notification-icon.error {\n background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);\n color: white;\n }\n\n .notification-icon.error::before {\n background: #ef4444;\n }\n\n .notification-icon.warning {\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n color: white;\n }\n\n .notification-icon.warning::before {\n background: #f59e0b;\n }\n\n .notification-icon.info {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: white;\n }\n\n .notification-icon.info::before {\n background: #3b82f6;\n }\n .notification-icon.question {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: white;\n }\n\n .notification-icon.question::before {\n background: #3b82f6;\n }\n\n .notification-title {\n font-size: 24px;\n font-weight: 700;\n color: #1f2937;\n margin-bottom: 12px;\n line-height: 1.3;\n }\n\n .notification-message {\n font-size: 16px;\n color: #6b7280;\n line-height: 1.6;\n margin-bottom: 30px;\n }\n\n .notification-button {\n color: white;\n border: none;\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 16px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n }\n\n .notification-button:hover {\n transform: translateY(-2px);\n filter: brightness(1.1);\n }\n\n .notification-button:active {\n transform: translateY(0);\n }\n\n /* group container for multiple action buttons */\n .notification-button-group {\n display: flex;\n gap: 12px;\n justify-content: center;\n flex-wrap: wrap;\n margin-top: 10px;\n }\n\n .notification-icon-checkmark {\n animation: checkmark-draw 0.6s ease-in-out;\n }\n\n .notification-icon-cross {\n animation: cross-draw 0.5s ease-in-out;\n }\n\n @keyframes checkmark-draw {\n 0% {\n transform: scale(0) rotate(-45deg);\n opacity: 0;\n }\n 50% {\n transform: scale(1.2) rotate(-45deg);\n }\n 100% {\n transform: scale(1) rotate(0deg);\n opacity: 1;\n }\n }\n\n @keyframes cross-draw {\n 0% {\n transform: scale(0) rotate(-180deg);\n opacity: 0;\n }\n 50% {\n transform: scale(1.2) rotate(-90deg);\n }\n 100% {\n transform: scale(1) rotate(0deg);\n opacity: 1;\n }\n }\n\n /* Loading spinner styles */\n .notification-loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n margin: 0 auto;\n }\n\n .notification-spinner {\n width: 60px;\n height: 60px;\n border: 5px solid rgba(99, 102, 241, 0.15);\n border-top-color: #6366f1;\n border-radius: 50%;\n animation: notification-spin 1s linear infinite;\n margin: 0 auto;\n }\n\n @keyframes notification-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n .notification-loading-text {\n font-size: 14px;\n color: #6b7280;\n text-align: center;\n margin-top: 12px;\n }\n\n .dark .notification-loading-text {\n color: #cbd5e1;\n }\n\n /* ==================== Toast ==================== */\n .notify-toast-container {\n position: fixed;\n z-index: 10000;\n display: flex;\n flex-direction: column;\n gap: 10px;\n pointer-events: none;\n width: 360px;\n max-width: calc(100vw - 40px);\n }\n .notify-toast-top-right { top: 20px; right: 20px; }\n .notify-toast-top-left { top: 20px; left: 20px; }\n .notify-toast-top-center { top: 20px; left: 50%; transform: translateX(-50%); }\n .notify-toast-bottom-right { bottom: 20px; right: 20px; flex-direction: column-reverse; }\n .notify-toast-bottom-left { bottom: 20px; left: 20px; flex-direction: column-reverse; }\n\n .notify-toast {\n background: white;\n border-radius: 12px;\n padding: 14px 40px 14px 14px;\n box-shadow: 0 4px 24px rgba(0,0,0,0.12), 0 1px 4px rgba(0,0,0,0.06);\n display: flex;\n align-items: flex-start;\n gap: 12px;\n pointer-events: auto;\n position: relative;\n overflow: hidden;\n opacity: 0;\n transform: translateX(30px);\n transition: opacity 0.25s ease, transform 0.25s ease;\n }\n .notify-toast-top-left .notify-toast,\n .notify-toast-bottom-left .notify-toast { transform: translateX(-30px); }\n .notify-toast-top-center .notify-toast { transform: translateY(-20px); }\n .notify-toast.notify-toast-visible {\n opacity: 1;\n transform: translateX(0) translateY(0) !important;\n }\n\n .notify-toast-icon {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 20px;\n flex-shrink: 0;\n color: white;\n }\n .notify-toast-icon.success { background: linear-gradient(135deg, #10b981 0%, #059669 100%); }\n .notify-toast-icon.error { background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); }\n .notify-toast-icon.warning { background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); }\n .notify-toast-icon.info { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); }\n .notify-toast-icon.question { background: linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%); }\n .notify-toast-icon.loading { background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%); }\n\n .notify-toast-content { flex: 1; min-width: 0; }\n .notify-toast-title {\n font-size: 14px;\n font-weight: 700;\n color: #1f2937;\n margin-bottom: 2px;\n line-height: 1.3;\n cursor: default;\n }\n .notify-toast-message {\n font-size: 13px;\n color: #6b7280;\n line-height: 1.5;\n cursor: default;\n }\n\n .notify-toast-close {\n position: absolute;\n top: 8px;\n right: 8px;\n width: 24px;\n height: 24px;\n border-radius: 6px;\n border: none;\n background: rgba(0,0,0,0.06);\n color: #6b7280;\n cursor: pointer;\n font-size: 16px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n padding: 0;\n }\n .notify-toast-close:hover { background: rgba(0,0,0,0.1); color: #374151; }\n\n /* Sin botón de cierre: reducir padding derecho */\n .notify-toast.notify-toast-no-close { padding-right: 14px; }\n\n .notify-toast-progress {\n position: absolute;\n bottom: 0;\n left: 0;\n height: 3px;\n width: 100%;\n border-radius: 0 0 0 12px;\n }\n .notify-toast-progress.success { background: #10b981; }\n .notify-toast-progress.error { background: #ef4444; }\n .notify-toast-progress.warning { background: #f59e0b; }\n .notify-toast-progress.info { background: #3b82f6; }\n .notify-toast-progress.question { background: #8b5cf6; }\n .notify-toast-progress.loading { background: #6366f1; }\n\n /* Spinner para toast de carga */\n .notify-toast-spinner {\n width: 18px;\n height: 18px;\n border: 2.5px solid rgba(255,255,255,0.35);\n border-top-color: white;\n border-radius: 50%;\n animation: notification-spin 0.8s linear infinite;\n flex-shrink: 0;\n }\n\n .dark .notify-toast { background: #0f1724; box-shadow: 0 4px 24px rgba(0,0,0,0.35); }\n .dark .notify-toast-title { color: #e6eef8; }\n .dark .notify-toast-message { color: #cbd5e1; }\n .dark .notify-toast-close { background: rgba(255,255,255,0.06); color: #94a3b8; }\n .dark .notify-toast-close:hover { background: rgba(255,255,255,0.1); color: #e2e8f0; }\n\n /* Respeta la preferencia de movimiento reducido del sistema */\n @media (prefers-reduced-motion: reduce) {\n .notify-toast {\n transition: opacity 0.1s ease !important;\n transform: none !important;\n }\n .notify-toast.notify-toast-visible {\n transform: none !important;\n }\n .notify-toast-spinner {\n animation-duration: 1.5s !important;\n }\n .notify-toast-progress {\n transition: none !important;\n }\n }\n ",document.head.appendChild(t)}getIcon(t){const n={success:'<i class="bx bx-check" aria-hidden="true"></i>',error:'<i class="bx bx-x" aria-hidden="true"></i>',warning:'<i class="bx bx-error" aria-hidden="true"></i>',info:'<i class="bx bx-info-circle" aria-hidden="true"></i>',question:'<i class="bx bx-question-mark" aria-hidden="true"></i>',loading:'<div class="notify-toast-spinner" aria-hidden="true"></div>'};return n[t]||n.info}getDefaultTitle(t){return{success:"¡Éxito!",error:"Error",warning:"Advertencia",info:"Información",question:"Pregunta"}[t]||"Notificación"}getButtonGradient(t){const n={success:"linear-gradient(135deg, #10b981 0%, #059669 100%)",error:"linear-gradient(135deg, #ef4444 0%, #dc2626 100%)",warning:"linear-gradient(135deg, #f59e0b 0%, #d97706 100%)",info:"linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)",question:"linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)"};return n[t]||n.info}getButtonShadow(t){const n={success:"rgba(16, 185, 129, 0)",error:"rgba(239, 68, 68, 0)",warning:"rgba(245, 159, 11, 0)",info:"rgba(59, 131, 246, 0)",question:"rgba(108, 99, 245, 0)"};return n[t]||n.info}show(t={}){if(this.currentNotification){const t=this.currentNotification;this.currentNotification=null;try{t&&t.parentNode&&t.parentNode.removeChild(t)}catch(t){}}const{type:n="info",title:e=this.getDefaultTitle(n),message:o="",buttonText:i="OK",buttonColor:a=null,onClose:r=null,timer:s=null,allowOutsideClick:c=!0,allowEscapeKey:l=!0,hideButton:d=!1,buttons:f=null}=t,u=!0===t.showCloseButton;try{document.body.style.overflow="hidden"}catch(t){}try{document.documentElement.style.overflow="hidden"}catch(t){}const p=document.createElement("div");p.className="notification-overlay",p.tabIndex=-1,p.setAttribute("role","dialog"),p.setAttribute("aria-modal","true"),p.style.pointerEvents="auto";const m=document.createElement("div");m.className="notification-box";const b=document.createElement("div");b.className=`notification-icon ${n}`,d&&"info"===n?(b.className="notification-loading-container",b.innerHTML='<div class="notification-spinner"></div>',b.style.background="transparent",b.style.boxShadow="none",b.style.width="100px",b.style.height="100px"):b.innerHTML=this.getIcon(n);const g=document.createElement("h3");g.className="notification-title",g.textContent=e;const h=document.createElement("p");h.className="notification-message",h.textContent=o;let y=null;if(t.html||t.content)if(y=document.createElement("div"),y.className="notification-content",t.html)try{y.innerHTML=t.html}catch(n){y.textContent=t.html}else t.content&&t.content instanceof HTMLElement&&y.appendChild(t.content);const x=()=>this.close(r);let w=null,v=null;if(!d)if(Array.isArray(f)&&f.length)v=document.createElement("div"),v.className="notification-button-group",f.forEach(t=>{const e=document.createElement("button");e.className="notification-button",e.textContent=t.text||"OK";const o=t.color||this.getButtonGradient(n),i=t.shadowColor||this.getButtonShadow(n);e.style.background=o,e.style.boxShadow=`0 4px 12px ${i}`,e.addEventListener("click",n=>{n.stopPropagation(),n.preventDefault();try{x().then(()=>{if("function"==typeof t.onClick)try{const n=t.onClick();n&&"function"==typeof n.then&&n.catch(t=>console.error(t))}catch(t){console.error(t)}}).catch(()=>{})}catch(t){console.error(t)}}),e.addEventListener("mouseenter",()=>{e.style.boxShadow=`0 6px 16px ${i}`}),e.addEventListener("mouseleave",()=>{e.style.boxShadow=`0 4px 12px ${i}`}),v.appendChild(e)});else if(t.onConfirm||t.onCancel||t.confirmText||t.cancelText){v=document.createElement("div"),v.className="notification-button-group";const e=t.cancelText||"Cancelar",o=t.confirmText||"Aceptar",i=document.createElement("button");i.className="notification-button",i.textContent=e;const a=t.cancelColor||"linear-gradient(135deg, #9ca3af 0%, #6b7280 100%)",r=t.cancelShadow||"rgba(107,114,128,0.25)";i.style.background=a,i.style.boxShadow=`0 4px 12px ${r}`,i.addEventListener("click",n=>{n.stopPropagation(),n.preventDefault(),x().then(()=>{try{if("function"==typeof t.onCancel){const n=t.onCancel();n&&"function"==typeof n.then&&n.catch(t=>console.error(t))}}catch(t){console.error(t)}}).catch(()=>{})}),i.addEventListener("mouseenter",()=>{i.style.boxShadow=`0 6px 16px ${r}`}),i.addEventListener("mouseleave",()=>{i.style.boxShadow=`0 4px 12px ${r}`});const s=document.createElement("button");s.className="notification-button",s.textContent=o;const c=t.confirmColor||this.getButtonGradient(n),l=t.confirmShadow||this.getButtonShadow(n);s.style.background=c,s.style.boxShadow=`0 4px 12px ${l}`,s.addEventListener("click",async n=>{n.stopPropagation(),n.preventDefault();try{if(await x(),"function"==typeof t.onConfirm){const n=t.onConfirm();n&&"function"==typeof n.then&&await n}}catch(t){console.error(t)}}),s.addEventListener("mouseenter",()=>{s.style.boxShadow=`0 6px 16px ${l}`}),s.addEventListener("mouseleave",()=>{s.style.boxShadow=`0 4px 12px ${l}`}),v.appendChild(i),v.appendChild(s)}else if(i){w=document.createElement("button"),w.className="notification-button",w.textContent=i;const t=a||this.getButtonGradient(n),e=this.getButtonShadow(n);w.style.background=t,w.style.boxShadow=`0 4px 12px ${e}`}let k=null;if(u&&(k=document.createElement("button"),k.setAttribute("aria-label","Cerrar"),k.className="notification-close",k.innerHTML="×",k.addEventListener("click",t=>{t.stopPropagation(),x()})),m.appendChild(b),y){const t="notify-desc-"+Date.now();y.id=t,p.setAttribute("aria-describedby",t),m.appendChild(y)}else m.appendChild(g),m.appendChild(h);k&&m.appendChild(k),v?m.appendChild(v):w&&m.appendChild(w),p.appendChild(m),document.body.appendChild(p);const E=p,C=new Promise(t=>{try{E._externalResolve=t}catch(t){}});try{const t=document.getElementById("notify-live");t&&(t.textContent=`${e}: ${o}`)}catch(t){}try{this._lastActiveElement=document.activeElement}catch(t){this._lastActiveElement=null}this.currentNotification=p;try{const t=m.querySelectorAll('a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])');t&&t.length?t[0].focus():w?w.focus():p.focus()}catch(t){try{p.focus()}catch(t){}}const _=t=>{if("Tab"!==t.key)return;const n=Array.from(m.querySelectorAll('a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])')).filter(t=>t instanceof HTMLElement&&null!==t.offsetParent);if(!n.length)return void t.preventDefault();const e=n[0],o=n[n.length-1];t.shiftKey||document.activeElement!==o?t.shiftKey&&document.activeElement===e&&(t.preventDefault(),o.focus()):(t.preventDefault(),e.focus())};E._focusTrap=_,document.addEventListener("keydown",_);const N=t.anim||{},T="number"==typeof N.overlayDuration?N.overlayDuration:150,S=N.overlayEasing||"easeOutQuad",L="number"==typeof N.boxDuration?N.boxDuration:200,j="number"==typeof N.boxDelay?N.boxDelay:50,O=N.boxEasing||"easeOutBack",D="number"==typeof N.boxStartScale?N.boxStartScale:.8,A="number"==typeof N.iconDuration?N.iconDuration:250,$="number"==typeof N.iconDelay?N.iconDelay:100,P="number"==typeof N.iconRotate?N.iconRotate:"success"===n?-90:"error"===n?90:0;if("number"==typeof N.overlayOpacity&&(p.style.backgroundColor=`rgba(0,0,0,${N.overlayOpacity})`),anime({targets:p,opacity:[0,1],duration:T,easing:S}),anime({targets:m,scale:[D,1],opacity:[0,1],duration:L,easing:O,delay:j}),anime({targets:b,scale:[0,1],rotate:[P,0],duration:A,easing:O,delay:$}),w){const t=this.getButtonShadow(n);w.addEventListener("mouseenter",()=>{w.style.boxShadow=`0 6px 16px ${t}`}),w.addEventListener("mouseleave",()=>{w.style.boxShadow=`0 4px 12px ${t}`}),w.addEventListener("click",t=>{t.stopPropagation(),t.preventDefault(),x().catch(()=>{})})}if(c&&p.addEventListener("click",t=>{m.contains(t.target)||x()}),s&&setTimeout(()=>{x()},s),l){const t=n=>{"Escape"===n.key&&(x(),document.removeEventListener("keydown",t))};E._escHandler=t,document.addEventListener("keydown",t)}return C}close(t=null){if(!this.currentNotification)return Promise.resolve();const n=this.currentNotification,e=n,o=n.querySelector(".notification-box");return this.currentNotification=null,anime({targets:o,scale:.8,opacity:0,duration:100,easing:"easeInQuad"}),new Promise(o=>{anime({targets:n,opacity:0,duration:100,easing:"easeInQuad",complete:()=>{try{e&&e._escHandler&&(document.removeEventListener("keydown",e._escHandler),e._escHandler=void 0)}catch(t){}try{e&&e._focusTrap&&(document.removeEventListener("keydown",e._focusTrap),e._focusTrap=void 0)}catch(t){}try{if(e&&"function"==typeof e._externalResolve){try{e._externalResolve()}catch(t){}e._externalResolve=void 0}}catch(t){}try{n&&n.parentNode&&n.parentNode.removeChild(n)}catch(t){try{n.remove()}catch(t){}}if(!this.currentNotification){try{document.body.style.overflow=""}catch(t){}try{document.documentElement.style.overflow=""}catch(t){}}try{this._lastActiveElement&&"function"==typeof this._lastActiveElement.focus&&this._lastActiveElement.focus()}catch(t){}this._lastActiveElement=null,t&&t(),o()}})})}success(t,n=null,e={}){this.show(Object.assign({type:"success",title:n||this.getDefaultTitle("success"),message:t},e))}error(t,n=null,e={}){this.show(Object.assign({type:"error",title:n||this.getDefaultTitle("error"),message:t},e))}warning(t,n=null,e={}){this.show(Object.assign({type:"warning",title:n||this.getDefaultTitle("warning"),message:t},e))}question(t,n=null,e={}){this.show(Object.assign({type:"question",title:n||this.getDefaultTitle("question"),message:t},e))}info(t,n=null,e={}){this.show(Object.assign({type:"info",title:n||this.getDefaultTitle("info"),message:t},e))}loading(t="Cargando...",n="Espera",e={}){const o=Object.assign({type:"info",title:n,message:t,hideButton:!0,allowOutsideClick:!1,allowEscapeKey:!1},e),i=this.show(o);return this._currentLoadingPromise=i,i}closeLoading(t=null){return this._currentLoadingPromise=null,this.close(t)}hide(t=null){return this.close(t)}hiden(t=null){return this.close(t)}_formatTime(t){const n=Math.max(0,Math.floor(t));return`${Math.floor(n/60).toString().padStart(2,"0")}:${(n%60).toString().padStart(2,"0")}`}showToast(t,n={}){var e,o;const i=n.type||"info",a=null!==(e=n.title)&&void 0!==e?e:null,r="number"==typeof n.duration?n.duration:4e3,s=n.position||"top-right",c=!1!==n.showProgress,l=null!==(o=n.id)&&void 0!==o?o:null,d=!1!==n.closeable;if(null!==l){const t=this._toastInstances.get(l);if(t)return void t.reset(r)}let f=this._toastContainers.get(s);f&&document.body.contains(f)||(f=document.createElement("div"),f.className=`notify-toast-container notify-toast-${s}`,f.setAttribute("aria-label","Notificaciones"),document.body.appendChild(f),this._toastContainers.set(s,f));const u=s.startsWith("bottom"),p="top-center"===s,m=document.createElement("div");m.className="notify-toast",d||m.classList.add("notify-toast-no-close"),"error"===i||"warning"===i?m.setAttribute("role","alert"):m.setAttribute("role","status"),m.setAttribute("aria-atomic","true"),m.setAttribute("aria-live","error"===i||"warning"===i?"assertive":"polite");const b=document.createElement("div");b.className=`notify-toast-icon ${i}`,b.innerHTML=this.getIcon(i);const g=document.createElement("div");if(g.className="notify-toast-content",a){const t=document.createElement("div");t.className="notify-toast-title",t.textContent=a,g.appendChild(t)}const h=document.createElement("div");if(h.className="notify-toast-message",h.textContent=t,g.appendChild(h),m.appendChild(b),m.appendChild(g),d){const t=document.createElement("button");t.className="notify-toast-close",t.setAttribute("aria-label","Cerrar notificación"),t.innerHTML="×",t.addEventListener("click",E),m.appendChild(t)}let y=null;r>0&&c&&(y=document.createElement("div"),y.className=`notify-toast-progress ${i}`,y.setAttribute("role","progressbar"),y.setAttribute("aria-hidden","true"),m.appendChild(y)),u||p?f.appendChild(m):f.insertBefore(m,f.firstChild);let x=!1,w=null,v=r,k=0;function E(){if(x)return Promise.resolve();if(x=!0,m.contains(document.activeElement))try{document.activeElement.blur()}catch(t){}return m.classList.remove("notify-toast-visible"),new Promise(t=>{setTimeout(()=>{m.parentNode&&m.parentNode.removeChild(m),t()},300)})}const C=t=>{k=Date.now(),w=setTimeout(()=>{null!==l&&this._toastInstances.delete(l),E()},t),y&&(y.style.transition=`width ${t}ms linear`,y.style.width="0%")},_=t=>{x||(null!==w&&(clearTimeout(w),w=null),v=t,t>0?(y&&(y.style.transition="none",y.style.width="100%",y.offsetWidth),C(t)):y&&(y.style.transition="none",y.style.width="100%"))};if(null!==l){const t=()=>{if(!x){if(x=!0,null!==w&&clearTimeout(w),m.contains(document.activeElement))try{document.activeElement.blur()}catch(t){}m.parentNode&&m.parentNode.removeChild(m)}};this._toastInstances.set(l,{reset:_,dismiss:E,_silentDismiss:t})}requestAnimationFrame(()=>{requestAnimationFrame(()=>{m.classList.add("notify-toast-visible"),r>0&&C(r)})}),r>0&&d&&(m.addEventListener("mouseenter",()=>{if(x||null===w)return;clearTimeout(w),w=null;const t=Date.now()-k;if(v=Math.max(0,v-t),y){const t=v/r*100;y.style.transition="none",y.style.width=`${t}%`}}),m.addEventListener("mouseleave",()=>{x||v<=0||C(v)}))}toast(t,n={}){if("string"==typeof t)this.showToast(t,n);else{const{message:n=""}=t,e=__rest(t,["message"]);this.showToast(n,e)}}toastSuccess(t,n,e={}){this.showToast(t,Object.assign(Object.assign({},e),{type:"success",title:null!=n?n:e.title}))}toastError(t,n,e={}){this.showToast(t,Object.assign(Object.assign({},e),{type:"error",title:null!=n?n:e.title}))}toastWarning(t,n,e={}){this.showToast(t,Object.assign(Object.assign({},e),{type:"warning",title:null!=n?n:e.title}))}toastInfo(t,n,e={}){this.showToast(t,Object.assign(Object.assign({},e),{type:"info",title:null!=n?n:e.title}))}toastQuestion(t,n,e={}){this.showToast(t,Object.assign(Object.assign({},e),{type:"question",title:null!=n?n:e.title}))}toastLoading(t="Cargando...",n,e={}){this.showToast(t,Object.assign(Object.assign({position:"top-right"},e),{type:"loading",title:null!=n?n:e.title,id:"__loading__",closeable:!1,duration:0,showProgress:!1}))}closeToastLoading(){const t=this._toastInstances.get("__loading__");return t?(this._toastInstances.delete("__loading__"),t.dismiss()):Promise.resolve()}replaceToastLoading(t,n={}){const e=this._toastInstances.get("__loading__");e&&(this._toastInstances.delete("__loading__"),e._silentDismiss()),this.showToast(t,n)}},n=window;n.notify=t,n.Notification=t}}();const NotificationSystem=window.notify?.constructor||function(){throw new Error("NotificationSystem no se pudo cargar. Verifica que anime.js esté disponible.")};export default NotificationSystem;export{NotificationSystem};
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
2
13
|
(function ensureAnimeDependency() {
|
|
3
14
|
if (typeof anime !== 'undefined') {
|
|
4
15
|
initFerNotify();
|
|
@@ -18,6 +29,8 @@
|
|
|
18
29
|
this.currentNotification = null;
|
|
19
30
|
this._lastActiveElement = null;
|
|
20
31
|
this._currentLoadingPromise = null;
|
|
32
|
+
this._toastContainers = new Map();
|
|
33
|
+
this._toastInstances = new Map();
|
|
21
34
|
this.injectStyles();
|
|
22
35
|
this.loadBoxicons();
|
|
23
36
|
}
|
|
@@ -324,6 +337,152 @@
|
|
|
324
337
|
.dark .notification-loading-text {
|
|
325
338
|
color: #cbd5e1;
|
|
326
339
|
}
|
|
340
|
+
|
|
341
|
+
/* ==================== Toast ==================== */
|
|
342
|
+
.notify-toast-container {
|
|
343
|
+
position: fixed;
|
|
344
|
+
z-index: 10000;
|
|
345
|
+
display: flex;
|
|
346
|
+
flex-direction: column;
|
|
347
|
+
gap: 10px;
|
|
348
|
+
pointer-events: none;
|
|
349
|
+
width: 360px;
|
|
350
|
+
max-width: calc(100vw - 40px);
|
|
351
|
+
}
|
|
352
|
+
.notify-toast-top-right { top: 20px; right: 20px; }
|
|
353
|
+
.notify-toast-top-left { top: 20px; left: 20px; }
|
|
354
|
+
.notify-toast-top-center { top: 20px; left: 50%; transform: translateX(-50%); }
|
|
355
|
+
.notify-toast-bottom-right { bottom: 20px; right: 20px; flex-direction: column-reverse; }
|
|
356
|
+
.notify-toast-bottom-left { bottom: 20px; left: 20px; flex-direction: column-reverse; }
|
|
357
|
+
|
|
358
|
+
.notify-toast {
|
|
359
|
+
background: white;
|
|
360
|
+
border-radius: 12px;
|
|
361
|
+
padding: 14px 40px 14px 14px;
|
|
362
|
+
box-shadow: 0 4px 24px rgba(0,0,0,0.12), 0 1px 4px rgba(0,0,0,0.06);
|
|
363
|
+
display: flex;
|
|
364
|
+
align-items: flex-start;
|
|
365
|
+
gap: 12px;
|
|
366
|
+
pointer-events: auto;
|
|
367
|
+
position: relative;
|
|
368
|
+
overflow: hidden;
|
|
369
|
+
opacity: 0;
|
|
370
|
+
transform: translateX(30px);
|
|
371
|
+
transition: opacity 0.25s ease, transform 0.25s ease;
|
|
372
|
+
}
|
|
373
|
+
.notify-toast-top-left .notify-toast,
|
|
374
|
+
.notify-toast-bottom-left .notify-toast { transform: translateX(-30px); }
|
|
375
|
+
.notify-toast-top-center .notify-toast { transform: translateY(-20px); }
|
|
376
|
+
.notify-toast.notify-toast-visible {
|
|
377
|
+
opacity: 1;
|
|
378
|
+
transform: translateX(0) translateY(0) !important;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.notify-toast-icon {
|
|
382
|
+
width: 36px;
|
|
383
|
+
height: 36px;
|
|
384
|
+
border-radius: 50%;
|
|
385
|
+
display: flex;
|
|
386
|
+
align-items: center;
|
|
387
|
+
justify-content: center;
|
|
388
|
+
font-size: 20px;
|
|
389
|
+
flex-shrink: 0;
|
|
390
|
+
color: white;
|
|
391
|
+
}
|
|
392
|
+
.notify-toast-icon.success { background: linear-gradient(135deg, #10b981 0%, #059669 100%); }
|
|
393
|
+
.notify-toast-icon.error { background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); }
|
|
394
|
+
.notify-toast-icon.warning { background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); }
|
|
395
|
+
.notify-toast-icon.info { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); }
|
|
396
|
+
.notify-toast-icon.question { background: linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%); }
|
|
397
|
+
.notify-toast-icon.loading { background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%); }
|
|
398
|
+
|
|
399
|
+
.notify-toast-content { flex: 1; min-width: 0; }
|
|
400
|
+
.notify-toast-title {
|
|
401
|
+
font-size: 14px;
|
|
402
|
+
font-weight: 700;
|
|
403
|
+
color: #1f2937;
|
|
404
|
+
margin-bottom: 2px;
|
|
405
|
+
line-height: 1.3;
|
|
406
|
+
cursor: default;
|
|
407
|
+
}
|
|
408
|
+
.notify-toast-message {
|
|
409
|
+
font-size: 13px;
|
|
410
|
+
color: #6b7280;
|
|
411
|
+
line-height: 1.5;
|
|
412
|
+
cursor: default;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.notify-toast-close {
|
|
416
|
+
position: absolute;
|
|
417
|
+
top: 8px;
|
|
418
|
+
right: 8px;
|
|
419
|
+
width: 24px;
|
|
420
|
+
height: 24px;
|
|
421
|
+
border-radius: 6px;
|
|
422
|
+
border: none;
|
|
423
|
+
background: rgba(0,0,0,0.06);
|
|
424
|
+
color: #6b7280;
|
|
425
|
+
cursor: pointer;
|
|
426
|
+
font-size: 16px;
|
|
427
|
+
display: flex;
|
|
428
|
+
align-items: center;
|
|
429
|
+
justify-content: center;
|
|
430
|
+
line-height: 1;
|
|
431
|
+
padding: 0;
|
|
432
|
+
}
|
|
433
|
+
.notify-toast-close:hover { background: rgba(0,0,0,0.1); color: #374151; }
|
|
434
|
+
|
|
435
|
+
/* Sin botón de cierre: reducir padding derecho */
|
|
436
|
+
.notify-toast.notify-toast-no-close { padding-right: 14px; }
|
|
437
|
+
|
|
438
|
+
.notify-toast-progress {
|
|
439
|
+
position: absolute;
|
|
440
|
+
bottom: 0;
|
|
441
|
+
left: 0;
|
|
442
|
+
height: 3px;
|
|
443
|
+
width: 100%;
|
|
444
|
+
border-radius: 0 0 0 12px;
|
|
445
|
+
}
|
|
446
|
+
.notify-toast-progress.success { background: #10b981; }
|
|
447
|
+
.notify-toast-progress.error { background: #ef4444; }
|
|
448
|
+
.notify-toast-progress.warning { background: #f59e0b; }
|
|
449
|
+
.notify-toast-progress.info { background: #3b82f6; }
|
|
450
|
+
.notify-toast-progress.question { background: #8b5cf6; }
|
|
451
|
+
.notify-toast-progress.loading { background: #6366f1; }
|
|
452
|
+
|
|
453
|
+
/* Spinner para toast de carga */
|
|
454
|
+
.notify-toast-spinner {
|
|
455
|
+
width: 18px;
|
|
456
|
+
height: 18px;
|
|
457
|
+
border: 2.5px solid rgba(255,255,255,0.35);
|
|
458
|
+
border-top-color: white;
|
|
459
|
+
border-radius: 50%;
|
|
460
|
+
animation: notification-spin 0.8s linear infinite;
|
|
461
|
+
flex-shrink: 0;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
.dark .notify-toast { background: #0f1724; box-shadow: 0 4px 24px rgba(0,0,0,0.35); }
|
|
465
|
+
.dark .notify-toast-title { color: #e6eef8; }
|
|
466
|
+
.dark .notify-toast-message { color: #cbd5e1; }
|
|
467
|
+
.dark .notify-toast-close { background: rgba(255,255,255,0.06); color: #94a3b8; }
|
|
468
|
+
.dark .notify-toast-close:hover { background: rgba(255,255,255,0.1); color: #e2e8f0; }
|
|
469
|
+
|
|
470
|
+
/* Respeta la preferencia de movimiento reducido del sistema */
|
|
471
|
+
@media (prefers-reduced-motion: reduce) {
|
|
472
|
+
.notify-toast {
|
|
473
|
+
transition: opacity 0.1s ease !important;
|
|
474
|
+
transform: none !important;
|
|
475
|
+
}
|
|
476
|
+
.notify-toast.notify-toast-visible {
|
|
477
|
+
transform: none !important;
|
|
478
|
+
}
|
|
479
|
+
.notify-toast-spinner {
|
|
480
|
+
animation-duration: 1.5s !important;
|
|
481
|
+
}
|
|
482
|
+
.notify-toast-progress {
|
|
483
|
+
transition: none !important;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
327
486
|
`;
|
|
328
487
|
document.head.appendChild(style);
|
|
329
488
|
}
|
|
@@ -333,7 +492,8 @@
|
|
|
333
492
|
'error': '<i class="bx bx-x" aria-hidden="true"></i>',
|
|
334
493
|
'warning': '<i class="bx bx-error" aria-hidden="true"></i>',
|
|
335
494
|
'info': '<i class="bx bx-info-circle" aria-hidden="true"></i>',
|
|
336
|
-
'question': '<i class="bx bx-question-mark" aria-hidden="true"></i>'
|
|
495
|
+
'question': '<i class="bx bx-question-mark" aria-hidden="true"></i>',
|
|
496
|
+
'loading': '<div class="notify-toast-spinner" aria-hidden="true"></div>'
|
|
337
497
|
};
|
|
338
498
|
return icons[type] || icons.info;
|
|
339
499
|
}
|
|
@@ -830,6 +990,252 @@
|
|
|
830
990
|
const ss = (s % 60).toString().padStart(2, '0');
|
|
831
991
|
return `${mm}:${ss}`;
|
|
832
992
|
}
|
|
993
|
+
showToast(message, options = {}) {
|
|
994
|
+
var _a, _b;
|
|
995
|
+
const type = options.type || 'info';
|
|
996
|
+
const title = (_a = options.title) !== null && _a !== void 0 ? _a : null;
|
|
997
|
+
const duration = typeof options.duration === 'number' ? options.duration : 4000;
|
|
998
|
+
const position = options.position || 'top-right';
|
|
999
|
+
const showProgress = options.showProgress !== false;
|
|
1000
|
+
const toastId = (_b = options.id) !== null && _b !== void 0 ? _b : null;
|
|
1001
|
+
const closeable = options.closeable !== false;
|
|
1002
|
+
// Deduplicación: si ya existe un toast con este ID, resetear su cuenta regresiva
|
|
1003
|
+
if (toastId !== null) {
|
|
1004
|
+
const existing = this._toastInstances.get(toastId);
|
|
1005
|
+
if (existing) {
|
|
1006
|
+
existing.reset(duration);
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
let container = this._toastContainers.get(position);
|
|
1011
|
+
if (!container || !document.body.contains(container)) {
|
|
1012
|
+
container = document.createElement('div');
|
|
1013
|
+
container.className = `notify-toast-container notify-toast-${position}`;
|
|
1014
|
+
container.setAttribute('aria-label', 'Notificaciones');
|
|
1015
|
+
document.body.appendChild(container);
|
|
1016
|
+
this._toastContainers.set(position, container);
|
|
1017
|
+
}
|
|
1018
|
+
const isBottom = position.startsWith('bottom');
|
|
1019
|
+
const isCenter = position === 'top-center';
|
|
1020
|
+
const toast = document.createElement('div');
|
|
1021
|
+
toast.className = 'notify-toast';
|
|
1022
|
+
if (!closeable) {
|
|
1023
|
+
toast.classList.add('notify-toast-no-close');
|
|
1024
|
+
}
|
|
1025
|
+
// Accesibilidad: role + aria-live según la urgencia del tipo
|
|
1026
|
+
// role="alert" implica aria-live="assertive" + aria-atomic="true" → lector lo interrumpe
|
|
1027
|
+
// role="status" implica aria-live="polite" + aria-atomic="true" → lector espera pausa
|
|
1028
|
+
if (type === 'error' || type === 'warning') {
|
|
1029
|
+
toast.setAttribute('role', 'alert');
|
|
1030
|
+
}
|
|
1031
|
+
else {
|
|
1032
|
+
toast.setAttribute('role', 'status');
|
|
1033
|
+
}
|
|
1034
|
+
toast.setAttribute('aria-atomic', 'true');
|
|
1035
|
+
toast.setAttribute('aria-live', type === 'error' || type === 'warning' ? 'assertive' : 'polite');
|
|
1036
|
+
const iconEl = document.createElement('div');
|
|
1037
|
+
iconEl.className = `notify-toast-icon ${type}`;
|
|
1038
|
+
iconEl.innerHTML = this.getIcon(type);
|
|
1039
|
+
const contentEl = document.createElement('div');
|
|
1040
|
+
contentEl.className = 'notify-toast-content';
|
|
1041
|
+
if (title) {
|
|
1042
|
+
const titleEl = document.createElement('div');
|
|
1043
|
+
titleEl.className = 'notify-toast-title';
|
|
1044
|
+
titleEl.textContent = title;
|
|
1045
|
+
contentEl.appendChild(titleEl);
|
|
1046
|
+
}
|
|
1047
|
+
const msgEl = document.createElement('div');
|
|
1048
|
+
msgEl.className = 'notify-toast-message';
|
|
1049
|
+
msgEl.textContent = message;
|
|
1050
|
+
contentEl.appendChild(msgEl);
|
|
1051
|
+
toast.appendChild(iconEl);
|
|
1052
|
+
toast.appendChild(contentEl);
|
|
1053
|
+
if (closeable) {
|
|
1054
|
+
const closeBtn = document.createElement('button');
|
|
1055
|
+
closeBtn.className = 'notify-toast-close';
|
|
1056
|
+
closeBtn.setAttribute('aria-label', 'Cerrar notificación');
|
|
1057
|
+
closeBtn.innerHTML = '×';
|
|
1058
|
+
closeBtn.addEventListener('click', removeToast);
|
|
1059
|
+
toast.appendChild(closeBtn);
|
|
1060
|
+
}
|
|
1061
|
+
let progressEl = null;
|
|
1062
|
+
if (duration > 0 && showProgress) {
|
|
1063
|
+
progressEl = document.createElement('div');
|
|
1064
|
+
progressEl.className = `notify-toast-progress ${type}`;
|
|
1065
|
+
progressEl.setAttribute('role', 'progressbar');
|
|
1066
|
+
progressEl.setAttribute('aria-hidden', 'true'); // decorativo: el timer no añade info que el usuario necesite leer
|
|
1067
|
+
toast.appendChild(progressEl);
|
|
1068
|
+
}
|
|
1069
|
+
if (isBottom || isCenter) {
|
|
1070
|
+
container.appendChild(toast);
|
|
1071
|
+
}
|
|
1072
|
+
else {
|
|
1073
|
+
container.insertBefore(toast, container.firstChild);
|
|
1074
|
+
}
|
|
1075
|
+
let dismissed = false;
|
|
1076
|
+
let timerId = null;
|
|
1077
|
+
let remaining = duration;
|
|
1078
|
+
let timerStartedAt = 0;
|
|
1079
|
+
function removeToast() {
|
|
1080
|
+
if (dismissed)
|
|
1081
|
+
return Promise.resolve();
|
|
1082
|
+
dismissed = true;
|
|
1083
|
+
// Si el foco estaba dentro del toast, sacarlo antes de que el nodo desaparezca
|
|
1084
|
+
// para evitar que el foco se pierda silenciosamente en el documento
|
|
1085
|
+
if (toast.contains(document.activeElement)) {
|
|
1086
|
+
try {
|
|
1087
|
+
document.activeElement.blur();
|
|
1088
|
+
}
|
|
1089
|
+
catch (e) { }
|
|
1090
|
+
}
|
|
1091
|
+
toast.classList.remove('notify-toast-visible');
|
|
1092
|
+
return new Promise(resolve => {
|
|
1093
|
+
setTimeout(() => {
|
|
1094
|
+
if (toast.parentNode)
|
|
1095
|
+
toast.parentNode.removeChild(toast);
|
|
1096
|
+
resolve();
|
|
1097
|
+
}, 300);
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1100
|
+
const startCountdown = (ms) => {
|
|
1101
|
+
timerStartedAt = Date.now();
|
|
1102
|
+
timerId = setTimeout(() => {
|
|
1103
|
+
if (toastId !== null)
|
|
1104
|
+
this._toastInstances.delete(toastId);
|
|
1105
|
+
removeToast();
|
|
1106
|
+
}, ms);
|
|
1107
|
+
if (progressEl) {
|
|
1108
|
+
progressEl.style.transition = `width ${ms}ms linear`;
|
|
1109
|
+
progressEl.style.width = '0%';
|
|
1110
|
+
}
|
|
1111
|
+
};
|
|
1112
|
+
const pauseCountdown = () => {
|
|
1113
|
+
if (dismissed || timerId === null)
|
|
1114
|
+
return;
|
|
1115
|
+
clearTimeout(timerId);
|
|
1116
|
+
timerId = null;
|
|
1117
|
+
const elapsed = Date.now() - timerStartedAt;
|
|
1118
|
+
remaining = Math.max(0, remaining - elapsed);
|
|
1119
|
+
if (progressEl) {
|
|
1120
|
+
const pct = (remaining / duration) * 100;
|
|
1121
|
+
progressEl.style.transition = 'none';
|
|
1122
|
+
progressEl.style.width = `${pct}%`;
|
|
1123
|
+
}
|
|
1124
|
+
};
|
|
1125
|
+
const resumeCountdown = () => {
|
|
1126
|
+
if (dismissed || remaining <= 0)
|
|
1127
|
+
return;
|
|
1128
|
+
startCountdown(remaining);
|
|
1129
|
+
};
|
|
1130
|
+
const resetCountdown = (newDuration) => {
|
|
1131
|
+
if (dismissed)
|
|
1132
|
+
return;
|
|
1133
|
+
if (timerId !== null) {
|
|
1134
|
+
clearTimeout(timerId);
|
|
1135
|
+
timerId = null;
|
|
1136
|
+
}
|
|
1137
|
+
remaining = newDuration;
|
|
1138
|
+
if (newDuration > 0) {
|
|
1139
|
+
if (progressEl) {
|
|
1140
|
+
progressEl.style.transition = 'none';
|
|
1141
|
+
progressEl.style.width = '100%';
|
|
1142
|
+
// Forzar reflow para que la transición se aplique desde el inicio
|
|
1143
|
+
void progressEl.offsetWidth;
|
|
1144
|
+
}
|
|
1145
|
+
startCountdown(newDuration);
|
|
1146
|
+
}
|
|
1147
|
+
else if (progressEl) {
|
|
1148
|
+
progressEl.style.transition = 'none';
|
|
1149
|
+
progressEl.style.width = '100%';
|
|
1150
|
+
}
|
|
1151
|
+
};
|
|
1152
|
+
if (toastId !== null) {
|
|
1153
|
+
const silentDismiss = () => {
|
|
1154
|
+
if (dismissed)
|
|
1155
|
+
return;
|
|
1156
|
+
dismissed = true;
|
|
1157
|
+
if (timerId !== null)
|
|
1158
|
+
clearTimeout(timerId);
|
|
1159
|
+
if (toast.contains(document.activeElement)) {
|
|
1160
|
+
try {
|
|
1161
|
+
document.activeElement.blur();
|
|
1162
|
+
}
|
|
1163
|
+
catch (e) { }
|
|
1164
|
+
}
|
|
1165
|
+
if (toast.parentNode)
|
|
1166
|
+
toast.parentNode.removeChild(toast);
|
|
1167
|
+
};
|
|
1168
|
+
this._toastInstances.set(toastId, { reset: resetCountdown, dismiss: removeToast, _silentDismiss: silentDismiss });
|
|
1169
|
+
}
|
|
1170
|
+
requestAnimationFrame(() => {
|
|
1171
|
+
requestAnimationFrame(() => {
|
|
1172
|
+
toast.classList.add('notify-toast-visible');
|
|
1173
|
+
if (duration > 0) {
|
|
1174
|
+
startCountdown(duration);
|
|
1175
|
+
}
|
|
1176
|
+
});
|
|
1177
|
+
});
|
|
1178
|
+
if (duration > 0 && closeable) {
|
|
1179
|
+
toast.addEventListener('mouseenter', pauseCountdown);
|
|
1180
|
+
toast.addEventListener('mouseleave', resumeCountdown);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
toast(messageOrOptions, options = {}) {
|
|
1184
|
+
if (typeof messageOrOptions === 'string') {
|
|
1185
|
+
this.showToast(messageOrOptions, options);
|
|
1186
|
+
}
|
|
1187
|
+
else {
|
|
1188
|
+
const { message = '' } = messageOrOptions, rest = __rest(messageOrOptions, ["message"]);
|
|
1189
|
+
this.showToast(message, rest);
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
toastSuccess(message, title, options = {}) {
|
|
1193
|
+
this.showToast(message, Object.assign(Object.assign({}, options), { type: 'success', title: title !== null && title !== void 0 ? title : options.title }));
|
|
1194
|
+
}
|
|
1195
|
+
toastError(message, title, options = {}) {
|
|
1196
|
+
this.showToast(message, Object.assign(Object.assign({}, options), { type: 'error', title: title !== null && title !== void 0 ? title : options.title }));
|
|
1197
|
+
}
|
|
1198
|
+
toastWarning(message, title, options = {}) {
|
|
1199
|
+
this.showToast(message, Object.assign(Object.assign({}, options), { type: 'warning', title: title !== null && title !== void 0 ? title : options.title }));
|
|
1200
|
+
}
|
|
1201
|
+
toastInfo(message, title, options = {}) {
|
|
1202
|
+
this.showToast(message, Object.assign(Object.assign({}, options), { type: 'info', title: title !== null && title !== void 0 ? title : options.title }));
|
|
1203
|
+
}
|
|
1204
|
+
toastQuestion(message, title, options = {}) {
|
|
1205
|
+
this.showToast(message, Object.assign(Object.assign({}, options), { type: 'question', title: title !== null && title !== void 0 ? title : options.title }));
|
|
1206
|
+
}
|
|
1207
|
+
/**
|
|
1208
|
+
* Muestra un toast de carga con spinner.
|
|
1209
|
+
* - No se puede cerrar manualmente (closeable: false por defecto).
|
|
1210
|
+
* - No tiene cuenta regresiva (duration: 0 por defecto).
|
|
1211
|
+
* - Solo puede existir uno a la vez (id '__loading__').
|
|
1212
|
+
* Ciérralo con notify.closeToastLoading().
|
|
1213
|
+
*/
|
|
1214
|
+
toastLoading(message = 'Cargando...', title, options = {}) {
|
|
1215
|
+
this.showToast(message, Object.assign(Object.assign({ position: 'top-right' }, options), { type: 'loading', title: title !== null && title !== void 0 ? title : options.title, id: '__loading__', closeable: false, duration: 0, showProgress: false }));
|
|
1216
|
+
}
|
|
1217
|
+
/** Cierra el toast de carga activo (si existe). Devuelve una Promise que resuelve cuando la animación de salida termina (≈300 ms). */
|
|
1218
|
+
closeToastLoading() {
|
|
1219
|
+
const entry = this._toastInstances.get('__loading__');
|
|
1220
|
+
if (entry) {
|
|
1221
|
+
this._toastInstances.delete('__loading__');
|
|
1222
|
+
return entry.dismiss();
|
|
1223
|
+
}
|
|
1224
|
+
return Promise.resolve();
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Reemplaza el toast de carga activo por un toast de resultado en el mismo lugar,
|
|
1228
|
+
* sin animación de salida/entrada — no hay solapamiento ni hueco visual.
|
|
1229
|
+
* Si no existe un toast de carga activo, simplemente muestra un toast normal.
|
|
1230
|
+
*/
|
|
1231
|
+
replaceToastLoading(message, options = {}) {
|
|
1232
|
+
const entry = this._toastInstances.get('__loading__');
|
|
1233
|
+
if (entry) {
|
|
1234
|
+
this._toastInstances.delete('__loading__');
|
|
1235
|
+
entry._silentDismiss();
|
|
1236
|
+
}
|
|
1237
|
+
this.showToast(message, options);
|
|
1238
|
+
}
|
|
833
1239
|
}
|
|
834
1240
|
const notifyInstance = new NotificationSystem();
|
|
835
1241
|
const w = window;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";!function(){if("undefined"!=typeof anime)n();else{const t=document.createElement("script");t.src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js",t.onload=n,t.onerror=()=>{console.error("FerNotify: No se pudo cargar anime.js. Por favor, cargalo manualmente.")},document.head.appendChild(t)}function n(){const n=new class{constructor(){this.currentNotification=null,this._lastActiveElement=null,this._currentLoadingPromise=null,this.injectStyles(),this.loadBoxicons()}loadBoxicons(){if(!document.querySelector('link[href*="boxicons"]')){const n=document.createElement("link");n.rel="stylesheet",n.href="https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css",document.head.appendChild(n)}}injectStyles(){const n=document.createElement("style");n.textContent="\n .notification-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 9999;\n opacity: 0;\n overflow: hidden;\n }\n\n .notification-box {\n background: white;\n border-radius: 16px;\n padding: 40px 30px;\n max-width: 500px;\n width: 90%;\n max-height: 80vh;\n overflow: auto;\n position: relative;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n text-align: center;\n transform: scale(0.7);\n opacity: 0;\n }\n\n .notification-content {\n text-align: left;\n margin-bottom: 18px;\n }\n\n .notification-close {\n position: absolute;\n top: 10px;\n right: 10px;\n width: 38px;\n height: 38px;\n border-radius: 8px;\n border: none;\n background: rgba(0,0,0,0.06);\n color: #111827;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 18px;\n }\n\n .notification-close:hover {\n background: rgba(0,0,0,0.09);\n }\n\n /* Form controls inside the modal */\n .notification-box input,\n .notification-box textarea,\n .notification-box select {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n background: #ffffff;\n color: #111827;\n font-size: 15px;\n box-sizing: border-box;\n transition: box-shadow 0.15s ease, border-color 0.15s ease;\n }\n\n .notification-box input:focus,\n .notification-box textarea:focus,\n .notification-box select:focus {\n outline: none;\n border-color: #6366f1;\n box-shadow: 0 6px 24px rgba(99,102,241,0.12), 0 0 0 4px rgba(99,102,241,0.06);\n }\n\n .notification-box label { display: block; margin-bottom: 6px; color: #374151; font-weight: 600; }\n\n /* Soporte para tema oscuro con clase .dark (Tailwind darkMode: 'class') */\n /* Esto tiene prioridad sobre prefers-color-scheme para respetar la elección del usuario en la web */\n .dark .notification-box { background: #0f1724 !important; color: #e6eef8 !important; }\n .dark .notification-box input,\n .dark .notification-box textarea,\n .dark .notification-box select {\n background: #0b1220 !important;\n border: 1px solid rgba(255,255,255,0.06) !important;\n color: #e6eef8 !important;\n }\n .dark .notification-box .notification-close { background: rgba(255,255,255,0.03) !important; color: #e6eef8 !important; }\n .dark .notification-overlay { background-color: rgba(0,0,0,0.6) !important; }\n .dark .notification-title { color: #e6eef8 !important; }\n .dark .notification-message { color: #cbd5e1 !important; }\n\n /* Forzar modo claro cuando NO hay clase .dark, ignorando prefers-color-scheme */\n html:not(.dark) .notification-box { background: white !important; color: #111827 !important; }\n html:not(.dark) .notification-box input,\n html:not(.dark) .notification-box textarea,\n html:not(.dark) .notification-box select {\n background: #ffffff !important;\n border: 1px solid #e5e7eb !important;\n color: #111827 !important;\n }\n html:not(.dark) .notification-box .notification-close { background: rgba(0,0,0,0.06) !important; color: #111827 !important; }\n html:not(.dark) .notification-overlay { background-color: rgba(0, 0, 0, 0.4) !important; }\n html:not(.dark) .notification-title { color: #1f2937 !important; }\n html:not(.dark) .notification-message { color: #6b7280 !important; }\n\n .notification-icon {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n margin: 0 auto 25px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 40px;\n position: relative;\n }\n\n .notification-icon::before {\n content: '';\n position: absolute;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n opacity: 0.2;\n }\n\n .notification-icon.success {\n background: linear-gradient(135deg, #10b981 0%, #059669 100%);\n color: white;\n }\n\n .notification-icon.success::before {\n background: #10b981;\n }\n\n .notification-icon.error {\n background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);\n color: white;\n }\n\n .notification-icon.error::before {\n background: #ef4444;\n }\n\n .notification-icon.warning {\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n color: white;\n }\n\n .notification-icon.warning::before {\n background: #f59e0b;\n }\n\n .notification-icon.info {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: white;\n }\n\n .notification-icon.info::before {\n background: #3b82f6;\n }\n .notification-icon.question {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: white;\n }\n\n .notification-icon.question::before {\n background: #3b82f6;\n }\n\n .notification-title {\n font-size: 24px;\n font-weight: 700;\n color: #1f2937;\n margin-bottom: 12px;\n line-height: 1.3;\n }\n\n .notification-message {\n font-size: 16px;\n color: #6b7280;\n line-height: 1.6;\n margin-bottom: 30px;\n }\n\n .notification-button {\n color: white;\n border: none;\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 16px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n }\n\n .notification-button:hover {\n transform: translateY(-2px);\n filter: brightness(1.1);\n }\n\n .notification-button:active {\n transform: translateY(0);\n }\n\n /* group container for multiple action buttons */\n .notification-button-group {\n display: flex;\n gap: 12px;\n justify-content: center;\n flex-wrap: wrap;\n margin-top: 10px;\n }\n\n .notification-icon-checkmark {\n animation: checkmark-draw 0.6s ease-in-out;\n }\n\n .notification-icon-cross {\n animation: cross-draw 0.5s ease-in-out;\n }\n\n @keyframes checkmark-draw {\n 0% {\n transform: scale(0) rotate(-45deg);\n opacity: 0;\n }\n 50% {\n transform: scale(1.2) rotate(-45deg);\n }\n 100% {\n transform: scale(1) rotate(0deg);\n opacity: 1;\n }\n }\n\n @keyframes cross-draw {\n 0% {\n transform: scale(0) rotate(-180deg);\n opacity: 0;\n }\n 50% {\n transform: scale(1.2) rotate(-90deg);\n }\n 100% {\n transform: scale(1) rotate(0deg);\n opacity: 1;\n }\n }\n\n /* Loading spinner styles */\n .notification-loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n margin: 0 auto;\n }\n\n .notification-spinner {\n width: 60px;\n height: 60px;\n border: 5px solid rgba(99, 102, 241, 0.15);\n border-top-color: #6366f1;\n border-radius: 50%;\n animation: notification-spin 1s linear infinite;\n margin: 0 auto;\n }\n\n @keyframes notification-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n .notification-loading-text {\n font-size: 14px;\n color: #6b7280;\n text-align: center;\n margin-top: 12px;\n }\n\n .dark .notification-loading-text {\n color: #cbd5e1;\n }\n ",document.head.appendChild(n)}getIcon(n){const t={success:'<i class="bx bx-check" aria-hidden="true"></i>',error:'<i class="bx bx-x" aria-hidden="true"></i>',warning:'<i class="bx bx-error" aria-hidden="true"></i>',info:'<i class="bx bx-info-circle" aria-hidden="true"></i>',question:'<i class="bx bx-question-mark" aria-hidden="true"></i>'};return t[n]||t.info}getDefaultTitle(n){return{success:"¡Éxito!",error:"Error",warning:"Advertencia",info:"Información",question:"Pregunta"}[n]||"Notificación"}getButtonGradient(n){const t={success:"linear-gradient(135deg, #10b981 0%, #059669 100%)",error:"linear-gradient(135deg, #ef4444 0%, #dc2626 100%)",warning:"linear-gradient(135deg, #f59e0b 0%, #d97706 100%)",info:"linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)",question:"linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)"};return t[n]||t.info}getButtonShadow(n){const t={success:"rgba(16, 185, 129, 0)",error:"rgba(239, 68, 68, 0)",warning:"rgba(245, 159, 11, 0)",info:"rgba(59, 131, 246, 0)",question:"rgba(108, 99, 245, 0)"};return t[n]||t.info}show(n={}){if(this.currentNotification){const n=this.currentNotification;this.currentNotification=null;try{n&&n.parentNode&&n.parentNode.removeChild(n)}catch(n){}}const{type:t="info",title:e=this.getDefaultTitle(t),message:o="",buttonText:i="OK",buttonColor:a=null,onClose:r=null,timer:c=null,allowOutsideClick:s=!0,allowEscapeKey:l=!0,hideButton:d=!1,buttons:u=null}=n,f=!0===n.showCloseButton;try{document.body.style.overflow="hidden"}catch(n){}try{document.documentElement.style.overflow="hidden"}catch(n){}const p=document.createElement("div");p.className="notification-overlay",p.tabIndex=-1,p.setAttribute("role","dialog"),p.setAttribute("aria-modal","true"),p.style.pointerEvents="auto";const m=document.createElement("div");m.className="notification-box";const b=document.createElement("div");b.className=`notification-icon ${t}`,d&&"info"===t?(b.className="notification-loading-container",b.innerHTML='<div class="notification-spinner"></div>',b.style.background="transparent",b.style.boxShadow="none",b.style.width="100px",b.style.height="100px"):b.innerHTML=this.getIcon(t);const h=document.createElement("h3");h.className="notification-title",h.textContent=e;const g=document.createElement("p");g.className="notification-message",g.textContent=o;let x=null;if(n.html||n.content)if(x=document.createElement("div"),x.className="notification-content",n.html)try{x.innerHTML=n.html}catch(t){x.textContent=n.html}else n.content&&n.content instanceof HTMLElement&&x.appendChild(n.content);const y=()=>this.close(r);let w=null,v=null;if(!d)if(Array.isArray(u)&&u.length)v=document.createElement("div"),v.className="notification-button-group",u.forEach(n=>{const e=document.createElement("button");e.className="notification-button",e.textContent=n.text||"OK";const o=n.color||this.getButtonGradient(t),i=n.shadowColor||this.getButtonShadow(t);e.style.background=o,e.style.boxShadow=`0 4px 12px ${i}`,e.addEventListener("click",t=>{t.stopPropagation(),t.preventDefault();try{y().then(()=>{if("function"==typeof n.onClick)try{const t=n.onClick();t&&"function"==typeof t.then&&t.catch(n=>console.error(n))}catch(n){console.error(n)}}).catch(()=>{})}catch(n){console.error(n)}}),e.addEventListener("mouseenter",()=>{e.style.boxShadow=`0 6px 16px ${i}`}),e.addEventListener("mouseleave",()=>{e.style.boxShadow=`0 4px 12px ${i}`}),v.appendChild(e)});else if(n.onConfirm||n.onCancel||n.confirmText||n.cancelText){v=document.createElement("div"),v.className="notification-button-group";const e=n.cancelText||"Cancelar",o=n.confirmText||"Aceptar",i=document.createElement("button");i.className="notification-button",i.textContent=e;const a=n.cancelColor||"linear-gradient(135deg, #9ca3af 0%, #6b7280 100%)",r=n.cancelShadow||"rgba(107,114,128,0.25)";i.style.background=a,i.style.boxShadow=`0 4px 12px ${r}`,i.addEventListener("click",t=>{t.stopPropagation(),t.preventDefault(),y().then(()=>{try{if("function"==typeof n.onCancel){const t=n.onCancel();t&&"function"==typeof t.then&&t.catch(n=>console.error(n))}}catch(n){console.error(n)}}).catch(()=>{})}),i.addEventListener("mouseenter",()=>{i.style.boxShadow=`0 6px 16px ${r}`}),i.addEventListener("mouseleave",()=>{i.style.boxShadow=`0 4px 12px ${r}`});const c=document.createElement("button");c.className="notification-button",c.textContent=o;const s=n.confirmColor||this.getButtonGradient(t),l=n.confirmShadow||this.getButtonShadow(t);c.style.background=s,c.style.boxShadow=`0 4px 12px ${l}`,c.addEventListener("click",async t=>{t.stopPropagation(),t.preventDefault();try{if(await y(),"function"==typeof n.onConfirm){const t=n.onConfirm();t&&"function"==typeof t.then&&await t}}catch(n){console.error(n)}}),c.addEventListener("mouseenter",()=>{c.style.boxShadow=`0 6px 16px ${l}`}),c.addEventListener("mouseleave",()=>{c.style.boxShadow=`0 4px 12px ${l}`}),v.appendChild(i),v.appendChild(c)}else if(i){w=document.createElement("button"),w.className="notification-button",w.textContent=i;const n=a||this.getButtonGradient(t),e=this.getButtonShadow(t);w.style.background=n,w.style.boxShadow=`0 4px 12px ${e}`}let k=null;if(f&&(k=document.createElement("button"),k.setAttribute("aria-label","Cerrar"),k.className="notification-close",k.innerHTML="×",k.addEventListener("click",n=>{n.stopPropagation(),y()})),m.appendChild(b),x){const n="notify-desc-"+Date.now();x.id=n,p.setAttribute("aria-describedby",n),m.appendChild(x)}else m.appendChild(h),m.appendChild(g);k&&m.appendChild(k),v?m.appendChild(v):w&&m.appendChild(w),p.appendChild(m),document.body.appendChild(p);const E=p,C=new Promise(n=>{try{E._externalResolve=n}catch(n){}});try{const n=document.getElementById("notify-live");n&&(n.textContent=`${e}: ${o}`)}catch(n){}try{this._lastActiveElement=document.activeElement}catch(n){this._lastActiveElement=null}this.currentNotification=p;try{const n=m.querySelectorAll('a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])');n&&n.length?n[0].focus():w?w.focus():p.focus()}catch(n){try{p.focus()}catch(n){}}const S=n=>{if("Tab"!==n.key)return;const t=Array.from(m.querySelectorAll('a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])')).filter(n=>n instanceof HTMLElement&&null!==n.offsetParent);if(!t.length)return void n.preventDefault();const e=t[0],o=t[t.length-1];n.shiftKey||document.activeElement!==o?n.shiftKey&&document.activeElement===e&&(n.preventDefault(),o.focus()):(n.preventDefault(),e.focus())};E._focusTrap=S,document.addEventListener("keydown",S);const N=n.anim||{},L="number"==typeof N.overlayDuration?N.overlayDuration:150,T=N.overlayEasing||"easeOutQuad",D="number"==typeof N.boxDuration?N.boxDuration:200,_="number"==typeof N.boxDelay?N.boxDelay:50,j=N.boxEasing||"easeOutBack",A="number"==typeof N.boxStartScale?N.boxStartScale:.8,$="number"==typeof N.iconDuration?N.iconDuration:250,B="number"==typeof N.iconDelay?N.iconDelay:100,O="number"==typeof N.iconRotate?N.iconRotate:"success"===t?-90:"error"===t?90:0;if("number"==typeof N.overlayOpacity&&(p.style.backgroundColor=`rgba(0,0,0,${N.overlayOpacity})`),anime({targets:p,opacity:[0,1],duration:L,easing:T}),anime({targets:m,scale:[A,1],opacity:[0,1],duration:D,easing:j,delay:_}),anime({targets:b,scale:[0,1],rotate:[O,0],duration:$,easing:j,delay:B}),w){const n=this.getButtonShadow(t);w.addEventListener("mouseenter",()=>{w.style.boxShadow=`0 6px 16px ${n}`}),w.addEventListener("mouseleave",()=>{w.style.boxShadow=`0 4px 12px ${n}`}),w.addEventListener("click",n=>{n.stopPropagation(),n.preventDefault(),y().catch(()=>{})})}if(s&&p.addEventListener("click",n=>{m.contains(n.target)||y()}),c&&setTimeout(()=>{y()},c),l){const n=t=>{"Escape"===t.key&&(y(),document.removeEventListener("keydown",n))};E._escHandler=n,document.addEventListener("keydown",n)}return C}close(n=null){if(!this.currentNotification)return Promise.resolve();const t=this.currentNotification,e=t,o=t.querySelector(".notification-box");return this.currentNotification=null,anime({targets:o,scale:.8,opacity:0,duration:100,easing:"easeInQuad"}),new Promise(o=>{anime({targets:t,opacity:0,duration:100,easing:"easeInQuad",complete:()=>{try{e&&e._escHandler&&(document.removeEventListener("keydown",e._escHandler),e._escHandler=void 0)}catch(n){}try{e&&e._focusTrap&&(document.removeEventListener("keydown",e._focusTrap),e._focusTrap=void 0)}catch(n){}try{if(e&&"function"==typeof e._externalResolve){try{e._externalResolve()}catch(n){}e._externalResolve=void 0}}catch(n){}try{t&&t.parentNode&&t.parentNode.removeChild(t)}catch(n){try{t.remove()}catch(n){}}if(!this.currentNotification){try{document.body.style.overflow=""}catch(n){}try{document.documentElement.style.overflow=""}catch(n){}}try{this._lastActiveElement&&"function"==typeof this._lastActiveElement.focus&&this._lastActiveElement.focus()}catch(n){}this._lastActiveElement=null,n&&n(),o()}})})}success(n,t=null,e={}){this.show(Object.assign({type:"success",title:t||this.getDefaultTitle("success"),message:n},e))}error(n,t=null,e={}){this.show(Object.assign({type:"error",title:t||this.getDefaultTitle("error"),message:n},e))}warning(n,t=null,e={}){this.show(Object.assign({type:"warning",title:t||this.getDefaultTitle("warning"),message:n},e))}question(n,t=null,e={}){this.show(Object.assign({type:"question",title:t||this.getDefaultTitle("question"),message:n},e))}info(n,t=null,e={}){this.show(Object.assign({type:"info",title:t||this.getDefaultTitle("info"),message:n},e))}loading(n="Cargando...",t="Espera",e={}){const o=Object.assign({type:"info",title:t,message:n,hideButton:!0,allowOutsideClick:!1,allowEscapeKey:!1},e),i=this.show(o);return this._currentLoadingPromise=i,i}closeLoading(n=null){return this._currentLoadingPromise=null,this.close(n)}hide(n=null){return this.close(n)}hiden(n=null){return this.close(n)}_formatTime(n){const t=Math.max(0,Math.floor(n));return`${Math.floor(t/60).toString().padStart(2,"0")}:${(t%60).toString().padStart(2,"0")}`}},t=window;t.notify=n,t.Notification=n}}();
|
|
1
|
+
"use strict";var __rest=this&&this.__rest||function(t,n){var e={};for(var o in t)Object.prototype.hasOwnProperty.call(t,o)&&n.indexOf(o)<0&&(e[o]=t[o]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(o=Object.getOwnPropertySymbols(t);i<o.length;i++)n.indexOf(o[i])<0&&Object.prototype.propertyIsEnumerable.call(t,o[i])&&(e[o[i]]=t[o[i]])}return e};!function(){if("undefined"!=typeof anime)t();else{const n=document.createElement("script");n.src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js",n.onload=t,n.onerror=()=>{console.error("FerNotify: No se pudo cargar anime.js. Por favor, cargalo manualmente.")},document.head.appendChild(n)}function t(){const t=new class{constructor(){this.currentNotification=null,this._lastActiveElement=null,this._currentLoadingPromise=null,this._toastContainers=new Map,this._toastInstances=new Map,this.injectStyles(),this.loadBoxicons()}loadBoxicons(){if(!document.querySelector('link[href*="boxicons"]')){const t=document.createElement("link");t.rel="stylesheet",t.href="https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css",document.head.appendChild(t)}}injectStyles(){const t=document.createElement("style");t.textContent="\n .notification-overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.4);\n backdrop-filter: blur(4px);\n -webkit-backdrop-filter: blur(4px);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 9999;\n opacity: 0;\n overflow: hidden;\n }\n\n .notification-box {\n background: white;\n border-radius: 16px;\n padding: 40px 30px;\n max-width: 500px;\n width: 90%;\n max-height: 80vh;\n overflow: auto;\n position: relative;\n box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);\n text-align: center;\n transform: scale(0.7);\n opacity: 0;\n }\n\n .notification-content {\n text-align: left;\n margin-bottom: 18px;\n }\n\n .notification-close {\n position: absolute;\n top: 10px;\n right: 10px;\n width: 38px;\n height: 38px;\n border-radius: 8px;\n border: none;\n background: rgba(0,0,0,0.06);\n color: #111827;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n font-size: 18px;\n }\n\n .notification-close:hover {\n background: rgba(0,0,0,0.09);\n }\n\n /* Form controls inside the modal */\n .notification-box input,\n .notification-box textarea,\n .notification-box select {\n width: 100%;\n padding: 10px 12px;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n background: #ffffff;\n color: #111827;\n font-size: 15px;\n box-sizing: border-box;\n transition: box-shadow 0.15s ease, border-color 0.15s ease;\n }\n\n .notification-box input:focus,\n .notification-box textarea:focus,\n .notification-box select:focus {\n outline: none;\n border-color: #6366f1;\n box-shadow: 0 6px 24px rgba(99,102,241,0.12), 0 0 0 4px rgba(99,102,241,0.06);\n }\n\n .notification-box label { display: block; margin-bottom: 6px; color: #374151; font-weight: 600; }\n\n /* Soporte para tema oscuro con clase .dark (Tailwind darkMode: 'class') */\n /* Esto tiene prioridad sobre prefers-color-scheme para respetar la elección del usuario en la web */\n .dark .notification-box { background: #0f1724 !important; color: #e6eef8 !important; }\n .dark .notification-box input,\n .dark .notification-box textarea,\n .dark .notification-box select {\n background: #0b1220 !important;\n border: 1px solid rgba(255,255,255,0.06) !important;\n color: #e6eef8 !important;\n }\n .dark .notification-box .notification-close { background: rgba(255,255,255,0.03) !important; color: #e6eef8 !important; }\n .dark .notification-overlay { background-color: rgba(0,0,0,0.6) !important; }\n .dark .notification-title { color: #e6eef8 !important; }\n .dark .notification-message { color: #cbd5e1 !important; }\n\n /* Forzar modo claro cuando NO hay clase .dark, ignorando prefers-color-scheme */\n html:not(.dark) .notification-box { background: white !important; color: #111827 !important; }\n html:not(.dark) .notification-box input,\n html:not(.dark) .notification-box textarea,\n html:not(.dark) .notification-box select {\n background: #ffffff !important;\n border: 1px solid #e5e7eb !important;\n color: #111827 !important;\n }\n html:not(.dark) .notification-box .notification-close { background: rgba(0,0,0,0.06) !important; color: #111827 !important; }\n html:not(.dark) .notification-overlay { background-color: rgba(0, 0, 0, 0.4) !important; }\n html:not(.dark) .notification-title { color: #1f2937 !important; }\n html:not(.dark) .notification-message { color: #6b7280 !important; }\n\n .notification-icon {\n width: 80px;\n height: 80px;\n border-radius: 50%;\n margin: 0 auto 25px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 40px;\n position: relative;\n }\n\n .notification-icon::before {\n content: '';\n position: absolute;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n opacity: 0.2;\n }\n\n .notification-icon.success {\n background: linear-gradient(135deg, #10b981 0%, #059669 100%);\n color: white;\n }\n\n .notification-icon.success::before {\n background: #10b981;\n }\n\n .notification-icon.error {\n background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);\n color: white;\n }\n\n .notification-icon.error::before {\n background: #ef4444;\n }\n\n .notification-icon.warning {\n background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n color: white;\n }\n\n .notification-icon.warning::before {\n background: #f59e0b;\n }\n\n .notification-icon.info {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: white;\n }\n\n .notification-icon.info::before {\n background: #3b82f6;\n }\n .notification-icon.question {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: white;\n }\n\n .notification-icon.question::before {\n background: #3b82f6;\n }\n\n .notification-title {\n font-size: 24px;\n font-weight: 700;\n color: #1f2937;\n margin-bottom: 12px;\n line-height: 1.3;\n }\n\n .notification-message {\n font-size: 16px;\n color: #6b7280;\n line-height: 1.6;\n margin-bottom: 30px;\n }\n\n .notification-button {\n color: white;\n border: none;\n padding: 10px 14px;\n border-radius: 8px;\n font-size: 16px;\n font-weight: 600;\n cursor: pointer;\n transition: all 0.3s ease;\n }\n\n .notification-button:hover {\n transform: translateY(-2px);\n filter: brightness(1.1);\n }\n\n .notification-button:active {\n transform: translateY(0);\n }\n\n /* group container for multiple action buttons */\n .notification-button-group {\n display: flex;\n gap: 12px;\n justify-content: center;\n flex-wrap: wrap;\n margin-top: 10px;\n }\n\n .notification-icon-checkmark {\n animation: checkmark-draw 0.6s ease-in-out;\n }\n\n .notification-icon-cross {\n animation: cross-draw 0.5s ease-in-out;\n }\n\n @keyframes checkmark-draw {\n 0% {\n transform: scale(0) rotate(-45deg);\n opacity: 0;\n }\n 50% {\n transform: scale(1.2) rotate(-45deg);\n }\n 100% {\n transform: scale(1) rotate(0deg);\n opacity: 1;\n }\n }\n\n @keyframes cross-draw {\n 0% {\n transform: scale(0) rotate(-180deg);\n opacity: 0;\n }\n 50% {\n transform: scale(1.2) rotate(-90deg);\n }\n 100% {\n transform: scale(1) rotate(0deg);\n opacity: 1;\n }\n }\n\n /* Loading spinner styles */\n .notification-loading-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n margin: 0 auto;\n }\n\n .notification-spinner {\n width: 60px;\n height: 60px;\n border: 5px solid rgba(99, 102, 241, 0.15);\n border-top-color: #6366f1;\n border-radius: 50%;\n animation: notification-spin 1s linear infinite;\n margin: 0 auto;\n }\n\n @keyframes notification-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n .notification-loading-text {\n font-size: 14px;\n color: #6b7280;\n text-align: center;\n margin-top: 12px;\n }\n\n .dark .notification-loading-text {\n color: #cbd5e1;\n }\n\n /* ==================== Toast ==================== */\n .notify-toast-container {\n position: fixed;\n z-index: 10000;\n display: flex;\n flex-direction: column;\n gap: 10px;\n pointer-events: none;\n width: 360px;\n max-width: calc(100vw - 40px);\n }\n .notify-toast-top-right { top: 20px; right: 20px; }\n .notify-toast-top-left { top: 20px; left: 20px; }\n .notify-toast-top-center { top: 20px; left: 50%; transform: translateX(-50%); }\n .notify-toast-bottom-right { bottom: 20px; right: 20px; flex-direction: column-reverse; }\n .notify-toast-bottom-left { bottom: 20px; left: 20px; flex-direction: column-reverse; }\n\n .notify-toast {\n background: white;\n border-radius: 12px;\n padding: 14px 40px 14px 14px;\n box-shadow: 0 4px 24px rgba(0,0,0,0.12), 0 1px 4px rgba(0,0,0,0.06);\n display: flex;\n align-items: flex-start;\n gap: 12px;\n pointer-events: auto;\n position: relative;\n overflow: hidden;\n opacity: 0;\n transform: translateX(30px);\n transition: opacity 0.25s ease, transform 0.25s ease;\n }\n .notify-toast-top-left .notify-toast,\n .notify-toast-bottom-left .notify-toast { transform: translateX(-30px); }\n .notify-toast-top-center .notify-toast { transform: translateY(-20px); }\n .notify-toast.notify-toast-visible {\n opacity: 1;\n transform: translateX(0) translateY(0) !important;\n }\n\n .notify-toast-icon {\n width: 36px;\n height: 36px;\n border-radius: 50%;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 20px;\n flex-shrink: 0;\n color: white;\n }\n .notify-toast-icon.success { background: linear-gradient(135deg, #10b981 0%, #059669 100%); }\n .notify-toast-icon.error { background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); }\n .notify-toast-icon.warning { background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); }\n .notify-toast-icon.info { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); }\n .notify-toast-icon.question { background: linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%); }\n .notify-toast-icon.loading { background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%); }\n\n .notify-toast-content { flex: 1; min-width: 0; }\n .notify-toast-title {\n font-size: 14px;\n font-weight: 700;\n color: #1f2937;\n margin-bottom: 2px;\n line-height: 1.3;\n cursor: default;\n }\n .notify-toast-message {\n font-size: 13px;\n color: #6b7280;\n line-height: 1.5;\n cursor: default;\n }\n\n .notify-toast-close {\n position: absolute;\n top: 8px;\n right: 8px;\n width: 24px;\n height: 24px;\n border-radius: 6px;\n border: none;\n background: rgba(0,0,0,0.06);\n color: #6b7280;\n cursor: pointer;\n font-size: 16px;\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n padding: 0;\n }\n .notify-toast-close:hover { background: rgba(0,0,0,0.1); color: #374151; }\n\n /* Sin botón de cierre: reducir padding derecho */\n .notify-toast.notify-toast-no-close { padding-right: 14px; }\n\n .notify-toast-progress {\n position: absolute;\n bottom: 0;\n left: 0;\n height: 3px;\n width: 100%;\n border-radius: 0 0 0 12px;\n }\n .notify-toast-progress.success { background: #10b981; }\n .notify-toast-progress.error { background: #ef4444; }\n .notify-toast-progress.warning { background: #f59e0b; }\n .notify-toast-progress.info { background: #3b82f6; }\n .notify-toast-progress.question { background: #8b5cf6; }\n .notify-toast-progress.loading { background: #6366f1; }\n\n /* Spinner para toast de carga */\n .notify-toast-spinner {\n width: 18px;\n height: 18px;\n border: 2.5px solid rgba(255,255,255,0.35);\n border-top-color: white;\n border-radius: 50%;\n animation: notification-spin 0.8s linear infinite;\n flex-shrink: 0;\n }\n\n .dark .notify-toast { background: #0f1724; box-shadow: 0 4px 24px rgba(0,0,0,0.35); }\n .dark .notify-toast-title { color: #e6eef8; }\n .dark .notify-toast-message { color: #cbd5e1; }\n .dark .notify-toast-close { background: rgba(255,255,255,0.06); color: #94a3b8; }\n .dark .notify-toast-close:hover { background: rgba(255,255,255,0.1); color: #e2e8f0; }\n\n /* Respeta la preferencia de movimiento reducido del sistema */\n @media (prefers-reduced-motion: reduce) {\n .notify-toast {\n transition: opacity 0.1s ease !important;\n transform: none !important;\n }\n .notify-toast.notify-toast-visible {\n transform: none !important;\n }\n .notify-toast-spinner {\n animation-duration: 1.5s !important;\n }\n .notify-toast-progress {\n transition: none !important;\n }\n }\n ",document.head.appendChild(t)}getIcon(t){const n={success:'<i class="bx bx-check" aria-hidden="true"></i>',error:'<i class="bx bx-x" aria-hidden="true"></i>',warning:'<i class="bx bx-error" aria-hidden="true"></i>',info:'<i class="bx bx-info-circle" aria-hidden="true"></i>',question:'<i class="bx bx-question-mark" aria-hidden="true"></i>',loading:'<div class="notify-toast-spinner" aria-hidden="true"></div>'};return n[t]||n.info}getDefaultTitle(t){return{success:"¡Éxito!",error:"Error",warning:"Advertencia",info:"Información",question:"Pregunta"}[t]||"Notificación"}getButtonGradient(t){const n={success:"linear-gradient(135deg, #10b981 0%, #059669 100%)",error:"linear-gradient(135deg, #ef4444 0%, #dc2626 100%)",warning:"linear-gradient(135deg, #f59e0b 0%, #d97706 100%)",info:"linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)",question:"linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)"};return n[t]||n.info}getButtonShadow(t){const n={success:"rgba(16, 185, 129, 0)",error:"rgba(239, 68, 68, 0)",warning:"rgba(245, 159, 11, 0)",info:"rgba(59, 131, 246, 0)",question:"rgba(108, 99, 245, 0)"};return n[t]||n.info}show(t={}){if(this.currentNotification){const t=this.currentNotification;this.currentNotification=null;try{t&&t.parentNode&&t.parentNode.removeChild(t)}catch(t){}}const{type:n="info",title:e=this.getDefaultTitle(n),message:o="",buttonText:i="OK",buttonColor:a=null,onClose:r=null,timer:s=null,allowOutsideClick:c=!0,allowEscapeKey:l=!0,hideButton:d=!1,buttons:f=null}=t,u=!0===t.showCloseButton;try{document.body.style.overflow="hidden"}catch(t){}try{document.documentElement.style.overflow="hidden"}catch(t){}const p=document.createElement("div");p.className="notification-overlay",p.tabIndex=-1,p.setAttribute("role","dialog"),p.setAttribute("aria-modal","true"),p.style.pointerEvents="auto";const m=document.createElement("div");m.className="notification-box";const b=document.createElement("div");b.className=`notification-icon ${n}`,d&&"info"===n?(b.className="notification-loading-container",b.innerHTML='<div class="notification-spinner"></div>',b.style.background="transparent",b.style.boxShadow="none",b.style.width="100px",b.style.height="100px"):b.innerHTML=this.getIcon(n);const g=document.createElement("h3");g.className="notification-title",g.textContent=e;const h=document.createElement("p");h.className="notification-message",h.textContent=o;let x=null;if(t.html||t.content)if(x=document.createElement("div"),x.className="notification-content",t.html)try{x.innerHTML=t.html}catch(n){x.textContent=t.html}else t.content&&t.content instanceof HTMLElement&&x.appendChild(t.content);const y=()=>this.close(r);let w=null,v=null;if(!d)if(Array.isArray(f)&&f.length)v=document.createElement("div"),v.className="notification-button-group",f.forEach(t=>{const e=document.createElement("button");e.className="notification-button",e.textContent=t.text||"OK";const o=t.color||this.getButtonGradient(n),i=t.shadowColor||this.getButtonShadow(n);e.style.background=o,e.style.boxShadow=`0 4px 12px ${i}`,e.addEventListener("click",n=>{n.stopPropagation(),n.preventDefault();try{y().then(()=>{if("function"==typeof t.onClick)try{const n=t.onClick();n&&"function"==typeof n.then&&n.catch(t=>console.error(t))}catch(t){console.error(t)}}).catch(()=>{})}catch(t){console.error(t)}}),e.addEventListener("mouseenter",()=>{e.style.boxShadow=`0 6px 16px ${i}`}),e.addEventListener("mouseleave",()=>{e.style.boxShadow=`0 4px 12px ${i}`}),v.appendChild(e)});else if(t.onConfirm||t.onCancel||t.confirmText||t.cancelText){v=document.createElement("div"),v.className="notification-button-group";const e=t.cancelText||"Cancelar",o=t.confirmText||"Aceptar",i=document.createElement("button");i.className="notification-button",i.textContent=e;const a=t.cancelColor||"linear-gradient(135deg, #9ca3af 0%, #6b7280 100%)",r=t.cancelShadow||"rgba(107,114,128,0.25)";i.style.background=a,i.style.boxShadow=`0 4px 12px ${r}`,i.addEventListener("click",n=>{n.stopPropagation(),n.preventDefault(),y().then(()=>{try{if("function"==typeof t.onCancel){const n=t.onCancel();n&&"function"==typeof n.then&&n.catch(t=>console.error(t))}}catch(t){console.error(t)}}).catch(()=>{})}),i.addEventListener("mouseenter",()=>{i.style.boxShadow=`0 6px 16px ${r}`}),i.addEventListener("mouseleave",()=>{i.style.boxShadow=`0 4px 12px ${r}`});const s=document.createElement("button");s.className="notification-button",s.textContent=o;const c=t.confirmColor||this.getButtonGradient(n),l=t.confirmShadow||this.getButtonShadow(n);s.style.background=c,s.style.boxShadow=`0 4px 12px ${l}`,s.addEventListener("click",async n=>{n.stopPropagation(),n.preventDefault();try{if(await y(),"function"==typeof t.onConfirm){const n=t.onConfirm();n&&"function"==typeof n.then&&await n}}catch(t){console.error(t)}}),s.addEventListener("mouseenter",()=>{s.style.boxShadow=`0 6px 16px ${l}`}),s.addEventListener("mouseleave",()=>{s.style.boxShadow=`0 4px 12px ${l}`}),v.appendChild(i),v.appendChild(s)}else if(i){w=document.createElement("button"),w.className="notification-button",w.textContent=i;const t=a||this.getButtonGradient(n),e=this.getButtonShadow(n);w.style.background=t,w.style.boxShadow=`0 4px 12px ${e}`}let k=null;if(u&&(k=document.createElement("button"),k.setAttribute("aria-label","Cerrar"),k.className="notification-close",k.innerHTML="×",k.addEventListener("click",t=>{t.stopPropagation(),y()})),m.appendChild(b),x){const t="notify-desc-"+Date.now();x.id=t,p.setAttribute("aria-describedby",t),m.appendChild(x)}else m.appendChild(g),m.appendChild(h);k&&m.appendChild(k),v?m.appendChild(v):w&&m.appendChild(w),p.appendChild(m),document.body.appendChild(p);const E=p,C=new Promise(t=>{try{E._externalResolve=t}catch(t){}});try{const t=document.getElementById("notify-live");t&&(t.textContent=`${e}: ${o}`)}catch(t){}try{this._lastActiveElement=document.activeElement}catch(t){this._lastActiveElement=null}this.currentNotification=p;try{const t=m.querySelectorAll('a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])');t&&t.length?t[0].focus():w?w.focus():p.focus()}catch(t){try{p.focus()}catch(t){}}const _=t=>{if("Tab"!==t.key)return;const n=Array.from(m.querySelectorAll('a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])')).filter(t=>t instanceof HTMLElement&&null!==t.offsetParent);if(!n.length)return void t.preventDefault();const e=n[0],o=n[n.length-1];t.shiftKey||document.activeElement!==o?t.shiftKey&&document.activeElement===e&&(t.preventDefault(),o.focus()):(t.preventDefault(),e.focus())};E._focusTrap=_,document.addEventListener("keydown",_);const T=t.anim||{},N="number"==typeof T.overlayDuration?T.overlayDuration:150,L=T.overlayEasing||"easeOutQuad",S="number"==typeof T.boxDuration?T.boxDuration:200,j="number"==typeof T.boxDelay?T.boxDelay:50,O=T.boxEasing||"easeOutBack",D="number"==typeof T.boxStartScale?T.boxStartScale:.8,A="number"==typeof T.iconDuration?T.iconDuration:250,$="number"==typeof T.iconDelay?T.iconDelay:100,P="number"==typeof T.iconRotate?T.iconRotate:"success"===n?-90:"error"===n?90:0;if("number"==typeof T.overlayOpacity&&(p.style.backgroundColor=`rgba(0,0,0,${T.overlayOpacity})`),anime({targets:p,opacity:[0,1],duration:N,easing:L}),anime({targets:m,scale:[D,1],opacity:[0,1],duration:S,easing:O,delay:j}),anime({targets:b,scale:[0,1],rotate:[P,0],duration:A,easing:O,delay:$}),w){const t=this.getButtonShadow(n);w.addEventListener("mouseenter",()=>{w.style.boxShadow=`0 6px 16px ${t}`}),w.addEventListener("mouseleave",()=>{w.style.boxShadow=`0 4px 12px ${t}`}),w.addEventListener("click",t=>{t.stopPropagation(),t.preventDefault(),y().catch(()=>{})})}if(c&&p.addEventListener("click",t=>{m.contains(t.target)||y()}),s&&setTimeout(()=>{y()},s),l){const t=n=>{"Escape"===n.key&&(y(),document.removeEventListener("keydown",t))};E._escHandler=t,document.addEventListener("keydown",t)}return C}close(t=null){if(!this.currentNotification)return Promise.resolve();const n=this.currentNotification,e=n,o=n.querySelector(".notification-box");return this.currentNotification=null,anime({targets:o,scale:.8,opacity:0,duration:100,easing:"easeInQuad"}),new Promise(o=>{anime({targets:n,opacity:0,duration:100,easing:"easeInQuad",complete:()=>{try{e&&e._escHandler&&(document.removeEventListener("keydown",e._escHandler),e._escHandler=void 0)}catch(t){}try{e&&e._focusTrap&&(document.removeEventListener("keydown",e._focusTrap),e._focusTrap=void 0)}catch(t){}try{if(e&&"function"==typeof e._externalResolve){try{e._externalResolve()}catch(t){}e._externalResolve=void 0}}catch(t){}try{n&&n.parentNode&&n.parentNode.removeChild(n)}catch(t){try{n.remove()}catch(t){}}if(!this.currentNotification){try{document.body.style.overflow=""}catch(t){}try{document.documentElement.style.overflow=""}catch(t){}}try{this._lastActiveElement&&"function"==typeof this._lastActiveElement.focus&&this._lastActiveElement.focus()}catch(t){}this._lastActiveElement=null,t&&t(),o()}})})}success(t,n=null,e={}){this.show(Object.assign({type:"success",title:n||this.getDefaultTitle("success"),message:t},e))}error(t,n=null,e={}){this.show(Object.assign({type:"error",title:n||this.getDefaultTitle("error"),message:t},e))}warning(t,n=null,e={}){this.show(Object.assign({type:"warning",title:n||this.getDefaultTitle("warning"),message:t},e))}question(t,n=null,e={}){this.show(Object.assign({type:"question",title:n||this.getDefaultTitle("question"),message:t},e))}info(t,n=null,e={}){this.show(Object.assign({type:"info",title:n||this.getDefaultTitle("info"),message:t},e))}loading(t="Cargando...",n="Espera",e={}){const o=Object.assign({type:"info",title:n,message:t,hideButton:!0,allowOutsideClick:!1,allowEscapeKey:!1},e),i=this.show(o);return this._currentLoadingPromise=i,i}closeLoading(t=null){return this._currentLoadingPromise=null,this.close(t)}hide(t=null){return this.close(t)}hiden(t=null){return this.close(t)}_formatTime(t){const n=Math.max(0,Math.floor(t));return`${Math.floor(n/60).toString().padStart(2,"0")}:${(n%60).toString().padStart(2,"0")}`}showToast(t,n={}){var e,o;const i=n.type||"info",a=null!==(e=n.title)&&void 0!==e?e:null,r="number"==typeof n.duration?n.duration:4e3,s=n.position||"top-right",c=!1!==n.showProgress,l=null!==(o=n.id)&&void 0!==o?o:null,d=!1!==n.closeable;if(null!==l){const t=this._toastInstances.get(l);if(t)return void t.reset(r)}let f=this._toastContainers.get(s);f&&document.body.contains(f)||(f=document.createElement("div"),f.className=`notify-toast-container notify-toast-${s}`,f.setAttribute("aria-label","Notificaciones"),document.body.appendChild(f),this._toastContainers.set(s,f));const u=s.startsWith("bottom"),p="top-center"===s,m=document.createElement("div");m.className="notify-toast",d||m.classList.add("notify-toast-no-close"),"error"===i||"warning"===i?m.setAttribute("role","alert"):m.setAttribute("role","status"),m.setAttribute("aria-atomic","true"),m.setAttribute("aria-live","error"===i||"warning"===i?"assertive":"polite");const b=document.createElement("div");b.className=`notify-toast-icon ${i}`,b.innerHTML=this.getIcon(i);const g=document.createElement("div");if(g.className="notify-toast-content",a){const t=document.createElement("div");t.className="notify-toast-title",t.textContent=a,g.appendChild(t)}const h=document.createElement("div");if(h.className="notify-toast-message",h.textContent=t,g.appendChild(h),m.appendChild(b),m.appendChild(g),d){const t=document.createElement("button");t.className="notify-toast-close",t.setAttribute("aria-label","Cerrar notificación"),t.innerHTML="×",t.addEventListener("click",E),m.appendChild(t)}let x=null;r>0&&c&&(x=document.createElement("div"),x.className=`notify-toast-progress ${i}`,x.setAttribute("role","progressbar"),x.setAttribute("aria-hidden","true"),m.appendChild(x)),u||p?f.appendChild(m):f.insertBefore(m,f.firstChild);let y=!1,w=null,v=r,k=0;function E(){if(y)return Promise.resolve();if(y=!0,m.contains(document.activeElement))try{document.activeElement.blur()}catch(t){}return m.classList.remove("notify-toast-visible"),new Promise(t=>{setTimeout(()=>{m.parentNode&&m.parentNode.removeChild(m),t()},300)})}const C=t=>{k=Date.now(),w=setTimeout(()=>{null!==l&&this._toastInstances.delete(l),E()},t),x&&(x.style.transition=`width ${t}ms linear`,x.style.width="0%")},_=t=>{y||(null!==w&&(clearTimeout(w),w=null),v=t,t>0?(x&&(x.style.transition="none",x.style.width="100%",x.offsetWidth),C(t)):x&&(x.style.transition="none",x.style.width="100%"))};if(null!==l){const t=()=>{if(!y){if(y=!0,null!==w&&clearTimeout(w),m.contains(document.activeElement))try{document.activeElement.blur()}catch(t){}m.parentNode&&m.parentNode.removeChild(m)}};this._toastInstances.set(l,{reset:_,dismiss:E,_silentDismiss:t})}requestAnimationFrame(()=>{requestAnimationFrame(()=>{m.classList.add("notify-toast-visible"),r>0&&C(r)})}),r>0&&d&&(m.addEventListener("mouseenter",()=>{if(y||null===w)return;clearTimeout(w),w=null;const t=Date.now()-k;if(v=Math.max(0,v-t),x){const t=v/r*100;x.style.transition="none",x.style.width=`${t}%`}}),m.addEventListener("mouseleave",()=>{y||v<=0||C(v)}))}toast(t,n={}){if("string"==typeof t)this.showToast(t,n);else{const{message:n=""}=t,e=__rest(t,["message"]);this.showToast(n,e)}}toastSuccess(t,n,e={}){this.showToast(t,Object.assign(Object.assign({},e),{type:"success",title:null!=n?n:e.title}))}toastError(t,n,e={}){this.showToast(t,Object.assign(Object.assign({},e),{type:"error",title:null!=n?n:e.title}))}toastWarning(t,n,e={}){this.showToast(t,Object.assign(Object.assign({},e),{type:"warning",title:null!=n?n:e.title}))}toastInfo(t,n,e={}){this.showToast(t,Object.assign(Object.assign({},e),{type:"info",title:null!=n?n:e.title}))}toastQuestion(t,n,e={}){this.showToast(t,Object.assign(Object.assign({},e),{type:"question",title:null!=n?n:e.title}))}toastLoading(t="Cargando...",n,e={}){this.showToast(t,Object.assign(Object.assign({position:"top-right"},e),{type:"loading",title:null!=n?n:e.title,id:"__loading__",closeable:!1,duration:0,showProgress:!1}))}closeToastLoading(){const t=this._toastInstances.get("__loading__");return t?(this._toastInstances.delete("__loading__"),t.dismiss()):Promise.resolve()}replaceToastLoading(t,n={}){const e=this._toastInstances.get("__loading__");e&&(this._toastInstances.delete("__loading__"),e._silentDismiss()),this.showToast(t,n)}},n=window;n.notify=t,n.Notification=t}}();
|
package/package.json
CHANGED