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
2 lines • 4.26 kB
JavaScript
import {a,g,b,c}from'./chunk-3QNKEEDV.mjs';import {c as c$1}from'./chunk-R2GD7YTX.mjs';import*as d from'react';import {createContext,useState,useMemo,useEffect,useContext,useCallback}from'react';import {jsx,Fragment}from'react/jsx-runtime';var m=class n{constructor(t){this.events=a();this.config={userId:t.userId,initialBalance:t.initialBalance??0,minBalance:t.minBalance??0,maxBalance:t.maxBalance??Number.MAX_SAFE_INTEGER,onBalanceChange:t.onBalanceChange??(()=>{})},this.state={userId:t.userId,balance:this.config.initialBalance,transactions:[],lifetime:this.config.initialBalance};}getBalance(){return this.state.balance}getLifetimePoints(){return this.state.lifetime}getTransactions(){return [...this.state.transactions]}addPoints(t,e){if(t<=0)throw new Error("Amount must be positive");let i=this.state.balance,s=g(this.state.balance+t,this.config.minBalance,this.config.maxBalance),a=this.createTransaction(t,e,s);return this.state.balance=s,this.state.lifetime+=t,this.state.transactions.push(a),this.events.emit("pointsAdded",{amount:t,reason:e,newBalance:s}),this.events.emit("transactionAdded",a),this.emitBalanceChange(i,s),a}subtractPoints(t,e){if(t<=0)throw new Error("Amount must be positive");let i=this.state.balance,s=g(this.state.balance-t,this.config.minBalance,this.config.maxBalance),a=this.createTransaction(-t,e,s);return this.state.balance=s,this.state.transactions.push(a),this.events.emit("pointsSubtracted",{amount:t,reason:e,newBalance:s}),this.events.emit("transactionAdded",a),this.emitBalanceChange(i,s),a}setBalance(t,e){let i=this.state.balance,s=g(t,this.config.minBalance,this.config.maxBalance),a=s-i,o=this.createTransaction(a,e,s);return this.state.balance=s,a>0&&(this.state.lifetime+=a),this.state.transactions.push(o),this.events.emit("transactionAdded",o),this.emitBalanceChange(i,s),o}reset(){let t=this.state.balance;this.state.balance=this.config.initialBalance,this.state.transactions=[],this.state.lifetime=this.config.initialBalance,this.emitBalanceChange(t,this.config.initialBalance);}createTransaction(t,e,i){return {id:c(),userId:this.state.userId,amount:t,reason:e,balance:i,createdAt:b(),updatedAt:b()}}emitBalanceChange(t,e){t!==e&&(this.events.emit("balanceChanged",{oldBalance:t,newBalance:e}),this.config.onBalanceChange(e));}toJSON(){return {...this.state}}static fromJSON(t,e){let i=new n(t);return i.state=e,i}};var x=createContext(null);function w({children:n,config:t,storage:e=new c$1,storageKey:i=`points:${t.userId}`}){let[s,a]=useState(true),o=useMemo(()=>new m(t),[t.userId]);return useEffect(()=>{let c=true;return (async()=>{try{let l=await e.get(i);l&&c&&Object.assign(o,m.fromJSON(t,l));}catch(l){console.error("Failed to load points state:",l);}finally{c&&a(false);}})(),()=>{c=false;}},[e,i,t,o]),useEffect(()=>s?void 0:o.events.on("balanceChanged",async()=>{try{await e.set(i,o.toJSON());}catch(f){console.error("Failed to save points state:",f);}}),[o,e,i,s]),s?null:jsx(x.Provider,{value:o,children:n})}function v(){let n=useContext(x);if(!n)throw new Error("usePointsContext must be used within a PointsProvider");return n}function P(){let n=v(),[t,e]=useState(n.getBalance()),[i,s]=useState(n.getLifetimePoints()),[a,o]=useState(n.getTransactions());useEffect(()=>n.events.on("balanceChanged",({newBalance:r})=>{e(r),s(n.getLifetimePoints()),o(n.getTransactions());}),[n]);let c=useCallback((u,r)=>n.addPoints(u,r),[n]),f=useCallback((u,r)=>n.subtractPoints(u,r),[n]),l=useCallback((u,r)=>n.setBalance(u,r),[n]),T=useCallback(()=>{n.reset();},[n]);return {balance:t,lifetime:i,transactions:a,addPoints:c,subtractPoints:f,setBalance:l,reset:T}}function M({children:n,format:t,...e}){let{balance:i}=P(),s=t?t(i):i.toLocaleString();return jsx("div",{"data-questro-points":true,...e,children:n??s})}function H({children:n,format:t,...e}){let{lifetime:i}=P(),s=t?t(i):i.toLocaleString();return jsx("div",{"data-questro-lifetime-points":true,...e,children:n??s})}function O({children:n}){let{balance:t}=P(),[e,i]=d.useState(t),[s,a]=d.useState(false);return d.useEffect(()=>{t!==e&&(a(t>e),i(t));},[t,e]),jsx(Fragment,{children:n(t,s)})}export{m as a,w as b,v as c,P as d,M as e,H as f,O as g};//# sourceMappingURL=chunk-WD7ZAXL7.mjs.map
//# sourceMappingURL=chunk-WD7ZAXL7.mjs.map