react-achievements 1.0.3 → 1.0.5

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/dist/index.esm.js CHANGED
@@ -1,29 +1,7 @@
1
- import React, { createContext, useState, useCallback, useMemo, useContext, useEffect } from 'react';
2
-
3
- const defaultBadges = [
4
- {
5
- id: 'beginner',
6
- icon: '/path/to/beginner-icon.png',
7
- title: 'Beginner',
8
- description: 'Achieved beginner level',
9
- },
10
- {
11
- id: 'intermediate',
12
- icon: '/path/to/intermediate-icon.png',
13
- title: 'Intermediate',
14
- description: 'Achieved intermediate level',
15
- },
16
- // Add more badges as needed
17
- ];
18
-
19
- const defaultLevels = [
20
- { level: 1, threshold: 10, badgeId: 'beginner' },
21
- { level: 2, threshold: 50, badgeId: 'intermediate' },
22
- // Add more levels as needed
23
- ];
24
-
25
- const AchievementModal = ({ show, message, onClose }) => {
26
- if (!show)
1
+ import React, { useEffect, useRef, useState, useCallback, createContext, useContext } from 'react';
2
+
3
+ const AchievementModal = ({ show, achievement, onClose }) => {
4
+ if (!show || !achievement)
27
5
  return null;
28
6
  const modalStyle = {
29
7
  position: 'fixed',
@@ -49,12 +27,14 @@ const AchievementModal = ({ show, message, onClose }) => {
49
27
  React.createElement("div", { style: overlayStyle, onClick: onClose }),
50
28
  React.createElement("div", { style: modalStyle, role: "dialog", "aria-modal": "true", "aria-labelledby": "achievement-title" },
51
29
  React.createElement("h2", { id: "achievement-title" }, "Achievement Unlocked!"),
52
- React.createElement("p", null, message),
30
+ React.createElement("img", { src: achievement.icon, alt: achievement.title, style: { width: '50px', height: '50px' } }),
31
+ React.createElement("h3", null, achievement.title),
32
+ React.createElement("p", null, achievement.description),
53
33
  React.createElement("button", { onClick: onClose }, "Okay"))));
54
34
  };
55
35
  var AchievementModal$1 = React.memo(AchievementModal);
56
36
 
57
- const BadgesModal = ({ show, badges, onClose }) => {
37
+ const BadgesModal = ({ show, achievements, onClose }) => {
58
38
  if (!show)
59
39
  return null;
60
40
  const modalStyle = {
@@ -84,10 +64,10 @@ const BadgesModal = ({ show, badges, onClose }) => {
84
64
  React.createElement("div", { style: overlayStyle, onClick: onClose }),
85
65
  React.createElement("div", { style: modalStyle, role: "dialog", "aria-modal": "true", "aria-labelledby": "badges-title" },
86
66
  React.createElement("h2", { id: "badges-title" }, "Your Achievements"),
87
- React.createElement("div", { style: { display: 'flex', flexWrap: 'wrap', justifyContent: 'center' } }, badges.map(badge => (React.createElement("div", { key: badge.id, style: { margin: '10px', textAlign: 'center' } },
88
- React.createElement("img", { src: badge.icon, alt: badge.title, style: { width: '50px', height: '50px' } }),
89
- React.createElement("h4", null, badge.title),
90
- React.createElement("p", null, badge.description))))),
67
+ React.createElement("div", { style: { display: 'flex', flexWrap: 'wrap', justifyContent: 'center' } }, achievements.map(achievement => (React.createElement("div", { key: achievement.id, style: { margin: '10px', textAlign: 'center' } },
68
+ React.createElement("img", { src: achievement.icon, alt: achievement.title, style: { width: '50px', height: '50px' } }),
69
+ React.createElement("h4", null, achievement.title),
70
+ React.createElement("p", null, achievement.description))))),
91
71
  React.createElement("button", { onClick: onClose, style: { marginTop: '20px' } }, "Close"))));
92
72
  };
93
73
  var BadgesModal$1 = React.memo(BadgesModal);
@@ -109,52 +89,171 @@ const BadgesButton = ({ onClick, position }) => {
109
89
  };
110
90
  var BadgesButton$1 = React.memo(BadgesButton);
111
91
 
92
+ var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
93
+
94
+ function getDefaultExportFromCjs (x) {
95
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
96
+ }
97
+
98
+ var reactConfetti_min = {exports: {}};
99
+
100
+ (function (module, exports) {
101
+ !function(t,e){module.exports=e(React);}("undefined"!=typeof self?self:commonjsGlobal,(function(t){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r});},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0});},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(r,i,function(e){return t[e]}.bind(null,i));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=2)}([function(e,n){e.exports=t;},function(t,e,n){var r={linear:function(t,e,n,r){return (n-e)*t/r+e},easeInQuad:function(t,e,n,r){return (n-e)*(t/=r)*t+e},easeOutQuad:function(t,e,n,r){return -(n-e)*(t/=r)*(t-2)+e},easeInOutQuad:function(t,e,n,r){var i=n-e;return (t/=r/2)<1?i/2*t*t+e:-i/2*(--t*(t-2)-1)+e},easeInCubic:function(t,e,n,r){return (n-e)*(t/=r)*t*t+e},easeOutCubic:function(t,e,n,r){return (n-e)*((t=t/r-1)*t*t+1)+e},easeInOutCubic:function(t,e,n,r){var i=n-e;return (t/=r/2)<1?i/2*t*t*t+e:i/2*((t-=2)*t*t+2)+e},easeInQuart:function(t,e,n,r){return (n-e)*(t/=r)*t*t*t+e},easeOutQuart:function(t,e,n,r){return -(n-e)*((t=t/r-1)*t*t*t-1)+e},easeInOutQuart:function(t,e,n,r){var i=n-e;return (t/=r/2)<1?i/2*t*t*t*t+e:-i/2*((t-=2)*t*t*t-2)+e},easeInQuint:function(t,e,n,r){return (n-e)*(t/=r)*t*t*t*t+e},easeOutQuint:function(t,e,n,r){return (n-e)*((t=t/r-1)*t*t*t*t+1)+e},easeInOutQuint:function(t,e,n,r){var i=n-e;return (t/=r/2)<1?i/2*t*t*t*t*t+e:i/2*((t-=2)*t*t*t*t+2)+e},easeInSine:function(t,e,n,r){var i=n-e;return -i*Math.cos(t/r*(Math.PI/2))+i+e},easeOutSine:function(t,e,n,r){return (n-e)*Math.sin(t/r*(Math.PI/2))+e},easeInOutSine:function(t,e,n,r){return -(n-e)/2*(Math.cos(Math.PI*t/r)-1)+e},easeInExpo:function(t,e,n,r){return 0==t?e:(n-e)*Math.pow(2,10*(t/r-1))+e},easeOutExpo:function(t,e,n,r){var i=n-e;return t==r?e+i:i*(1-Math.pow(2,-10*t/r))+e},easeInOutExpo:function(t,e,n,r){var i=n-e;return 0===t?e:t===r?e+i:(t/=r/2)<1?i/2*Math.pow(2,10*(t-1))+e:i/2*(2-Math.pow(2,-10*--t))+e},easeInCirc:function(t,e,n,r){return -(n-e)*(Math.sqrt(1-(t/=r)*t)-1)+e},easeOutCirc:function(t,e,n,r){return (n-e)*Math.sqrt(1-(t=t/r-1)*t)+e},easeInOutCirc:function(t,e,n,r){var i=n-e;return (t/=r/2)<1?-i/2*(Math.sqrt(1-t*t)-1)+e:i/2*(Math.sqrt(1-(t-=2)*t)+1)+e},easeInElastic:function(t,e,n,r){var i,o,a,c=n-e;return a=1.70158,0===t?e:1==(t/=r)?e+c:((o=0)||(o=.3*r),(i=c)<Math.abs(c)?(i=c,a=o/4):a=o/(2*Math.PI)*Math.asin(c/i),-i*Math.pow(2,10*(t-=1))*Math.sin((t*r-a)*(2*Math.PI)/o)+e)},easeOutElastic:function(t,e,n,r){var i,o,a,c=n-e;return a=1.70158,0===t?e:1==(t/=r)?e+c:((o=0)||(o=.3*r),(i=c)<Math.abs(c)?(i=c,a=o/4):a=o/(2*Math.PI)*Math.asin(c/i),i*Math.pow(2,-10*t)*Math.sin((t*r-a)*(2*Math.PI)/o)+c+e)},easeInOutElastic:function(t,e,n,r){var i,o,a,c=n-e;return a=1.70158,0===t?e:2==(t/=r/2)?e+c:((o=0)||(o=r*(.3*1.5)),(i=c)<Math.abs(c)?(i=c,a=o/4):a=o/(2*Math.PI)*Math.asin(c/i),t<1?i*Math.pow(2,10*(t-=1))*Math.sin((t*r-a)*(2*Math.PI)/o)*-.5+e:i*Math.pow(2,-10*(t-=1))*Math.sin((t*r-a)*(2*Math.PI)/o)*.5+c+e)},easeInBack:function(t,e,n,r,i){return void 0===i&&(i=1.70158),(n-e)*(t/=r)*t*((i+1)*t-i)+e},easeOutBack:function(t,e,n,r,i){return void 0===i&&(i=1.70158),(n-e)*((t=t/r-1)*t*((i+1)*t+i)+1)+e},easeInOutBack:function(t,e,n,r,i){var o=n-e;return void 0===i&&(i=1.70158),(t/=r/2)<1?o/2*(t*t*((1+(i*=1.525))*t-i))+e:o/2*((t-=2)*t*((1+(i*=1.525))*t+i)+2)+e},easeInBounce:function(t,e,n,i){var o=n-e;return o-r.easeOutBounce(i-t,0,o,i)+e},easeOutBounce:function(t,e,n,r){var i=n-e;return (t/=r)<1/2.75?i*(7.5625*t*t)+e:t<2/2.75?i*(7.5625*(t-=1.5/2.75)*t+.75)+e:t<2.5/2.75?i*(7.5625*(t-=2.25/2.75)*t+.9375)+e:i*(7.5625*(t-=2.625/2.75)*t+.984375)+e},easeInOutBounce:function(t,e,n,i){var o=n-e;return t<i/2?.5*r.easeInBounce(2*t,0,o,i)+e:.5*r.easeOutBounce(2*t-i,0,o,i)+.5*o+e}};t.exports=r;},function(t,e,n){t.exports=n(3);},function(t,e,n){n.r(e),n.d(e,"ReactConfetti",(function(){return Q}));var r,i,o=n(0),a=n.n(o),c=n(1),s=n.n(c);function u(t,e){return t+Math.random()*(e-t)}function f(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r);}}function h(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}!function(t){t[t.Circle=0]="Circle",t[t.Square=1]="Square",t[t.Strip=2]="Strip";}(r||(r={})),function(t){t[t.Positive=1]="Positive",t[t.Negative=-1]="Negative";}(i||(i={}));var l=function(){function t(e,n,r,o){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),h(this,"context",void 0),h(this,"radius",void 0),h(this,"x",void 0),h(this,"y",void 0),h(this,"w",void 0),h(this,"h",void 0),h(this,"vx",void 0),h(this,"vy",void 0),h(this,"shape",void 0),h(this,"angle",void 0),h(this,"angularSpin",void 0),h(this,"color",void 0),h(this,"rotateY",void 0),h(this,"rotationDirection",void 0),h(this,"getOptions",void 0),this.getOptions=n;var a,c,s=this.getOptions(),f=s.colors,l=s.initialVelocityX,p=s.initialVelocityY;this.context=e,this.x=r,this.y=o,this.w=u(5,20),this.h=u(5,20),this.radius=u(5,10),this.vx="number"==typeof l?u(-l,l):u(l.min,l.max),this.vy="number"==typeof p?u(-p,0):u(p.min,p.max),this.shape=(a=0,c=2,Math.floor(a+Math.random()*(c-a+1))),this.angle=u(0,360)*Math.PI/180,this.angularSpin=u(-.2,.2),this.color=f[Math.floor(Math.random()*f.length)],this.rotateY=u(0,1),this.rotationDirection=u(0,1)?i.Positive:i.Negative;}var e,n;return e=t,(n=[{key:"update",value:function(){var t=this.getOptions(),e=t.gravity,n=t.wind,o=t.friction,a=t.opacity,c=t.drawShape;this.x+=this.vx,this.y+=this.vy,this.vy+=e,this.vx+=n,this.vx*=o,this.vy*=o,this.rotateY>=1&&this.rotationDirection===i.Positive?this.rotationDirection=i.Negative:this.rotateY<=-1&&this.rotationDirection===i.Negative&&(this.rotationDirection=i.Positive);var s=.1*this.rotationDirection;if(this.rotateY+=s,this.angle+=this.angularSpin,this.context.save(),this.context.translate(this.x,this.y),this.context.rotate(this.angle),this.context.scale(1,this.rotateY),this.context.rotate(this.angle),this.context.beginPath(),this.context.fillStyle=this.color,this.context.strokeStyle=this.color,this.context.globalAlpha=a,this.context.lineCap="round",this.context.lineWidth=2,c&&"function"==typeof c)c.call(this,this.context);else switch(this.shape){case r.Circle:this.context.beginPath(),this.context.arc(0,0,this.radius,0,2*Math.PI),this.context.fill();break;case r.Square:this.context.fillRect(-this.w/2,-this.h/2,this.w,this.h);break;case r.Strip:this.context.fillRect(-this.w/6,-this.h/2,this.w/3,this.h);}this.context.closePath(),this.context.restore();}}])&&f(e.prototype,n),t}();function p(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var v=function t(e,n){var r=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),p(this,"canvas",void 0),p(this,"context",void 0),p(this,"getOptions",void 0),p(this,"x",0),p(this,"y",0),p(this,"w",0),p(this,"h",0),p(this,"lastNumberOfPieces",0),p(this,"tweenInitTime",Date.now()),p(this,"particles",[]),p(this,"particlesGenerated",0),p(this,"removeParticleAt",(function(t){r.particles.splice(t,1);})),p(this,"getParticle",(function(){var t=u(r.x,r.w+r.x),e=u(r.y,r.h+r.y);return new l(r.context,r.getOptions,t,e)})),p(this,"animate",(function(){var t=r.canvas,e=r.context,n=r.particlesGenerated,i=r.lastNumberOfPieces,o=r.getOptions(),a=o.run,c=o.recycle,s=o.numberOfPieces,u=o.debug,f=o.tweenFunction,h=o.tweenDuration;if(!a)return !1;var l=r.particles.length,p=c?l:n,v=Date.now();if(p<s){i!==s&&(r.tweenInitTime=v,r.lastNumberOfPieces=s);for(var y=r.tweenInitTime,d=f(v-y>h?h:Math.max(0,v-y),p,s,h),b=Math.round(d-p),g=0;g<b;g++)r.particles.push(r.getParticle());r.particlesGenerated+=b;}return u&&(e.font="12px sans-serif",e.fillStyle="#333",e.textAlign="right",e.fillText("Particles: ".concat(l),t.width-10,t.height-20)),r.particles.forEach((function(e,n){e.update(),(e.y>t.height||e.y<-100||e.x>t.width+100||e.x<-100)&&(c&&p<=s?r.particles[n]=r.getParticle():r.removeParticleAt(n));})),l>0||p<s})),this.canvas=e;var i=this.canvas.getContext("2d");if(!i)throw new Error("Could not get canvas context");this.context=i,this.getOptions=n;};function y(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r);}return n}function d(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?y(Object(n),!0).forEach((function(e){g(t,e,n[e]);})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(n)):y(Object(n)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(n,e));}));}return t}function b(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r);}}function g(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var O={width:"undefined"!=typeof window?window.innerWidth:300,height:"undefined"!=typeof window?window.innerHeight:200,numberOfPieces:200,friction:.99,wind:0,gravity:.1,initialVelocityX:4,initialVelocityY:10,colors:["#f44336","#e91e63","#9c27b0","#673ab7","#3f51b5","#2196f3","#03a9f4","#00bcd4","#009688","#4CAF50","#8BC34A","#CDDC39","#FFEB3B","#FFC107","#FF9800","#FF5722","#795548"],opacity:1,debug:!1,tweenFunction:s.a.easeInOutQuad,tweenDuration:5e3,recycle:!0,run:!0},w=function(){function t(e,n){var r=this;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),g(this,"canvas",void 0),g(this,"context",void 0),g(this,"_options",void 0),g(this,"generator",void 0),g(this,"rafId",void 0),g(this,"setOptionsWithDefaults",(function(t){var e={confettiSource:{x:0,y:0,w:r.canvas.width,h:0}};r._options=d(d(d({},e),O),t),Object.assign(r,t.confettiSource);})),g(this,"update",(function(){var t=r.options,e=t.run,n=t.onConfettiComplete,i=r.canvas,o=r.context;e&&(o.fillStyle="white",o.clearRect(0,0,i.width,i.height)),r.generator.animate()?r.rafId=requestAnimationFrame(r.update):(n&&"function"==typeof n&&r.generator.particlesGenerated>0&&n.call(r,r),r._options.run=!1);})),g(this,"reset",(function(){r.generator&&r.generator.particlesGenerated>0&&(r.generator.particlesGenerated=0,r.generator.particles=[],r.generator.lastNumberOfPieces=0);})),g(this,"stop",(function(){r.options={run:!1},r.rafId&&(cancelAnimationFrame(r.rafId),r.rafId=void 0);})),this.canvas=e;var i=this.canvas.getContext("2d");if(!i)throw new Error("Could not get canvas context");this.context=i,this.generator=new v(this.canvas,(function(){return r.options})),this.options=n,this.update();}var e,n;return e=t,(n=[{key:"options",get:function(){return this._options},set:function(t){var e=this._options&&this._options.run,n=this._options&&this._options.recycle;this.setOptionsWithDefaults(t),this.generator&&(Object.assign(this.generator,this.options.confettiSource),"boolean"==typeof t.recycle&&t.recycle&&!1===n&&(this.generator.lastNumberOfPieces=this.generator.particles.length)),"boolean"==typeof t.run&&t.run&&!1===e&&this.update();}}])&&b(e.prototype,n),t}();function m(t){return function(t){if(Array.isArray(t))return C(t)}(t)||function(t){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(t))return Array.from(t)}(t)||S(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function x(t){return (x="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function P(){return (P=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r]);}return t}).apply(this,arguments)}function j(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r);}return n}function M(t){for(var e=1;e<arguments.length;e++){var n=null!=arguments[e]?arguments[e]:{};e%2?j(Object(n),!0).forEach((function(e){T(t,e,n[e]);})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(n)):j(Object(n)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(n,e));}));}return t}function I(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){if("undefined"==typeof Symbol||!(Symbol.iterator in Object(t)))return;var n=[],r=!0,i=!1,o=void 0;try{for(var a,c=t[Symbol.iterator]();!(r=(a=c.next()).done)&&(n.push(a.value),!e||n.length!==e);r=!0);}catch(t){i=!0,o=t;}finally{try{r||null==c.return||c.return();}finally{if(i)throw o}}return n}(t,e)||S(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function S(t,e){if(t){if("string"==typeof t)return C(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return "Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?C(t,e):void 0}}function C(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n<e;n++)r[n]=t[n];return r}function D(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function E(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r);}}function _(t,e){return (_=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function R(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return !1;if(Reflect.construct.sham)return !1;if("function"==typeof Proxy)return !0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return !1}}();return function(){var n,r=F(t);if(e){var i=F(this).constructor;n=Reflect.construct(r,arguments,i);}else n=r.apply(this,arguments);return k(this,n)}}function k(t,e){return !e||"object"!==x(e)&&"function"!=typeof e?A(t):e}function A(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}function F(t){return (F=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}function T(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var B=a.a.createRef(),N=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&_(t,e);}(o,t);var e,n,i=R(o);function o(t){var e;D(this,o);for(var n=arguments.length,r=new Array(n>1?n-1:0),c=1;c<n;c++)r[c-1]=arguments[c];return T(A(e=i.call.apply(i,[this,t].concat(r))),"canvas",a.a.createRef()),T(A(e),"confetti",void 0),e.canvas=t.canvasRef||B,e}return e=o,(n=[{key:"componentDidMount",value:function(){if(this.canvas.current){var t=q(this.props)[0];this.confetti=new w(this.canvas.current,t);}}},{key:"componentDidUpdate",value:function(){var t=q(this.props)[0];this.confetti&&(this.confetti.options=t);}},{key:"componentWillUnmount",value:function(){this.confetti&&this.confetti.stop(),this.confetti=void 0;}},{key:"render",value:function(){var t=I(q(this.props),2),e=t[0],n=t[1],r=M({zIndex:2,position:"absolute",pointerEvents:"none",top:0,left:0,bottom:0,right:0},n.style);return a.a.createElement("canvas",P({width:e.width,height:e.height,ref:this.canvas},n,{style:r}))}}])&&E(e.prototype,n),o}(o.Component);function q(t){var e={},n={},r=[].concat(m(Object.keys(O)),["confettiSource","drawShape","onConfettiComplete"]),i=["canvasRef"];for(var o in t){var a=t[o];r.includes(o)?e[o]=a:i.includes(o)?i[o]=a:n[o]=a;}return [e,n,{}]}T(N,"defaultProps",M({},O)),T(N,"displayName","ReactConfetti");var Q=a.a.forwardRef((function(t,e){return a.a.createElement(N,P({canvasRef:e},t))}));e.default=Q;}]).default}));
102
+
103
+ } (reactConfetti_min));
104
+
105
+ var reactConfetti_minExports = reactConfetti_min.exports;
106
+ var Confetti = /*@__PURE__*/getDefaultExportFromCjs(reactConfetti_minExports);
107
+
108
+ function on(obj) {
109
+ var args = [];
110
+ for (var _i = 1; _i < arguments.length; _i++) {
111
+ args[_i - 1] = arguments[_i];
112
+ }
113
+ if (obj && obj.addEventListener) {
114
+ obj.addEventListener.apply(obj, args);
115
+ }
116
+ }
117
+ function off(obj) {
118
+ var args = [];
119
+ for (var _i = 1; _i < arguments.length; _i++) {
120
+ args[_i - 1] = arguments[_i];
121
+ }
122
+ if (obj && obj.removeEventListener) {
123
+ obj.removeEventListener.apply(obj, args);
124
+ }
125
+ }
126
+ var isBrowser = typeof window !== 'undefined';
127
+
128
+ var useEffectOnce = function (effect) {
129
+ useEffect(effect, []);
130
+ };
131
+
132
+ var useUnmount = function (fn) {
133
+ var fnRef = useRef(fn);
134
+ // update the ref each render so if it change the newest callback will be invoked
135
+ fnRef.current = fn;
136
+ useEffectOnce(function () { return function () { return fnRef.current(); }; });
137
+ };
138
+
139
+ var useRafState = function (initialState) {
140
+ var frame = useRef(0);
141
+ var _a = useState(initialState), state = _a[0], setState = _a[1];
142
+ var setRafState = useCallback(function (value) {
143
+ cancelAnimationFrame(frame.current);
144
+ frame.current = requestAnimationFrame(function () {
145
+ setState(value);
146
+ });
147
+ }, []);
148
+ useUnmount(function () {
149
+ cancelAnimationFrame(frame.current);
150
+ });
151
+ return [state, setRafState];
152
+ };
153
+
154
+ var useWindowSize = function (initialWidth, initialHeight) {
155
+ if (initialWidth === void 0) { initialWidth = Infinity; }
156
+ if (initialHeight === void 0) { initialHeight = Infinity; }
157
+ var _a = useRafState({
158
+ width: isBrowser ? window.innerWidth : initialWidth,
159
+ height: isBrowser ? window.innerHeight : initialHeight,
160
+ }), state = _a[0], setState = _a[1];
161
+ useEffect(function () {
162
+ if (isBrowser) {
163
+ var handler_1 = function () {
164
+ setState({
165
+ width: window.innerWidth,
166
+ height: window.innerHeight,
167
+ });
168
+ };
169
+ on(window, 'resize', handler_1);
170
+ return function () {
171
+ off(window, 'resize', handler_1);
172
+ };
173
+ }
174
+ }, []);
175
+ return state;
176
+ };
177
+
178
+ const ConfettiWrapper = ({ show, confettiProps }) => {
179
+ const { width, height } = useWindowSize();
180
+ if (!show)
181
+ return null;
182
+ return (React.createElement(Confetti, Object.assign({ width: width, height: height }, confettiProps)));
183
+ };
184
+
112
185
  const AchievementContext = createContext(undefined);
