@enjoys/pinglet 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.
Files changed (2) hide show
  1. package/package.json +41 -0
  2. package/pinglet-sse.js +1 -0
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@enjoys/pinglet",
3
+ "version": "1.0.0",
4
+ "description": "Lightweight Customizable Web & CustomPush Notification SDK for modern web apps. Supports customizable layouts, secure delivery, and real-time updates via SSE.",
5
+ "main": "./pinglet-sse.js",
6
+ "types": "pinglet-sse.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./pinglet-sse.js",
10
+ "require": "./pinglet-sse.js"
11
+ }
12
+ },
13
+ "files": [
14
+ "pinglet-sse.js",
15
+ "pinglet-sse.d.ts"
16
+ ],
17
+ "keywords": [
18
+ "push",
19
+ "notifications",
20
+ "sse",
21
+ "widget",
22
+ "browser-sdk",
23
+ "realtime",
24
+ "toast",
25
+ "customizable",
26
+ "pinglet",
27
+ "webpush",
28
+ "web notification",
29
+ "eventstream"
30
+ ],
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/enjoys-in"
34
+ },
35
+ "bugs": {
36
+ "url": "https://github.com/enjoys-in"
37
+ },
38
+ "homepage": "https://github.com/enjoys-in",
39
+ "author": "Enjoys <su@enjoys.in>",
40
+ "license": "MIT"
41
+ }
package/pinglet-sse.js ADDED
@@ -0,0 +1 @@
1
+ !function(){"use strict";function e(e,t,n=[{text:"See Docs",onClick:()=>window.open("https://pinglet.enjoys.in/docs","_blank")}],o="⚠️"){const i="toastContainer";let s=document.getElementById(i);s||(s=document.createElement("div"),s.id=i,Object.assign(s.style,{position:"fixed",bottom:"24px",right:"24px",zIndex:"9999",display:"flex",flexDirection:"column",gap:"4px",alignItems:"flex-end",fontFamily:"Manrope, sans-serif"}),document.body.appendChild(s));const a=document.createElement("div");Object.assign(a.style,{background:"#1f1f1f",color:"#fff",padding:"16px 20px",borderRadius:"12px",boxShadow:"0 6px 18px rgba(0, 0, 0, 0.25)",fontFamily:"'Inter', sans-serif",minWidth:"260px",maxWidth:"340px",opacity:"0",transform:"translateX(100%)",transition:"opacity 0.3s ease, transform 0.3s ease",display:"flex",flexDirection:"column",gap:"10px",fontFamily:"Manrope, sans-serif"});const l=document.createElement("div");Object.assign(l.style,{display:"flex",alignItems:"center",gap:"10px",fontSize:"16px",fontWeight:"600",fontFamily:"Manrope, sans-serif"});const r=document.createElement("div");r.textContent=o;const c=document.createElement("div");if(c.textContent=e,l.appendChild(r),l.appendChild(c),a.appendChild(l),t){const e=document.createElement("div");e.textContent=t,Object.assign(e.style,{fontSize:"13.5px",fontWeight:"400",color:"#ddd",lineHeight:"1.5"}),a.appendChild(e)}if(Array.isArray(n)&&n.length){const e=document.createElement("div");Object.assign(e.style,{marginTop:"8px",display:"flex",gap:"10px",justifyContent:"flex-start"});for(const t of n){const n=document.createElement("button");n.textContent=t.text||"Click",Object.assign(n.style,{padding:"8px 14px",background:"#333",color:"#fff",border:"1px solid #444",borderRadius:"6px",fontSize:"13px",cursor:"pointer",transition:"background 0.3s",fontFamily:"Manrope, sans-serif"}),n.onmouseover=()=>n.style.background="#444",n.onmouseout=()=>n.style.background="#333","function"==typeof t.onClick&&n.addEventListener("click",t.onClick),e.appendChild(n)}a.appendChild(e)}s.appendChild(a);const d=document.createElement("div");return d.innerHTML='Notifications by <a href="https://pinglet.enjoys.in" target="_blank" style="color:#4da6ff;text-decoration:none;">Pinglet</a> - Enjoys',Object.assign(d.style,{fontSize:"11px",color:"#999",marginTop:"4px",textAlign:"right",fontFamily:"Manrope, sans-serif"}),s.appendChild(d),requestAnimationFrame((()=>{a.style.opacity="1",a.style.transform="translateX(0)"})),setTimeout((()=>{a.style.opacity="0",a.style.transform="translateX(100%)",setTimeout((()=>{a.remove(),d.remove()}),500)}),5e3),s}const t={duration:3e3,btn1:{color:"#ffffff",backgroundColor:"#007bff",padding:"6px 10px",borderRadius:"6px",fontSize:"14px",fontWeight:"600",border:"none",boxShadow:"0 2px 6px rgba(0,0,0,0.15)"},btn2:{color:"#333333",backgroundColor:"#f0f0f0",padding:"6px 10px",borderRadius:"6px",fontSize:"14px",fontWeight:"600",border:"1px solid #ccc"},title:{color:"#111111",fontSize:"14px",fontWeight:"500",lineHeight:"1.4",margin:"0 0 0 0",textAlign:"left"},description:{color:"#444444",fontSize:"13px",fontWeight:"400",lineHeight:"1.5",margin:"0 0 10px 0",textAlign:"left"},controls:{video:{autoplay:!1,muted:!1,loop:!1,controls:!1},audio:{autoplay:!1,muted:!1,loop:!1,controls:!1}},media:{image:{width:"100%",height:"200px",borderRadius:"6px",objectFit:"cover",margin:"0 0 8px 0"},icon:{width:"24px",height:"24px",margin:"0 8px 0 0",objectFit:"contain"},logo:{width:"50px",height:"50px",margin:"0 8px 0 0",objectFit:"contain"},video:{width:"100%",height:"140px",borderRadius:"6px",objectFit:"cover",margin:"0 0 10px 0"},iframe:{width:"100%",height:"140px",borderRadius:"6px",objectFit:"cover",margin:"0 0 10px 0"},audio:{width:"100%",margin:"8px 0"}}},n={position:"bottom-left",transition:"fade",branding:{show:!0,html:'Notifications by <a href="https://pinglet.enjoys.in" style="color:#4da6ff;text-decoration:none;" target="_blank">Pinglet</a> - Enjoys'},sound:{play:!1,src:"https://pinglet.enjoys.in/api/v1/pinglet-sound.mp3?v=1&ext=mp3",volume:.6},duration:2e3,maxVisible:3,stacking:!0,auto_dismiss:!0,dismissible:!0,website:"https://pinglet.enjoys.in",time:!0,favicon:!0,pauseOnHover:!0,theme:{mode:"light",customClass:"",rounded:!0,shadow:!0,border:!1},iconDefaults:{show:!0,size:20,position:"left"},progressBar:{show:!0,color:"#4da6ff",height:3}};let o,i,s=null,a=null;function l(e){if(i&&s)return{toastContainer:i,toastStack:s};const t=document.getElementById("pinglet-widget-container");return t?(i=t,s=i.querySelector(".pinglet-widget-stack"),{toastContainer:i,toastStack:s}):(i=document.createElement("div"),i.id="pinglet-widget-container",i.style.position="fixed",i.style.bottom="20px",i.style.left="20px",i.style.zIndex="9999",i.style.display="flex",i.style.flexDirection="column",i.style.alignItems="flex-start",i.style.gap="8px",i.style.maxWidth="360px",i.style.width="calc(100vw - 40px)",i.style.boxSizing="border-box",i.style.pointerEvents="none",i.style.padding="4px",i.style.borderRadius="8px",s=document.createElement("div"),s.className="pinglet-widget-stack",s.style.display="flex",s.style.flexDirection="column",s.style.gap="12px",s.style.pointerEvents="none",s.style.overflow="visible",s.style.flexShrink="0",i.appendChild(s),e?.show&&i.appendChild(function(e){return a||(a=document.createElement("div"),a.className="pinglet-branding",a.innerHTML=e?.html||'Notifications by <a href="https://pinglet.enjoys.in" class="pinglet-link" target="_blank" style="color:#4da6ff;text-decoration:none;">Pinglet</a>',a.style="\n font-size: 11px;\n color: #999;\n text-align: center;\n width: 100%;\n pointer-events: auto;\n ",a)}(e)),document.body.appendChild(i),{toastContainer:i,toastStack:s})}function r(e,t){const n=t.config,{toastContainer:i,toastStack:s}=l(n.branding);var r,d;i.appendChild(a),r=e,d=n.transition,r.style.opacity="0",r.style.transition="all 0.4s ease","fade"===d?(r.style.transform="translateX(20px)",requestAnimationFrame((()=>{r.style.opacity="1",r.style.transform="translateX(0)"}))):"slide"===d?(r.style.transform="translateX(100%)",requestAnimationFrame((()=>{r.style.opacity="1",r.style.transform="translateX(0)"}))):"zoom"===d?(r.style.transform="scale(0.8)",requestAnimationFrame((()=>{r.style.opacity="1",r.style.transform="scale(1)"}))):r.style.opacity="1",e.style.pointerEvents="auto",s.appendChild(e),n.sound?.play&&o&&o.play(),n?.auto_dismiss&&setTimeout((()=>{c(e,n?.transition||"fade")}),n.duration||3e3)}function c(e,t){e&&(e.style.transition="all 0.4s ease",a.style.transition="all 0.4s ease",a.style.transform="translateX(-40px)","fade"===t?(e.style.opacity="0",e.style.transform="translateX(-40px)"):"slide"===t?(e.style.transform="translateX(-100%)",e.style.opacity="0"):"zoom"===t?(e.style.transform="scale(0.8)",e.style.opacity="0"):e.style.opacity="0",e.addEventListener("transitionend",(()=>{e.remove(),s&&0===s.children.length&&a.remove()}),{once:!0}))}function d(e,o){const i=o.style,l=o.config,r=document.createElement("div");if(r.className=`pinglet-variant pinglet-${e.variant||"default"}`,r.style.display="flex",r.style.flexDirection="column",r.style.alignItems="stretch",r.style.width="100%",r.style.maxHeight="calc(100vh - 40px)",r.style.borderRadius="8px",r.style.overflowY="auto",r.style.boxShadow="0 2px 8px rgba(0, 0, 0, 0.1)",r.style.padding="4px",r.style.backgroundColor="rgba(255, 255, 255, 0.9)",r.style.gap="4px",r.style.pointerEvents="none",r.style.overflow="visible",r.style.flexShrink="0",r.appendChild(function(e=n,t=window.location.hostname,o="just now"){const i=document.createElement("div");i.className="pinglet-row",Object.assign(i.style,{display:"flex",justifyContent:"space-between",alignItems:"center",background:"#fff",fontFamily:"system-ui, sans-serif",fontSize:"10px"});const l=document.createElement("div");l.className="pinglet-left",Object.assign(l.style,{display:"flex",alignItems:"center",gap:"6px",flexGrow:"1"});const r=document.createElement("div");r.className="pinglet-icon",Object.assign(r.style,{width:"6px",height:"6px",borderRadius:"50%",backgroundColor:"#007bff",flexShrink:"0"});const c=document.createElement("span");c.className="pinglet-domain",c.textContent=t,c.style.color="#333";const d=document.createElement("span");d.className="pinglet-time",d.textContent=`- ${o}`,d.style.color="#666";const p=document.createElement("button");return p.className="pinglet-close",p.textContent="✕",Object.assign(p.style,{background:"none",border:"none",fontSize:"12px",cursor:"pointer",color:"#888"}),p.addEventListener("mouseenter",(()=>{p.style.color="#e00"})),p.addEventListener("mouseleave",(()=>{p.style.color="#888"})),e?.website&&l.appendChild(c),e?.time&&l.appendChild(d),e?.favicon&&l.appendChild(r),i.appendChild(l),e?.dismissible&&i.appendChild(p),p.onclick=()=>{p.parentElement.parentElement.remove(),s&&0===s.children.length&&a?.remove()},i}(l)),e.media?.type){const n=function(e,n,o){switch(e.type){case"logo":{const o=document.createElement("img");return o.src=e.src,Object.assign(o.style,n?.logo||t.media.logo),o}case"image":{const o=document.createElement("img");return o.src=e.src,Object.assign(o.style,n?.image||t.media.image),o}case"video":{const i=document.createElement("video");return i.src=e.src,i.autoplay=o?.video?.autoplay||t.controls.video.autoplay||!1,i.muted=o?.video?.muted||t.controls.video.muted||!1,i.loop=o?.video?.loop||t.controls.video.loop||!1,i.controls=o?.video?.controls||t.controls.video.controls||!1,i.style=n?.video||t.media.video,Object.assign(i.style,n?.video||t.media.video),i}case"audio":{const n=document.createElement("audio");return n.src=e.src,n.autoplay=o?.audio?.controls||t.controls?.audio.autoplay||!1,n.muted=o?.audio?.muted||t.controls?.audio.muted||!1,n.loop=o?.audio?.loop||t.controls?.audio?.loop||!1,n.controls=o?.audio?.controls||t.controls?.audio?.controls||!1,Object.assign(n.style,n?.video||t.media.audio),n}case"icon":{const e=document.createElement("span");return e.className="pinglet-icon",e.style={width:"40px",height:"40px",backgroundPosition:"center",borderRadius:"8px"},e}default:return null}}(e.media,i.media,i.controls);n&&r.appendChild(n)}if(e.title){const n=document.createElement("div");n.className="pinglet-title",n.innerText=e.title,Object.assign(n.style,i.title||t.title),r.appendChild(n)}if(e.description){const n=document.createElement("p");n.className="pinglet-desc",n.innerText=e.description,Object.assign(n.style,i.description||t.description),r.appendChild(n)}if(e.buttons){const t=document.createElement("div");t.className="pinglet-buttons",t.style.fontFamily="Manrope",e.buttons.forEach(((e,n)=>{const o=document.createElement("button");o.innerText=e.text,o.className="pinglet-btn",o.style.cursor="pointer",o.style.padding="6px 10px",o.style.fontFamily="Manrope, sans-serif",o.style.margin="1px 4px",Object.assign(o.style,0===n?i.btn1:i.btn2),o.onclick=new Function(e.onClick),t.appendChild(o)})),r.appendChild(t)}return r}const p=Array.from(document.scripts).find((e=>e.src.includes("pinglet-sse")&&e.dataset.endpoint))||document.currentScript,m=p?.dataset.endpoint,u=p?.dataset.configuredDomain,g=p?.dataset.projectId,f=p?.dataset.pingletId,y=p?.dataset.loadTemplates,x=p?.dataset.checksum;(async i=>{if(i.PingletWidget)return void console.warn("PingletWidget is already initialized.");!function(){const e=document.createElement("link");e.rel="stylesheet",e.href="https://fonts.googleapis.com/css2?family=Manrope:wght@200..800&display=swap",document.head.appendChild(e);const t=document.createElement("style");t.innerHTML='\n [class^="pinglet-"],\n [class*=" pinglet-"] {\n font-family: \'Manrope\', sans-serif !important;\n font-weight: 400 !important;\n }\n ',document.head.appendChild(t)}();let s={};const a={version:"0.0.2",checksum:x.replace("sha384-",""),async init({endpoint:i,configuredDomain:a,projectId:l,pingletId:c}){if("0.0.2"!==this.version)return e("Unsupported Version",`PingletWidget version ${this.version} is not supported. Please update to the latest version.`,[{text:"See Docs",onClick:()=>window.open("https://pinglet.enjoys.in/docs","_blank")}],"⚠️"),void console.warn("Unsupported version detected.");if(!this.checksum||!x)return e("Configuration Error","Missing checksum.");const p=await fetch(`${i}/load/projects?projectId=${l}&domain=${a}`,{headers:{"X-Project-ID":l,"X-Timestamp":Date.now(),"X-Pinglet-Signature":c,"X-Pinglet-Checksum":this.checksum,"X-Pinglet-Version":this.version,"X-Configured-Domain":a,"X-Pinglet-Id":c},credentials:"omit"}),m=await p.json();if(!m||!m.success)return e("Configuration Error",`Failed to load configuration for PingletWidget. ${m.message||"Unknown error"}`,[{text:"Retry",onClick:()=>window.location.reload()},{text:"See Docs",onClick:()=>window.open("https://pinglet.enjoys.in/docs","_blank")}],"❌"),console.error("Failed to load configuration for PingletWidget.");if("true"===y){const t=await async function(e,t,n,o,i){const s=await fetch(`${e}/load/templates?projectId=${t}`,{headers:{"X-Project-ID":t,"X-Timestamp":Date.now(),"X-Pinglet-Signature":n,"X-Pinglet-Checksum":o,"X-Pinglet-Version":i},credentials:"omit"}),a=await s.json();return a&&a.success?a.result:null}(i,l,c,this.checksum,this.version);t||e("Configuration Error","Failed to load templates for PingletWidget."),s=t}const u={is_tff:m.result?.is_premium??!1,templates:Object.assign({},{default:{compiled_text:e.toString(),config:n,is_active:!0,is_default:!0}},"true"===y?s:{[String(m.result.template?.id.toString())]:m.result.template}),style:Object.assign({},t,m.result.template?.config),config:Object.assign({},n,m.result.config)};!function(e){if(o)return o;e.sound?.play&&e.sound.src&&(o=new Audio(e.sound.src),o.volume=e.sound.volume??.5)}(u);new EventSource(`${i}/subscribe?projectId=${l}&pingletId=${c}`,{withCredentials:!1}).onmessage=e=>{const t=JSON.parse(e.data);if(t?.template_id){return r(new Function(`return ${u.templates[String(t.template_id)].compiled_text}`)()(t.title,t.description,t.media,t.buttons),u)}const n=d(t,u);u?.is_tdd&&Object.assign(u.config,u.config,t?.overrides??{}),r(n,u)}}};i.PingletWidget=a,document.addEventListener("DOMContentLoaded",(()=>{a.init({endpoint:m,configuredDomain:u,projectId:g,pingletId:f})})),console.log("%cPingletWidget initialized successfully.","color: #1e90ff; font-weight: bold;")})(window)}();