questro
Version:
A lightweight, modular gamification library for React with unique visual components. Features combo meters, daily challenges, achievement toasts, and progress rings. Add points, badges, quests, leaderboards, levels/XP, streaks, and notifications with zero
13 lines • 8 kB
JavaScript
;var $=require('react'),jsxRuntime=require('react/jsx-runtime');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var $__default=/*#__PURE__*/_interopDefault($);var g=class{constructor(i={},t){this.listeners=new Set;this.timeouts=new Map;this.config={position:i.position||"top-right",maxNotifications:i.maxNotifications??5,defaultDuration:i.defaultDuration??5e3,animations:i.animations??true,sound:i.sound??false,soundUrl:i.soundUrl},this.state=t||this.createInitialState();}createInitialState(){return {notifications:[],lastUpdated:Date.now()}}show(i){let t=`notif-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,o={...i,id:t,timestamp:Date.now(),duration:i.duration??this.config.defaultDuration,dismissible:i.dismissible??true,read:false};if(this.state.notifications=[o,...this.state.notifications.slice(0,this.config.maxNotifications-1)],this.state.lastUpdated=Date.now(),o.duration&&o.duration>0){let a=setTimeout(()=>{this.dismiss(t);},o.duration);this.timeouts.set(t,a);}return this.config.sound&&this.playSound(),this.notifyListeners(),t}dismiss(i){this.state.notifications=this.state.notifications.filter(o=>o.id!==i),this.state.lastUpdated=Date.now();let t=this.timeouts.get(i);t&&(clearTimeout(t),this.timeouts.delete(i)),this.notifyListeners();}dismissAll(){this.state.notifications=[],this.state.lastUpdated=Date.now(),this.timeouts.forEach(i=>clearTimeout(i)),this.timeouts.clear(),this.notifyListeners();}markAsRead(i){let t=this.state.notifications.find(o=>o.id===i);t&&(t.read=true,this.state.lastUpdated=Date.now(),this.notifyListeners());}getNotifications(){return [...this.state.notifications]}getVisibleNotifications(){return this.state.notifications.slice(0,this.config.maxNotifications)}getUnreadCount(){return this.state.notifications.filter(i=>!i.read).length}getState(){return {...this.state}}subscribe(i){return this.listeners.add(i),()=>this.listeners.delete(i)}destroy(){this.timeouts.forEach(i=>clearTimeout(i)),this.timeouts.clear(),this.listeners.clear();}playSound(){if(this.config.soundUrl)try{let i=new Audio(this.config.soundUrl);i.volume=.5,i.play().catch(()=>{});}catch{}}notifyListeners(){this.listeners.forEach(i=>i());}success(i,t,o="\u2705"){return this.show({type:"success",title:i,message:t,icon:o})}error(i,t,o="\u274C"){return this.show({type:"error",title:i,message:t,icon:o})}info(i,t,o="\u2139\uFE0F"){return this.show({type:"info",title:i,message:t,icon:o})}warning(i,t,o="\u26A0\uFE0F"){return this.show({type:"warning",title:i,message:t,icon:o})}levelUp(i){return this.show({type:"levelup",title:`Level ${i}!`,message:`You've reached level ${i}`,icon:"\u2B06\uFE0F",duration:7e3})}badgeUnlocked(i,t){return this.show({type:"achievement",title:"Badge Unlocked!",message:i,icon:t||"\u{1F3C6}",duration:7e3})}questCompleted(i,t){return this.show({type:"success",title:"Quest Completed!",message:`${i} (+${t} points)`,icon:"\u{1F3AF}",duration:6e3})}streakMilestone(i){return this.show({type:"achievement",title:`${i} Day Streak! \u{1F525}`,message:`You've maintained your streak for ${i} days!`,icon:"\u{1F389}",duration:7e3})}streakWarning(i){return this.show({type:"warning",title:"Streak at Risk!",message:`Complete an activity in ${Math.round(i)} hours to keep your streak`,icon:"\u26A0\uFE0F",duration:1e4})}};var P=$.createContext(null);function Q({children:s,config:i}){let[t]=$.useState(()=>new g(i)),[o,a]=$.useState([]),[f,p]=$.useState(0);$.useEffect(()=>{let e=()=>{a(t.getVisibleNotifications()),p(t.getUnreadCount());};e();let n=t.subscribe(e);return ()=>{n(),t.destroy();}},[t]);let u=$.useCallback(e=>t.show(e),[t]),m=$.useCallback(e=>{t.dismiss(e);},[t]),c=$.useCallback(()=>{t.dismissAll();},[t]),N=$.useCallback(e=>{t.markAsRead(e);},[t]),v=$.useCallback((e,n,d)=>t.success(e,n,d),[t]),x=$.useCallback((e,n,d)=>t.error(e,n,d),[t]),w=$.useCallback((e,n,d)=>t.info(e,n,d),[t]),C=$.useCallback((e,n,d)=>t.warning(e,n,d),[t]),k=$.useCallback(e=>t.levelUp(e),[t]),S=$.useCallback((e,n)=>t.badgeUnlocked(e,n),[t]),R=$.useCallback((e,n)=>t.questCompleted(e,n),[t]),T=$.useCallback(e=>t.streakMilestone(e),[t]),U=$.useCallback(e=>t.streakWarning(e),[t]),M=$.useMemo(()=>({notifications:o,unreadCount:f,show:u,dismiss:m,dismissAll:c,markAsRead:N,success:v,error:x,info:w,warning:C,levelUp:k,badgeUnlocked:S,questCompleted:R,streakMilestone:T,streakWarning:U}),[o,f,u,m,c,N,v,x,w,C,k,S,R,T,U]);return jsxRuntime.jsx(P.Provider,{value:M,children:s})}function I(){let s=$__default.default.useContext(P);if(!s)throw new Error("useNotifications must be used within a NotificationsProvider");return s}function y({notification:s,onDismiss:i,className:t,children:o}){if(o)return jsxRuntime.jsx(jsxRuntime.Fragment,{children:o({notification:s,onDismiss:i})});let a={success:"#10b981",error:"#ef4444",warning:"#f59e0b",info:"#3b82f6",levelup:"linear-gradient(135deg, #fbbf24 0%, #f97316 100%)",achievement:"linear-gradient(135deg, #a855f7 0%, #ec4899 100%)"};return jsxRuntime.jsxs("div",{className:t,"data-component":"toast","data-type":s.type,role:"alert",style:{background:a[s.type],color:"white",padding:"12px 16px",borderRadius:"8px",boxShadow:"0 4px 12px rgba(0, 0, 0, 0.15)",display:"flex",alignItems:"flex-start",gap:"12px",minWidth:"300px",maxWidth:"400px",animation:"slideIn 0.3s ease-out"},children:[s.icon&&jsxRuntime.jsx("div",{"data-toast-icon":true,style:{fontSize:"20px",flexShrink:0},children:s.icon}),jsxRuntime.jsxs("div",{"data-toast-content":true,style:{flex:1},children:[jsxRuntime.jsx("div",{"data-toast-title":true,style:{fontWeight:"bold",marginBottom:"4px"},children:s.title}),s.message&&jsxRuntime.jsx("div",{"data-toast-message":true,style:{fontSize:"14px",opacity:.9},children:s.message}),s.action&&jsxRuntime.jsx("button",{onClick:s.action.onClick,"data-toast-action":true,style:{marginTop:"8px",padding:"4px 12px",background:"rgba(255, 255, 255, 0.2)",border:"1px solid rgba(255, 255, 255, 0.3)",borderRadius:"4px",color:"white",cursor:"pointer",fontSize:"14px"},children:s.action.label})]}),s.dismissible!==false&&jsxRuntime.jsx("button",{onClick:i,"data-toast-close":true,"aria-label":"Dismiss",style:{background:"transparent",border:"none",color:"white",cursor:"pointer",fontSize:"20px",padding:"0",width:"24px",height:"24px",display:"flex",alignItems:"center",justifyContent:"center",opacity:.7,flexShrink:0},children:"\u2715"}),jsxRuntime.jsx("style",{children:`
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
`})]})}function V({position:s="top-right",maxVisible:i=3,className:t,renderToast:o,children:a}){let{notifications:f,dismiss:p}=I(),u=f.slice(0,i);return a?jsxRuntime.jsx(jsxRuntime.Fragment,{children:a({notifications:u,dismiss:p,position:s})}):jsxRuntime.jsxs("div",{className:t,"data-component":"notification-container","data-position":s,style:{position:"fixed",zIndex:9999,display:"flex",flexDirection:"column",gap:"12px",pointerEvents:"none",...{"top-left":{top:20,left:20,alignItems:"flex-start"},"top-center":{top:20,left:"50%",transform:"translateX(-50%)",alignItems:"center"},"top-right":{top:20,right:20,alignItems:"flex-end"},"bottom-left":{bottom:20,left:20,alignItems:"flex-start"},"bottom-center":{bottom:20,left:"50%",transform:"translateX(-50%)",alignItems:"center"},"bottom-right":{bottom:20,right:20,alignItems:"flex-end"}}[s]},children:[u.map(c=>jsxRuntime.jsx("div",{style:{pointerEvents:"auto"},children:o?o(c,()=>p(c.id)):jsxRuntime.jsx(y,{notification:c,onDismiss:()=>p(c.id)})},c.id)),f.length>i&&jsxRuntime.jsxs("div",{"data-notification-overflow":true,style:{background:"rgba(0, 0, 0, 0.75)",color:"white",padding:"8px 12px",borderRadius:"8px",fontSize:"14px",textAlign:"center"},children:["+",f.length-i," more"]})]})}exports.a=g;exports.b=Q;exports.c=I;exports.d=y;exports.e=V;//# sourceMappingURL=chunk-BLDSUKBK.js.map
//# sourceMappingURL=chunk-BLDSUKBK.js.map