fernotify 1.2.5 → 1.2.8

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
@@ -8,7 +8,7 @@
8
8
 
9
9
  ## Características
10
10
 
11
- - **4 tipos de notificaciones**: Success, Error, Warning, Info
11
+ - **5 tipos de notificaciones**: Success, Error, Warning, Info, Question
12
12
  - **Dark Mode automático**: Detecta el tema de tu web
13
13
  - **Animaciones fluidas**: Powered by anime.js
14
14
  - **Ligero y rápido**: ~10KB sin dependencias (excepto anime.js)
@@ -98,6 +98,9 @@ notify.warning('Esta acción no se puede deshacer');
98
98
 
99
99
  // Info
100
100
  notify.info('Hay una nueva actualización disponible');
101
+
102
+ // Question (nuevo)
103
+ notify.question('¿Seguro que quieres continuar?', 'Confirmación');
101
104
  ```
102
105
 
103
106
  ### Con Título Personalizado
@@ -188,6 +191,7 @@ notify.success(message, title?, options?)
188
191
  notify.error(message, title?, options?)
189
192
  notify.warning(message, title?, options?)
190
193
  notify.info(message, title?, options?)
194
+ notify.question(message, title?, options?)
191
195
  notify.close() // Cerrar la notificación actual
192
196
  ```
193
197
 
@@ -215,6 +215,14 @@
215
215
  .notification-icon.info::before {
216
216
  background: #3b82f6;
217
217
  }
218
+ .notification-icon.question {
219
+ background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
220
+ color: white;
221
+ }
222
+
223
+ .notification-icon.question::before {
224
+ background: #3b82f6;
225
+ }
218
226
 
219
227
  .notification-title {
220
228
  font-size: 24px;
@@ -339,7 +347,8 @@
339
347
  'success': '<i class="bx bx-check" aria-hidden="true"></i>',
340
348
  'error': '<i class="bx bx-x" aria-hidden="true"></i>',
341
349
  'warning': '<i class="bx bx-error" aria-hidden="true"></i>',
342
- 'info': '<i class="bx bx-info-circle" aria-hidden="true"></i>'
350
+ 'info': '<i class="bx bx-info-circle" aria-hidden="true"></i>',
351
+ 'question': '<i class="bx bx-question-mark" aria-hidden="true"></i>'
343
352
  };
344
353
  return icons[type] || icons.info;
345
354
  }
@@ -348,7 +357,8 @@
348
357
  'success': '¡Éxito!',
349
358
  'error': 'Error',
350
359
  'warning': 'Advertencia',
351
- 'info': 'Información'
360
+ 'info': 'Información',
361
+ 'question': 'Pregunta'
352
362
  };
353
363
  return titles[type] || 'Notificación';
354
364
  }
@@ -357,16 +367,18 @@
357
367
  'success': 'linear-gradient(135deg, #10b981 0%, #059669 100%)',
358
368
  'error': 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)',
359
369
  'warning': 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
360
- 'info': 'linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)'
370
+ 'info': 'linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)',
371
+ 'question': 'linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)'
361
372
  };
362
373
  return gradients[type] || gradients.info;
363
374
  }
364
375
  getButtonShadow(type) {
365
376
  const shadows = {
366
- 'success': 'rgba(16, 185, 129, 0.4)',
367
- 'error': 'rgba(239, 68, 68, 0.4)',
368
- 'warning': 'rgba(245, 158, 11, 0.4)',
369
- 'info': 'rgba(59, 130, 246, 0.4)'
377
+ 'success': 'rgba(16, 185, 129, 0)',
378
+ 'error': 'rgba(239, 68, 68, 0)',
379
+ 'warning': 'rgba(245, 159, 11, 0)',
380
+ 'info': 'rgba(59, 131, 246, 0)',
381
+ 'question': 'rgba(108, 99, 245, 0)'
370
382
  };
371
383
  return shadows[type] || shadows.info;
372
384
  }
