fernotify 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ !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 .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}=n,f=!0===n.showCloseButton;try{document.body.style.overflow="hidden"}catch(n){}try{document.documentElement.style.overflow="hidden"}catch(n){}const u=document.createElement("div");u.className="notification-overlay",u.tabIndex=-1,u.setAttribute("role","dialog"),u.setAttribute("aria-modal","true"),u.style.pointerEvents="auto";const m=document.createElement("div");m.className="notification-box";const p=document.createElement("div");p.className=`notification-icon ${t}`,d&&"info"===t?(p.className="notification-loading-container",p.innerHTML='<div class="notification-spinner"></div>',p.style.background="transparent",p.style.boxShadow="none",p.style.width="100px",p.style.height="100px"):p.innerHTML=this.getIcon(t);const b=document.createElement("h3");b.className="notification-title",b.textContent=e;const h=document.createElement("p");h.className="notification-message",h.textContent=o;let g=null;if(n.html||n.content)if(g=document.createElement("div"),g.className="notification-content",n.html)try{g.innerHTML=n.html}catch(t){g.textContent=n.html}else n.content&&n.content instanceof HTMLElement&&g.appendChild(n.content);let x=null;if(!d&&i){x=document.createElement("button"),x.className="notification-button",x.textContent=i;const n=a||this.getButtonGradient(t),e=this.getButtonShadow(t);x.style.background=n,x.style.boxShadow=`0 4px 12px ${e}`}let y=null;if(f&&(y=document.createElement("button"),y.setAttribute("aria-label","Cerrar"),y.className="notification-close",y.innerHTML="&times;",y.addEventListener("click",n=>{n.stopPropagation(),B()})),m.appendChild(p),g){const n="notify-desc-"+Date.now();g.id=n,u.setAttribute("aria-describedby",n),m.appendChild(g)}else m.appendChild(b),m.appendChild(h);y&&m.appendChild(y),x&&m.appendChild(x),u.appendChild(m),document.body.appendChild(u);const w=new Promise(n=>{try{u._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=u;try{const n=m.querySelectorAll('a[href], button:not([disabled]), textarea, input, select, [tabindex]:not([tabindex="-1"])');n&&n.length?n[0].focus():x?x.focus():u.focus()}catch(n){try{u.focus()}catch(n){}}const k=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=>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())};u._focusTrap=k,document.addEventListener("keydown",k);const v=n.anim||{},E="number"==typeof v.overlayDuration?v.overlayDuration:150,C=v.overlayEasing||"easeOutQuad",N="number"==typeof v.boxDuration?v.boxDuration:200,_="number"==typeof v.boxDelay?v.boxDelay:50,S=v.boxEasing||"easeOutBack",D="number"==typeof v.boxStartScale?v.boxStartScale:.8,L="number"==typeof v.iconDuration?v.iconDuration:250,T="number"==typeof v.iconDelay?v.iconDelay:100,A="number"==typeof v.iconRotate?v.iconRotate:"success"===t?-90:"error"===t?90:0;"number"==typeof v.overlayOpacity&&(u.style.backgroundColor=`rgba(0,0,0,${v.overlayOpacity})`),anime({targets:u,opacity:[0,1],duration:E,easing:C}),anime({targets:m,scale:[D,1],opacity:[0,1],duration:N,easing:S,delay:_}),anime({targets:p,scale:[0,1],rotate:[A,0],duration:L,easing:S,delay:T});const B=()=>{this.close(r)};if(x){const n=this.getButtonShadow(t);x.addEventListener("mouseenter",()=>{x.style.boxShadow=`0 6px 16px ${n}`}),x.addEventListener("mouseleave",()=>{x.style.boxShadow=`0 4px 12px ${n}`}),x.addEventListener("click",n=>{n.stopPropagation(),n.preventDefault(),B()})}if(s&&u.addEventListener("click",n=>{m.contains(n.target)||B()}),c&&setTimeout(()=>{B()},c),l){const n=t=>{"Escape"===t.key&&(B(),document.removeEventListener("keydown",n))};u._escHandler=n,document.addEventListener("keydown",n)}return w}close(n=null){if(!this.currentNotification)return Promise.resolve();const t=this.currentNotification,e=t.querySelector(".notification-box");return this.currentNotification=null,anime({targets:e,scale:.8,opacity:0,duration:100,easing:"easeInQuad"}),new Promise(e=>{anime({targets:t,opacity:0,duration:100,easing:"easeInQuad",complete:()=>{try{t&&t._escHandler&&(document.removeEventListener("keydown",t._escHandler),t._escHandler=null)}catch(n){}try{t&&t._focusTrap&&(document.removeEventListener("keydown",t._focusTrap),t._focusTrap=null)}catch(n){}try{if(t&&"function"==typeof t._externalResolve){try{t._externalResolve()}catch(n){}t._externalResolve=null}}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(),e()}})})}success(n,t=null,e={}){this.show({type:"success",title:t||this.getDefaultTitle("success"),message:n,...e})}error(n,t=null,e={}){this.show({type:"error",title:t||this.getDefaultTitle("error"),message:n,...e})}warning(n,t=null,e={}){this.show({type:"warning",title:t||this.getDefaultTitle("warning"),message:n,...e})}info(n,t=null,e={}){this.show({type:"info",title:t||this.getDefaultTitle("info"),message:n,...e})}loading(n="Cargando...",t="Espera",e={}){const o={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}}();
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "fernotify",
3
+ "version": "1.0.0",
4
+ "description": "Sistema moderno de notificaciones con animaciones fluidas y soporte completo de Dark Mode",
5
+ "main": "dist/notification-system.js",
6
+ "module": "dist/notification-system.esm.js",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/notification-system.esm.js",
10
+ "require": "./dist/notification-system.js"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist/",
15
+ "LICENSE",
16
+ "README.md",
17
+ "NOTIFICATION_SYSTEM_GUIDE.md"
18
+ ],
19
+ "keywords": [
20
+ "notifications",
21
+ "notificaciones",
22
+ "toast",
23
+ "anime",
24
+ "dark-mode",
25
+ "alerts",
26
+ "ui"
27
+ ],
28
+ "author": "Fernando Cabal <fernando@example.com>",
29
+ "license": "MIT",
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/Fernandocabal/fernotify.git"
33
+ },
34
+ "bugs": {
35
+ "url": "https://github.com/Fernandocabal/fernotify/issues"
36
+ },
37
+ "homepage": "https://github.com/Fernandocabal/fernotify#readme",
38
+ "engines": {
39
+ "node": ">=12.0.0"
40
+ },
41
+ "scripts": {
42
+ "build": "node build.js",
43
+ "build:watch": "node -e \"require('fs').watch('notification-system.js', () => require('child_process').exec('node build.js'))\"",
44
+ "prepublishOnly": "npm run build",
45
+ "publish-npm": "npm publish --access public"
46
+ },
47
+ "devDependencies": {
48
+ "terser": "^5.46.0"
49
+ }
50
+ }