113
- const AchievementProvider = ({ children, initialBadges = defaultBadges, initialLevels = defaultLevels, storageKey = 'react-achievements', badgesButtonPosition = 'top-right' }) => {
114
- const [metric, setMetric] = useState(() => {
115
- const saved = localStorage.getItem(`${storageKey}-metric`);
116
- return saved ? parseInt(saved, 10) : 0;
186
+ const AchievementProvider = ({ children, config, initialState = {}, storageKey = 'react-achievements', badgesButtonPosition = 'top-right' }) => {
187
+ const extractMetrics = (state) => {
188
+ return Object.keys(config).reduce((acc, key) => {
189
+ if (key in state) {
190
+ acc[key] = state[key];
191
+ }
192
+ return acc;
193
+ }, {});
194
+ };
195
+ const [metrics, setMetrics] = useState(() => {
196
+ const savedMetrics = localStorage.getItem(`${storageKey}-metrics`);
197
+ if (savedMetrics) {
198
+ return JSON.parse(savedMetrics);
199
+ }
200
+ return extractMetrics(initialState);
117
201
  });
118
- const [achievedLevels, setAchievedLevels] = useState(() => {
119
- const saved = localStorage.getItem(`${storageKey}-levels`);
202
+ const [achievedAchievements, setAchievedAchievements] = useState(() => {
203
+ const saved = localStorage.getItem(`${storageKey}-achievements`);
120
204
  return saved ? JSON.parse(saved) : [];
121
205
  });
122
- const [badges] = useState(initialBadges);
123
- const [levels] = useState(initialLevels);
124
- const [achievementModalMessage, setAchievementModalMessage] = useState('');
206
+ const [newAchievement, setNewAchievement] = useState(null);
125
207
  const [showBadges, setShowBadges] = useState(false);
126
- const handleAchieve = useCallback((level, message) => {
127
- if (!achievedLevels.includes(level)) {
128
- const newAchievedLevels = [...achievedLevels, level];
129
- setAchievedLevels(newAchievedLevels);
130
- localStorage.setItem(`${storageKey}-levels`, JSON.stringify(newAchievedLevels));
131
- setAchievementModalMessage(message);
208
+ const [showConfetti, setShowConfetti] = useState(false);
209
+ useEffect(() => {
210
+ localStorage.setItem(`${storageKey}-metrics`, JSON.stringify(metrics));
211
+ }, [metrics, storageKey]);
212
+ const checkAchievements = useCallback(() => {
213
+ const newAchievements = [];
214
+ Object.entries(config).forEach(([metricKey, conditions]) => {
215
+ const metricValue = metrics[metricKey];
216
+ conditions.forEach(condition => {
217
+ if (condition.check(metricValue) && !achievedAchievements.includes(condition.data.id)) {
218
+ newAchievements.push(condition.data);
219
+ }
220
+ });
221
+ });
222
+ if (newAchievements.length > 0) {
223
+ const updatedAchievements = [...achievedAchievements, ...newAchievements.map(a => a.id)];
224
+ setAchievedAchievements(updatedAchievements);
225
+ localStorage.setItem(`${storageKey}-achievements`, JSON.stringify(updatedAchievements));
226
+ setNewAchievement(newAchievements[0]);
227
+ setShowConfetti(true);
132
228
  }
133
- }, [achievedLevels, storageKey]);
134
- const showAchievementModal = useCallback((message) => {
135
- setAchievementModalMessage(message);
136
- }, []);
137
- const showBadgesModal = useCallback(() => {
229
+ }, [config, metrics, achievedAchievements, storageKey]);
230
+ useEffect(() => {
231
+ checkAchievements();
232
+ }, [checkAchievements]);
233
+ const showBadgesModal = () => {
138
234
  setShowBadges(true);
139
- }, []);
140
- const contextValue = useMemo(() => ({
141
- metric,
142
- setMetric: (value) => {
143
- setMetric(value);
144
- localStorage.setItem(`${storageKey}-metric`, value.toString());
235
+ };
236
+ const contextValue = {
237
+ metrics,
238
+ setMetrics: (newMetrics) => {
239
+ setMetrics(prevMetrics => {
240
+ const updatedMetrics = typeof newMetrics === 'function' ? newMetrics(prevMetrics) : newMetrics;
241
+ return updatedMetrics;
242
+ });
145
243
  },
146
- badges,
147
- levels,
148
- achievedLevels,
149
- handleAchieve,
150
- showAchievementModal,
244
+ achievedAchievements,
245
+ checkAchievements,
151
246
  showBadgesModal
152
- }), [metric, badges, levels, achievedLevels, handleAchieve, showAchievementModal, showBadgesModal, storageKey]);
247
+ };
153
248
  return (React.createElement(AchievementContext.Provider, { value: contextValue },
154
249
  children,
155
- React.createElement(AchievementModal$1, { show: !!achievementModalMessage, message: achievementModalMessage, onClose: () => setAchievementModalMessage('') }),
156
- React.createElement(BadgesModal$1, { show: showBadges, badges: badges.filter(badge => { var _a; return achievedLevels.includes(((_a = levels.find(level => level.badgeId === badge.id)) === null || _a === void 0 ? void 0 : _a.level) || -1); }), onClose: () => setShowBadges(false) }),
157
- React.createElement(BadgesButton$1, { onClick: showBadgesModal, position: badgesButtonPosition })));
250
+ React.createElement(AchievementModal$1, { show: !!newAchievement, achievement: newAchievement, onClose: () => {
251
+ setNewAchievement(null);
252
+ setShowConfetti(false);
253
+ } }),
254
+ React.createElement(BadgesModal$1, { show: showBadges, achievements: Object.values(config).flatMap(conditions => conditions.filter(c => achievedAchievements.includes(c.data.id)).map(c => c.data)), onClose: () => setShowBadges(false) }),
255
+ React.createElement(BadgesButton$1, { onClick: showBadgesModal, position: badgesButtonPosition }),
256
+ React.createElement(ConfettiWrapper, { show: showConfetti })));
158
257
  };
159
258
  const useAchievement = () => {
160
259
  const context = useContext(AchievementContext);
@@ -164,20 +263,4 @@ const useAchievement = () => {
164
263
  return context;
165
264
  };
166
265
 
167
- const Achievement = ({ metric, threshold, onAchieve, message, children }) => {
168
- const { setMetric, achievedLevels, levels, handleAchieve } = useAchievement();
169
- useEffect(() => {
170
- if (metric >= threshold && !achievedLevels.includes(threshold)) {
171
- onAchieve();
172
- const levelConfig = levels.find(level => level.threshold === threshold);
173
- if (levelConfig) {
174
- setMetric(metric);
175
- handleAchieve(levelConfig.level, message);
176
- }
177
- }
178
- }, [metric, threshold, onAchieve, achievedLevels, levels, message, setMetric, handleAchieve]);
179
- return React.createElement(React.Fragment, null, children);
180
- };
181
- var Achievement$1 = React.memo(Achievement);
182
-
183
- export { Achievement$1 as Achievement, AchievementProvider, useAchievement };
266
+ export { AchievementProvider, ConfettiWrapper, useAchievement };
@@ -0,0 +1,17 @@
1
+ export type MetricValue = number | boolean | string | any;
2
+ export interface Metrics {
3
+ [key: string]: MetricValue;
4
+ }
5
+ export interface AchievementData {
6
+ id: string;
7
+ title: string;
8
+ description: string;
9
+ icon: string;
10
+ }
11
+ export interface AchievementCondition {
12
+ check: (metricValue: MetricValue) => boolean;
13
+ data: AchievementData;
14
+ }
15
+ export interface AchievementConfig {
16
+ [metricKey: string]: AchievementCondition[];
17
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-achievements",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "This package allows users to transpose a React achievements engine over their React apps",
5
5
  "keywords": [
6
6
  "react",
@@ -1,13 +1,14 @@
1
1
  import React from 'react';
2
+ import { AchievementData } from '../types';
2
3
 
3
4
  interface AchievementModalProps {
4
5
  show: boolean;
5
- message: string;
6
+ achievement: AchievementData | null;
6
7
  onClose: () => void;
7
8
  }
8
9
 
9
- const AchievementModal: React.FC<AchievementModalProps> = ({ show, message, onClose }) => {
10
- if (!show) return null;
10
+ const AchievementModal: React.FC<AchievementModalProps> = ({ show, achievement, onClose }) => {
11
+ if (!show || !achievement) return null;
11
12
 
12
13
  const modalStyle: React.CSSProperties = {
13
14
  position: 'fixed',
@@ -36,7 +37,9 @@ const AchievementModal: React.FC<AchievementModalProps> = ({ show, message, onCl
36
37
  <div style={overlayStyle} onClick={onClose} />
37
38
  <div style={modalStyle} role="dialog" aria-modal="true" aria-labelledby="achievement-title">
38
39
  <h2 id="achievement-title">Achievement Unlocked!</h2>
39
- <p>{message}</p>
40
+ <img src={achievement.icon} alt={achievement.title} style={{ width: '50px', height: '50px' }} />
41
+ <h3>{achievement.title}</h3>
42
+ <p>{achievement.description}</p>
40
43
  <button onClick={onClose}>Okay</button>
41
44
  </div>
42
45
  </>
@@ -1,13 +1,13 @@
1
1
  import React from 'react';
2
- import { BadgeConfig } from '../badges';
2
+ import { AchievementData } from '../types';
3
3
 
4
4
  interface BadgesModalProps {
5
5
  show: boolean;
6
- badges: BadgeConfig[];
6
+ achievements: AchievementData[];
7
7
  onClose: () => void;
8
8
  }
9
9
 
10
- const BadgesModal: React.FC<BadgesModalProps> = ({ show, badges, onClose }) => {
10
+ const BadgesModal: React.FC<BadgesModalProps> = ({ show, achievements, onClose }) => {
11
11
  if (!show) return null;
12
12
 
13
13
  const modalStyle: React.CSSProperties = {
@@ -41,11 +41,11 @@ const BadgesModal: React.FC<BadgesModalProps> = ({ show, badges, onClose }) => {
41
41
  <div style={modalStyle} role="dialog" aria-modal="true" aria-labelledby="badges-title">
42
42
  <h2 id="badges-title">Your Achievements</h2>
43
43
  <div style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'center' }}>
44
- {badges.map(badge => (
45
- <div key={badge.id} style={{ margin: '10px', textAlign: 'center' }}>
46
- <img src={badge.icon} alt={badge.title} style={{ width: '50px', height: '50px' }} />
47
- <h4>{badge.title}</h4>
48
- <p>{badge.description}</p>
44
+ {achievements.map(achievement => (
45
+ <div key={achievement.id} style={{ margin: '10px', textAlign: 'center' }}>
46
+ <img src={achievement.icon} alt={achievement.title} style={{ width: '50px', height: '50px' }} />
47
+ <h4>{achievement.title}</h4>
48
+ <p>{achievement.description}</p>
49
49
  </div>
50
50
  ))}
51
51
  </div>
@@ -1,15 +1,25 @@
1
1
  import React from 'react';
2
2
  import Confetti from 'react-confetti';
3
3
  import { useWindowSize } from 'react-use';
4
+ import { ConfettiProps } from 'react-confetti';
4
5
 
5
6
  interface ConfettiWrapperProps {
6
7
  show: boolean;
8
+ confettiProps?: Partial<ConfettiProps>;
7
9
  }
8
10
 
9
- const ConfettiWrapper: React.FC<ConfettiWrapperProps> = ({ show }) => {
11
+ const ConfettiWrapper: React.FC<ConfettiWrapperProps> = ({ show, confettiProps }) => {
10
12
  const { width, height } = useWindowSize();
11
13
 
12
- return show ? <Confetti width={width} height={height} /> : null;
14
+ if (!show) return null;
15
+
16
+ return (
17
+ <Confetti
18
+ width={width}
19
+ height={height}
20
+ {...confettiProps}
21
+ />
22
+ );
13
23
  };
14
24
 
15
- export default ConfettiWrapper;
25
+ export default ConfettiWrapper;
@@ -1,25 +1,22 @@
1
- import React, { createContext, useContext, useState, ReactNode, useCallback, useMemo } from 'react';
2
- import { defaultBadges, BadgeConfig } from '../badges';
3
- import { defaultLevels, LevelConfig } from '../levels';
1
+ import React, { createContext, useContext, useState, useEffect, useCallback, ReactNode } from 'react';
2
+ import { Metrics, AchievementConfig, AchievementData } from '../types';
4
3
  import AchievementModal from '../components/AchievementModal';
5
4
  import BadgesModal from '../components/BadgesModal';
6
5
  import BadgesButton from '../components/BadgesButton';
6
+ import ConfettiWrapper from '../components/ConfettiWrapper';
7
7
 
8
8
  interface AchievementContextProps {
9
- metric: number;
10
- setMetric: (value: number) => void;
11
- badges: BadgeConfig[];
12
- levels: LevelConfig[];
13
- achievedLevels: number[];
14
- handleAchieve: (level: number, message: string) => void;
15
- showAchievementModal: (message: string) => void;
9
+ metrics: Metrics;
10
+ setMetrics: (metrics: Metrics | ((prevMetrics: Metrics) => Metrics)) => void;
11
+ achievedAchievements: string[];
12
+ checkAchievements: () => void;
16
13
  showBadgesModal: () => void;
17
14
  }
18
15
 
19
16
  interface AchievementProviderProps {
20
17
  children: ReactNode;
21
- initialBadges?: BadgeConfig[];
22
- initialLevels?: LevelConfig[];
18
+ config: AchievementConfig;
19
+ initialState?: Record<string, any>;
23
20
  storageKey?: string;
24
21
  badgesButtonPosition?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
25
22
  }
@@ -28,69 +25,103 @@ const AchievementContext = createContext<AchievementContextProps | undefined>(un
28
25
 
29
26
  export const AchievementProvider: React.FC<AchievementProviderProps> = ({
30
27
  children,
31
- initialBadges = defaultBadges,
32
- initialLevels = defaultLevels,
28
+ config,
29
+ initialState = {},
33
30
  storageKey = 'react-achievements',
34
31
  badgesButtonPosition = 'top-right'
35
32
  }) => {
36
- const [metric, setMetric] = useState(() => {
37
- const saved = localStorage.getItem(`${storageKey}-metric`);
38
- return saved ? parseInt(saved, 10) : 0;
33
+ const extractMetrics = (state: Record<string, any>): Metrics => {
34
+ return Object.keys(config).reduce((acc, key) => {
35
+ if (key in state) {
36
+ acc[key] = state[key];
37
+ }
38
+ return acc;
39
+ }, {} as Metrics);
40
+ };
41
+
42
+ const [metrics, setMetrics] = useState<Metrics>(() => {
43
+ const savedMetrics = localStorage.getItem(`${storageKey}-metrics`);
44
+ if (savedMetrics) {
45
+ return JSON.parse(savedMetrics);
46
+ }
47
+ return extractMetrics(initialState);
39
48
  });
40
- const [achievedLevels, setAchievedLevels] = useState<number[]>(() => {
41
- const saved = localStorage.getItem(`${storageKey}-levels`);
49
+
50
+ const [achievedAchievements, setAchievedAchievements] = useState<string[]>(() => {
51
+ const saved = localStorage.getItem(`${storageKey}-achievements`);
42
52
  return saved ? JSON.parse(saved) : [];
43
53
  });
44
- const [badges] = useState<BadgeConfig[]>(initialBadges);
45
- const [levels] = useState<LevelConfig[]>(initialLevels);
46
- const [achievementModalMessage, setAchievementModalMessage] = useState('');
54
+
55
+ const [newAchievement, setNewAchievement] = useState<AchievementData | null>(null);
47
56
  const [showBadges, setShowBadges] = useState(false);
57
+ const [showConfetti, setShowConfetti] = useState(false);
58
+
59
+ useEffect(() => {
60
+ localStorage.setItem(`${storageKey}-metrics`, JSON.stringify(metrics));
61
+ }, [metrics, storageKey]);
62
+
63
+ const checkAchievements = useCallback(() => {
64
+ const newAchievements: AchievementData[] = [];
65
+
66
+ Object.entries(config).forEach(([metricKey, conditions]) => {
67
+ const metricValue = metrics[metricKey];
68
+ conditions.forEach(condition => {
69
+ if (condition.check(metricValue) && !achievedAchievements.includes(condition.data.id)) {
70
+ newAchievements.push(condition.data);
71
+ }
72
+ });
73
+ });
48
74
 
49
- const handleAchieve = useCallback((level: number, message: string) => {
50
- if (!achievedLevels.includes(level)) {
51
- const newAchievedLevels = [...achievedLevels, level];
52
- setAchievedLevels(newAchievedLevels);
53
- localStorage.setItem(`${storageKey}-levels`, JSON.stringify(newAchievedLevels));
54
- setAchievementModalMessage(message);
75
+ if (newAchievements.length > 0) {
76
+ const updatedAchievements = [...achievedAchievements, ...newAchievements.map(a => a.id)];
77
+ setAchievedAchievements(updatedAchievements);
78
+ localStorage.setItem(`${storageKey}-achievements`, JSON.stringify(updatedAchievements));
79
+ setNewAchievement(newAchievements[0]);
80
+ setShowConfetti(true);
55
81
  }
56
- }, [achievedLevels, storageKey]);
82
+ }, [config, metrics, achievedAchievements, storageKey]);
57
83
 
58
- const showAchievementModal = useCallback((message: string) => {
59
- setAchievementModalMessage(message);
60
- }, []);
84
+ useEffect(() => {
85
+ checkAchievements();
86
+ }, [checkAchievements]);
61
87
 
62
- const showBadgesModal = useCallback(() => {
88
+ const showBadgesModal = () => {
63
89
  setShowBadges(true);
64
- }, []);
90
+ };
65
91
 
66
- const contextValue = useMemo(() => ({
67
- metric,
68
- setMetric: (value: number) => {
69
- setMetric(value);
70
- localStorage.setItem(`${storageKey}-metric`, value.toString());
92
+ const contextValue: AchievementContextProps = {
93
+ metrics,
94
+ setMetrics: (newMetrics) => {
95
+ setMetrics(prevMetrics => {
96
+ const updatedMetrics = typeof newMetrics === 'function' ? newMetrics(prevMetrics) : newMetrics;
97
+ return updatedMetrics;
98
+ });
71
99
  },
72
- badges,
73
- levels,
74
- achievedLevels,
75
- handleAchieve,
76
- showAchievementModal,
100
+ achievedAchievements,
101
+ checkAchievements,
77
102
  showBadgesModal
78
- }), [metric, badges, levels, achievedLevels, handleAchieve, showAchievementModal, showBadgesModal, storageKey]);
103
+ };
79
104
 
80
105
  return (
81
106
  <AchievementContext.Provider value={contextValue}>
82
107
  {children}
83
108
  <AchievementModal
84
- show={!!achievementModalMessage}
85
- message={achievementModalMessage}
86
- onClose={() => setAchievementModalMessage('')}
109
+ show={!!newAchievement}
110
+ achievement={newAchievement}
111
+ onClose={() => {
112
+ setNewAchievement(null);
113
+ setShowConfetti(false);
114
+ }}
87
115
  />
88
116
  <BadgesModal
89
117
  show={showBadges}
90
- badges={badges.filter(badge => achievedLevels.includes(levels.find(level => level.badgeId === badge.id)?.level || -1))}
118
+ achievements={Object.values(config).flatMap(conditions =>
119
+ conditions.filter(c => achievedAchievements.includes(c.data.id)).map(c => c.data)
120
+ )}
91
121
  onClose={() => setShowBadges(false)}
92
122
  />
93
123
  <BadgesButton onClick={showBadgesModal} position={badgesButtonPosition} />
124
+ <ConfettiWrapper show={showConfetti} />
94
125
  </AchievementContext.Provider>
95
126
  );
96
127
  };
package/src/index.ts CHANGED
@@ -1,6 +1,13 @@
1
1
  import { AchievementProvider, useAchievement } from './context/AchievementContext';
2
- import Achievement from './components/Achievement';
3
- import { BadgeConfig } from './badges';
4
- import { LevelConfig } from './levels';
2
+ import { Metrics, AchievementConfig, AchievementData, AchievementCondition } from './types';
3
+ import ConfettiWrapper from './components/ConfettiWrapper';
5
4
 
6
- export { AchievementProvider, useAchievement, Achievement, BadgeConfig, LevelConfig };
5
+ export {
6
+ AchievementProvider,
7
+ useAchievement,
8
+ Metrics,
9
+ AchievementConfig,
10
+ AchievementData,
11
+ AchievementCondition,
12
+ ConfettiWrapper
13
+ };