@@ -808,6 +820,9 @@
808
820
  warning(message, title = null, options = {}) {
809
821
  this.show(Object.assign({ type: 'warning', title: title || this.getDefaultTitle('warning'), message }, options));
810
822
  }
823
+ question(message, title = null, options = {}) {
824
+ this.show(Object.assign({ type: 'question', title: title || this.getDefaultTitle('question'), message }, options));
825
+ }
811
826
  info(message, title = null, options = {}) {
812
827
  this.show(Object.assign({ type: 'info', title: title || this.getDefaultTitle('info'), message }, options));
813
828
  }
@@ -831,8 +846,10 @@
831
846
  return `${mm}:${ss}`;
832
847
  }
833
848
  }
834
- window.notify = new NotificationSystem();
835
- window.Notification = window.notify;
849
+ const notifyInstance = new NotificationSystem();
850
+ const w = window;
851
+ w.notify = notifyInstance;
852
+ w.Notification = notifyInstance;
836
853
  }
837
854
  })();
838
855
  //# sourceMappingURL=notification-system.js.map
@@ -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(){window.notify=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\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>'};return t[n]||t.info}getDefaultTitle(n){return{success:"¡Éxito!",error:"Error",warning:"Advertencia",info:"Información"}[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%)"};return t[n]||t.info}getButtonShadow(n){const t={success:"rgba(16, 185, 129, 0.4)",error:"rgba(239, 68, 68, 0.4)",warning:"rgba(245, 158, 11, 0.4)",info:"rgba(59, 130, 246, 0.4)"};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:f=null}=n,u=!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 h=document.createElement("div");h.className=`notification-icon ${t}`,d&&"info"===t?(h.className="notification-loading-container",h.innerHTML='<div class="notification-spinner"></div>',h.style.background="transparent",h.style.boxShadow="none",h.style.width="100px",h.style.height="100px"):h.innerHTML=this.getIcon(t);const b=document.createElement("h3");b.className="notification-title",b.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(f)&&f.length)v=document.createElement("div"),v.className="notification-button-group",f.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(u&&(k=document.createElement("button"),k.setAttribute("aria-label","Cerrar"),k.className="notification-close",k.innerHTML="&times;",k.addEventListener("click",n=>{n.stopPropagation(),y()})),m.appendChild(h),x){const n="notify-desc-"+Date.now();x.id=n,p.setAttribute("aria-describedby",n),m.appendChild(x)}else m.appendChild(b),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:h,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))}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")}`}},window.Notification=window.notify}}();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";!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="&times;",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};
@@ -200,6 +200,14 @@
200
200
  .notification-icon.info::before {
201
201
  background: #3b82f6;
202
202
  }
203
+ .notification-icon.question {
204
+ background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
205
+ color: white;
206
+ }
207
+
208
+ .notification-icon.question::before {
209
+ background: #3b82f6;
210
+ }
203
211
 
204
212
  .notification-title {
205
213
  font-size: 24px;
@@ -324,7 +332,8 @@
324
332
  'success': '<i class="bx bx-check" aria-hidden="true"></i>',
325
333
  'error': '<i class="bx bx-x" aria-hidden="true"></i>',
326
334
  'warning': '<i class="bx bx-error" aria-hidden="true"></i>',
327
- 'info': '<i class="bx bx-info-circle" aria-hidden="true"></i>'
335
+ 'info': '<i class="bx bx-info-circle" aria-hidden="true"></i>',
336
+ 'question': '<i class="bx bx-question-mark" aria-hidden="true"></i>'
328
337
  };
329
338
  return icons[type] || icons.info;
330
339
  }
@@ -333,7 +342,8 @@
333
342
  'success': '¡Éxito!',
334
343
  'error': 'Error',
335
344
  'warning': 'Advertencia',
336
- 'info': 'Información'
345
+ 'info': 'Información',
346
+ 'question': 'Pregunta'
337
347
  };
338
348
  return titles[type] || 'Notificación';
339
349
  }
@@ -342,16 +352,18 @@
342
352
  'success': 'linear-gradient(135deg, #10b981 0%, #059669 100%)',
343
353
  'error': 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)',
344
354
  'warning': 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
345
- 'info': 'linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)'
355
+ 'info': 'linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)',
356
+ 'question': 'linear-gradient(135deg, #8b5cf6 0%, #6366f1 100%)'
346
357
  };
347
358
  return gradients[type] || gradients.info;
348
359
  }
349
360
  getButtonShadow(type) {
350
361
  const shadows = {
351
- 'success': 'rgba(16, 185, 129, 0.4)',
352
- 'error': 'rgba(239, 68, 68, 0.4)',
353
- 'warning': 'rgba(245, 158, 11, 0.4)',
354
- 'info': 'rgba(59, 130, 246, 0.4)'
362
+ 'success': 'rgba(16, 185, 129, 0)',
363
+ 'error': 'rgba(239, 68, 68, 0)',
364
+ 'warning': 'rgba(245, 159, 11, 0)',
365
+ 'info': 'rgba(59, 131, 246, 0)',
366
+ 'question': 'rgba(108, 99, 245, 0)'
355
367
  };
356
368
  return shadows[type] || shadows.info;
357
369
  }
@@ -793,6 +805,9 @@
793
805
  warning(message, title = null, options = {}) {
794
806
  this.show(Object.assign({ type: 'warning', title: title || this.getDefaultTitle('warning'), message }, options));
795
807
  }
808
+ question(message, title = null, options = {}) {
809
+ this.show(Object.assign({ type: 'question', title: title || this.getDefaultTitle('question'), message }, options));
810
+ }
796
811
  info(message, title = null, options = {}) {
797
812
  this.show(Object.assign({ type: 'info', title: title || this.getDefaultTitle('info'), message }, options));
798
813
  }
@@ -816,8 +831,10 @@
816
831
  return `${mm}:${ss}`;
817
832
  }
818
833
  }
819
- window.notify = new NotificationSystem();
820
- window.Notification = window.notify;
834
+ const notifyInstance = new NotificationSystem();
835
+ const w = window;
836
+ w.notify = notifyInstance;
837
+ w.Notification = notifyInstance;
821
838
  }
822
839
  })();
823
840
  //# sourceMappingURL=notification-system.js.map
@@ -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(){window.notify=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\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>'};return t[n]||t.info}getDefaultTitle(n){return{success:"¡Éxito!",error:"Error",warning:"Advertencia",info:"Información"}[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%)"};return t[n]||t.info}getButtonShadow(n){const t={success:"rgba(16, 185, 129, 0.4)",error:"rgba(239, 68, 68, 0.4)",warning:"rgba(245, 158, 11, 0.4)",info:"rgba(59, 130, 246, 0.4)"};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 h=document.createElement("div");h.className=`notification-icon ${t}`,d&&"info"===t?(h.className="notification-loading-container",h.innerHTML='<div class="notification-spinner"></div>',h.style.background="transparent",h.style.boxShadow="none",h.style.width="100px",h.style.height="100px"):h.innerHTML=this.getIcon(t);const b=document.createElement("h3");b.className="notification-title",b.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="&times;",k.addEventListener("click",n=>{n.stopPropagation(),y()})),m.appendChild(h),x){const n="notify-desc-"+Date.now();x.id=n,p.setAttribute("aria-describedby",n),m.appendChild(x)}else m.appendChild(b),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,A=N.boxEasing||"easeOutBack",$="number"==typeof N.boxStartScale?N.boxStartScale:.8,j="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:[$,1],opacity:[0,1],duration:D,easing:A,delay:_}),anime({targets:h,scale:[0,1],rotate:[O,0],duration:j,easing:A,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))}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")}`}},window.Notification=window.notify}}();
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="&times;",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}}();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fernotify",
3
- "version": "1.2.5",
3
+ "version": "1.2.8",
4
4
  "description": "Sistema moderno de notificaciones con animaciones fluidas y soporte completo de Dark Mode",
5
5
  "main": "dist/notification-system.js",
6
6
  "module": "dist/notification-system.esm.js",