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/README.md +143 -0
- package/dist/components/AchievementModal.d.ts +2 -1
- package/dist/components/BadgesModal.d.ts +2 -2
- package/dist/components/ConfettiWrapper.d.ts +2 -0
- package/dist/context/AchievementContext.d.ts +7 -11
- package/dist/index.cjs.js +165 -82
- package/dist/index.d.ts +3 -4
- package/dist/index.esm.js +167 -84
- package/dist/types.d.ts +17 -0
- package/package.json +1 -1
- package/src/components/AchievementModal.tsx +7 -4
- package/src/components/BadgesModal.tsx +8 -8
- package/src/components/ConfettiWrapper.tsx +13 -3
- package/src/context/AchievementContext.tsx +80 -49
- package/src/index.ts +11 -4
- package/src/{custom.d.ts → react-confetti.d.ts} +2 -4
- package/src/react-use.d.ts +4 -0
- package/src/types.ts +21 -0
- package/tsconfig.json +3 -1
- package/src/badges.ts +0 -24
- package/src/components/Achievement.tsx +0 -29
- package/src/components/Progress.tsx +0 -37
- package/src/levels.ts +0 -13
package/README.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Welcome to React-Achievements!
|
|
2
|
+
|
|
3
|
+
A flexible and customizable achievement system for React applications.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
The first thing you need to do is install react-achievements:
|
|
8
|
+
|
|
9
|
+
`npm install react-achievements`
|
|
10
|
+
|
|
11
|
+
or if you're using yarn:
|
|
12
|
+
`yarn add react-achievements`
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
### Set up the AchievementProvider
|
|
17
|
+
|
|
18
|
+
Wrap your app or a part of your app with the AchievementProvider:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
import { AchievementProvider } from 'react-achievements';
|
|
22
|
+
import achievementConfig from './achievementConfig';
|
|
23
|
+
|
|
24
|
+
function App() {
|
|
25
|
+
return (
|
|
26
|
+
<AchievementProvider config={achievementConfig} initialState={<your_object>}>
|
|
27
|
+
{/* Your app components */}
|
|
28
|
+
</AchievementProvider>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The object that you pass to the initialState prop should have keys that match the metrics defined in your achievement configuration. For example, if your achievement configuration defines a 'transactions' metric, your initialState object should look like this:
|
|
34
|
+
```typescript
|
|
35
|
+
const user = {
|
|
36
|
+
transactions: [
|
|
37
|
+
{
|
|
38
|
+
id: 1,
|
|
39
|
+
amount: 100
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: 2,
|
|
43
|
+
amount: 200
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Create an achievement configuration
|
|
50
|
+
Create a file (e.g., achievementConfig.js) to define your achievements:
|
|
51
|
+
```javascript
|
|
52
|
+
const achievementConfig = {
|
|
53
|
+
transactions: [
|
|
54
|
+
{
|
|
55
|
+
check: (value) => value.length >= 1,
|
|
56
|
+
data: {
|
|
57
|
+
id: 'first_transaction',
|
|
58
|
+
title: 'First Transaction',
|
|
59
|
+
description: 'Completed your first transaction',
|
|
60
|
+
icon: '/path/to/icon.png'
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
check: (value) => value.length >= 10,
|
|
65
|
+
data: {
|
|
66
|
+
id: 'ten_transactions',
|
|
67
|
+
title: 'Ten Transactions',
|
|
68
|
+
description: 'Completed ten transactions',
|
|
69
|
+
icon: '/path/to/icon.png'
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
// Add more metrics and achievements as needed
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export default achievementConfig;
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Use the useAchievement hook
|
|
80
|
+
In your components, use the useAchievement hook to update metrics and trigger achievement checks:
|
|
81
|
+
```javascript
|
|
82
|
+
import { useAchievement } from 'react-achievements';
|
|
83
|
+
|
|
84
|
+
function TransactionComponent() {
|
|
85
|
+
const { setMetrics } = useAchievement();
|
|
86
|
+
|
|
87
|
+
const handleNewTransaction = () => {
|
|
88
|
+
// Your transaction logic here
|
|
89
|
+
setMetrics(prevMetrics => ({
|
|
90
|
+
...prevMetrics,
|
|
91
|
+
transactions: (prevMetrics.transactions || 0) + 1
|
|
92
|
+
}));
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<button onClick={handleNewTransaction}>New Transaction</button>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Features
|
|
102
|
+
|
|
103
|
+
### Flexible Achievement System:
|
|
104
|
+
Define custom metrics and achievement conditions.
|
|
105
|
+
|
|
106
|
+
### Automatic Achievement Tracking:
|
|
107
|
+
Achievements are automatically checked and unlocked when metrics change.
|
|
108
|
+
|
|
109
|
+
### Achievement Notifications:
|
|
110
|
+
A modal pops up when an achievement is unlocked.
|
|
111
|
+
|
|
112
|
+
### Persistent Achievements:
|
|
113
|
+
Achieved achievements are stored in local storage.
|
|
114
|
+
|
|
115
|
+
### Achievement Gallery:
|
|
116
|
+
Users can view all their unlocked achievements.
|
|
117
|
+
|
|
118
|
+
### Customizable UI:
|
|
119
|
+
The achievement modal and badges button can be styled to fit your app's design.
|
|
120
|
+
Confetti Effect: A celebratory confetti effect is displayed when an achievement is unlocked.
|
|
121
|
+
|
|
122
|
+
## API
|
|
123
|
+
### AchievementProvider
|
|
124
|
+
#### Props:
|
|
125
|
+
|
|
126
|
+
1. config: An object defining your metrics and achievements.
|
|
127
|
+
storageKey (optional): A string to use as the key for localStorage. Default: 'react-achievements'
|
|
128
|
+
badgesButtonPosition (optional): Position of the badges button. Options: 'top-left', 'top-right', 'bottom-left', 'bottom-right'. Default: 'top-right'
|
|
129
|
+
|
|
130
|
+
2. useAchievement Hook Returns an object with:
|
|
131
|
+
|
|
132
|
+
3. setMetrics: Function to update the metrics.
|
|
133
|
+
|
|
134
|
+
4. metrics: Current metrics object.
|
|
135
|
+
5. achievedAchievements: Array of achieved achievement IDs.
|
|
136
|
+
6. showBadgesModal: Function to manually show the badges modal.
|
|
137
|
+
|
|
138
|
+
Customization
|
|
139
|
+
You can customize the appearance of the achievement modal, badges modal, and badges button by modifying their respective components in the package.
|
|
140
|
+
License
|
|
141
|
+
MIT
|
|
142
|
+
Copy
|
|
143
|
+
This README provides a comprehensive overview of how to use the react-achievements package, including setup, usage examples, features, and API details. You may want to adjust or expand certain sections based on the specific implementation details or additional features of your package.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { AchievementData } from '../types';
|
|
2
3
|
interface AchievementModalProps {
|
|
3
4
|
show: boolean;
|
|
4
|
-
|
|
5
|
+
achievement: AchievementData | null;
|
|
5
6
|
onClose: () => void;
|
|
6
7
|
}
|
|
7
8
|
declare const _default: React.NamedExoticComponent<AchievementModalProps>;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { AchievementData } from '../types';
|
|
3
3
|
interface BadgesModalProps {
|
|
4
4
|
show: boolean;
|
|
5
|
-
|
|
5
|
+
achievements: AchievementData[];
|
|
6
6
|
onClose: () => void;
|
|
7
7
|
}
|
|
8
8
|
declare const _default: React.NamedExoticComponent<BadgesModalProps>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { ConfettiProps } from 'react-confetti';
|
|
2
3
|
interface ConfettiWrapperProps {
|
|
3
4
|
show: boolean;
|
|
5
|
+
confettiProps?: Partial<ConfettiProps>;
|
|
4
6
|
}
|
|
5
7
|
declare const ConfettiWrapper: React.FC<ConfettiWrapperProps>;
|
|
6
8
|
export default ConfettiWrapper;
|
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { LevelConfig } from '../levels';
|
|
2
|
+
import { Metrics, AchievementConfig } from '../types';
|
|
4
3
|
interface AchievementContextProps {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
achievedLevels: number[];
|
|
10
|
-
handleAchieve: (level: number, message: string) => void;
|
|
11
|
-
showAchievementModal: (message: string) => void;
|
|
4
|
+
metrics: Metrics;
|
|
5
|
+
setMetrics: (metrics: Metrics | ((prevMetrics: Metrics) => Metrics)) => void;
|
|
6
|
+
achievedAchievements: string[];
|
|
7
|
+
checkAchievements: () => void;
|
|
12
8
|
showBadgesModal: () => void;
|
|
13
9
|
}
|
|
14
10
|
interface AchievementProviderProps {
|
|
15
11
|
children: ReactNode;
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
config: AchievementConfig;
|
|
13
|
+
initialState?: Record<string, any>;
|
|
18
14
|
storageKey?: string;
|
|
19
15
|
badgesButtonPosition?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
20
16
|
}
|
package/dist/index.cjs.js
CHANGED
|
@@ -2,30 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
var React = require('react');
|
|
4
4
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
id: 'beginner',
|
|
8
|
-
icon: '/path/to/beginner-icon.png',
|
|
9
|
-
title: 'Beginner',
|
|
10
|
-
description: 'Achieved beginner level',
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
id: 'intermediate',
|
|
14
|
-
icon: '/path/to/intermediate-icon.png',
|
|
15
|
-
title: 'Intermediate',
|
|
16
|
-
description: 'Achieved intermediate level',
|
|
17
|
-
},
|
|
18
|
-
// Add more badges as needed
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
const defaultLevels = [
|
|
22
|
-
{ level: 1, threshold: 10, badgeId: 'beginner' },
|
|
23
|
-
{ level: 2, threshold: 50, badgeId: 'intermediate' },
|
|
24
|
-
// Add more levels as needed
|
|
25
|
-
];
|
|
26
|
-
|
|
27
|
-
const AchievementModal = ({ show, message, onClose }) => {
|
|
28
|
-
if (!show)
|
|
5
|
+
const AchievementModal = ({ show, achievement, onClose }) => {
|
|
6
|
+
if (!show || !achievement)
|
|
29
7
|
return null;
|
|
30
8
|
const modalStyle = {
|
|
31
9
|
position: 'fixed',
|
|
@@ -51,12 +29,14 @@ const AchievementModal = ({ show, message, onClose }) => {
|
|
|
51
29
|
React.createElement("div", { style: overlayStyle, onClick: onClose }),
|
|
52
30
|
React.createElement("div", { style: modalStyle, role: "dialog", "aria-modal": "true", "aria-labelledby": "achievement-title" },
|
|
53
31
|
React.createElement("h2", { id: "achievement-title" }, "Achievement Unlocked!"),
|
|
54
|
-
React.createElement("
|
|
32
|
+
React.createElement("img", { src: achievement.icon, alt: achievement.title, style: { width: '50px', height: '50px' } }),
|
|
33
|
+
React.createElement("h3", null, achievement.title),
|
|
34
|
+
React.createElement("p", null, achievement.description),
|
|
55
35
|
React.createElement("button", { onClick: onClose }, "Okay"))));
|
|
56
36
|
};
|
|
57
37
|
var AchievementModal$1 = React.memo(AchievementModal);
|
|
58
38
|
|
|
59
|
-
const BadgesModal = ({ show,
|
|
39
|
+
const BadgesModal = ({ show, achievements, onClose }) => {
|
|
60
40
|
if (!show)
|
|
61
41
|
return null;
|
|
62
42
|
const modalStyle = {
|
|
@@ -86,10 +66,10 @@ const BadgesModal = ({ show, badges, onClose }) => {
|
|
|
86
66
|
React.createElement("div", { style: overlayStyle, onClick: onClose }),
|
|
87
67
|
React.createElement("div", { style: modalStyle, role: "dialog", "aria-modal": "true", "aria-labelledby": "badges-title" },
|
|
88
68
|
React.createElement("h2", { id: "badges-title" }, "Your Achievements"),
|
|
89
|
-
React.createElement("div", { style: { display: 'flex', flexWrap: 'wrap', justifyContent: 'center' } },
|
|
90
|
-
React.createElement("img", { src:
|
|
91
|
-
React.createElement("h4", null,
|
|
92
|
-
React.createElement("p", null,
|
|
69
|
+
React.createElement("div", { style: { display: 'flex', flexWrap: 'wrap', justifyContent: 'center' } }, achievements.map(achievement => (React.createElement("div", { key: achievement.id, style: { margin: '10px', textAlign: 'center' } },
|
|
70
|
+
React.createElement("img", { src: achievement.icon, alt: achievement.title, style: { width: '50px', height: '50px' } }),
|
|
71
|
+
React.createElement("h4", null, achievement.title),
|
|
72
|
+
React.createElement("p", null, achievement.description))))),
|
|
93
73
|
React.createElement("button", { onClick: onClose, style: { marginTop: '20px' } }, "Close"))));
|
|
94
74
|
};
|
|
95
75
|
var BadgesModal$1 = React.memo(BadgesModal);
|
|
@@ -111,52 +91,171 @@ const BadgesButton = ({ onClick, position }) => {
|
|
|
111
91
|
};
|
|
112
92
|
var BadgesButton$1 = React.memo(BadgesButton);
|
|
113
93
|
|
|
94
|
+
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
95
|
+
|
|
96
|
+
function getDefaultExportFromCjs (x) {
|
|
97
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
var reactConfetti_min = {exports: {}};
|
|
101
|
+
|
|
102
|
+
(function (module, exports) {
|
|
103
|
+
!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}));
|
|
104
|
+
|
|
105
|
+
} (reactConfetti_min));
|
|
106
|
+
|
|
107
|
+
var reactConfetti_minExports = reactConfetti_min.exports;
|
|
108
|
+
var Confetti = /*@__PURE__*/getDefaultExportFromCjs(reactConfetti_minExports);
|
|
109
|
+
|
|
110
|
+
function on(obj) {
|
|
111
|
+
var args = [];
|
|
112
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
113
|
+
args[_i - 1] = arguments[_i];
|
|
114
|
+
}
|
|
115
|
+
if (obj && obj.addEventListener) {
|
|
116
|
+
obj.addEventListener.apply(obj, args);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function off(obj) {
|
|
120
|
+
var args = [];
|
|
121
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
122
|
+
args[_i - 1] = arguments[_i];
|
|
123
|
+
}
|
|
124
|
+
if (obj && obj.removeEventListener) {
|
|
125
|
+
obj.removeEventListener.apply(obj, args);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
var isBrowser = typeof window !== 'undefined';
|
|
129
|
+
|
|
130
|
+
var useEffectOnce = function (effect) {
|
|
131
|
+
React.useEffect(effect, []);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
var useUnmount = function (fn) {
|
|
135
|
+
var fnRef = React.useRef(fn);
|
|
136
|
+
// update the ref each render so if it change the newest callback will be invoked
|
|
137
|
+
fnRef.current = fn;
|
|
138
|
+
useEffectOnce(function () { return function () { return fnRef.current(); }; });
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
var useRafState = function (initialState) {
|
|
142
|
+
var frame = React.useRef(0);
|
|
143
|
+
var _a = React.useState(initialState), state = _a[0], setState = _a[1];
|
|
144
|
+
var setRafState = React.useCallback(function (value) {
|
|
145
|
+
cancelAnimationFrame(frame.current);
|
|
146
|
+
frame.current = requestAnimationFrame(function () {
|
|
147
|
+
setState(value);
|
|
148
|
+
});
|
|
149
|
+
}, []);
|
|
150
|
+
useUnmount(function () {
|
|
151
|
+
cancelAnimationFrame(frame.current);
|
|
152
|
+
});
|
|
153
|
+
return [state, setRafState];
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
var useWindowSize = function (initialWidth, initialHeight) {
|
|
157
|
+
if (initialWidth === void 0) { initialWidth = Infinity; }
|
|
158
|
+
if (initialHeight === void 0) { initialHeight = Infinity; }
|
|
159
|
+
var _a = useRafState({
|
|
160
|
+
width: isBrowser ? window.innerWidth : initialWidth,
|
|
161
|
+
height: isBrowser ? window.innerHeight : initialHeight,
|
|
162
|
+
}), state = _a[0], setState = _a[1];
|
|
163
|
+
React.useEffect(function () {
|
|
164
|
+
if (isBrowser) {
|
|
165
|
+
var handler_1 = function () {
|
|
166
|
+
setState({
|
|
167
|
+
width: window.innerWidth,
|
|
168
|
+
height: window.innerHeight,
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
on(window, 'resize', handler_1);
|
|
172
|
+
return function () {
|
|
173
|
+
off(window, 'resize', handler_1);
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}, []);
|
|
177
|
+
return state;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const ConfettiWrapper = ({ show, confettiProps }) => {
|
|
181
|
+
const { width, height } = useWindowSize();
|
|
182
|
+
if (!show)
|
|
183
|
+
return null;
|
|
184
|
+
return (React.createElement(Confetti, Object.assign({ width: width, height: height }, confettiProps)));
|
|
185
|
+
};
|
|
186
|
+
|
|
114
187
|
const AchievementContext = React.createContext(undefined);
|
|
115
|
-
const AchievementProvider = ({ children,
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
188
|
+
const AchievementProvider = ({ children, config, initialState = {}, storageKey = 'react-achievements', badgesButtonPosition = 'top-right' }) => {
|
|
189
|
+
const extractMetrics = (state) => {
|
|
190
|
+
return Object.keys(config).reduce((acc, key) => {
|
|
191
|
+
if (key in state) {
|
|
192
|
+
acc[key] = state[key];
|
|
193
|
+
}
|
|
194
|
+
return acc;
|
|
195
|
+
}, {});
|
|
196
|
+
};
|
|
197
|
+
const [metrics, setMetrics] = React.useState(() => {
|
|
198
|
+
const savedMetrics = localStorage.getItem(`${storageKey}-metrics`);
|
|
199
|
+
if (savedMetrics) {
|
|
200
|
+
return JSON.parse(savedMetrics);
|
|
201
|
+
}
|
|
202
|
+
return extractMetrics(initialState);
|
|
119
203
|
});
|
|
120
|
-
const [
|
|
121
|
-
const saved = localStorage.getItem(`${storageKey}-
|
|
204
|
+
const [achievedAchievements, setAchievedAchievements] = React.useState(() => {
|
|
205
|
+
const saved = localStorage.getItem(`${storageKey}-achievements`);
|
|
122
206
|
return saved ? JSON.parse(saved) : [];
|
|
123
207
|
});
|
|
124
|
-
const [
|
|
125
|
-
const [levels] = React.useState(initialLevels);
|
|
126
|
-
const [achievementModalMessage, setAchievementModalMessage] = React.useState('');
|
|
208
|
+
const [newAchievement, setNewAchievement] = React.useState(null);
|
|
127
209
|
const [showBadges, setShowBadges] = React.useState(false);
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
210
|
+
const [showConfetti, setShowConfetti] = React.useState(false);
|
|
211
|
+
React.useEffect(() => {
|
|
212
|
+
localStorage.setItem(`${storageKey}-metrics`, JSON.stringify(metrics));
|
|
213
|
+
}, [metrics, storageKey]);
|
|
214
|
+
const checkAchievements = React.useCallback(() => {
|
|
215
|
+
const newAchievements = [];
|
|
216
|
+
Object.entries(config).forEach(([metricKey, conditions]) => {
|
|
217
|
+
const metricValue = metrics[metricKey];
|
|
218
|
+
conditions.forEach(condition => {
|
|
219
|
+
if (condition.check(metricValue) && !achievedAchievements.includes(condition.data.id)) {
|
|
220
|
+
newAchievements.push(condition.data);
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
if (newAchievements.length > 0) {
|
|
225
|
+
const updatedAchievements = [...achievedAchievements, ...newAchievements.map(a => a.id)];
|
|
226
|
+
setAchievedAchievements(updatedAchievements);
|
|
227
|
+
localStorage.setItem(`${storageKey}-achievements`, JSON.stringify(updatedAchievements));
|
|
228
|
+
setNewAchievement(newAchievements[0]);
|
|
229
|
+
setShowConfetti(true);
|
|
134
230
|
}
|
|
135
|
-
}, [
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}, []);
|
|
139
|
-
const showBadgesModal =
|
|
231
|
+
}, [config, metrics, achievedAchievements, storageKey]);
|
|
232
|
+
React.useEffect(() => {
|
|
233
|
+
checkAchievements();
|
|
234
|
+
}, [checkAchievements]);
|
|
235
|
+
const showBadgesModal = () => {
|
|
140
236
|
setShowBadges(true);
|
|
141
|
-
}
|
|
142
|
-
const contextValue =
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
237
|
+
};
|
|
238
|
+
const contextValue = {
|
|
239
|
+
metrics,
|
|
240
|
+
setMetrics: (newMetrics) => {
|
|
241
|
+
setMetrics(prevMetrics => {
|
|
242
|
+
const updatedMetrics = typeof newMetrics === 'function' ? newMetrics(prevMetrics) : newMetrics;
|
|
243
|
+
return updatedMetrics;
|
|
244
|
+
});
|
|
147
245
|
},
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
achievedLevels,
|
|
151
|
-
handleAchieve,
|
|
152
|
-
showAchievementModal,
|
|
246
|
+
achievedAchievements,
|
|
247
|
+
checkAchievements,
|
|
153
248
|
showBadgesModal
|
|
154
|
-
}
|
|
249
|
+
};
|
|
155
250
|
return (React.createElement(AchievementContext.Provider, { value: contextValue },
|
|
156
251
|
children,
|
|
157
|
-
React.createElement(AchievementModal$1, { show: !!
|
|
158
|
-
|
|
159
|
-
|
|
252
|
+
React.createElement(AchievementModal$1, { show: !!newAchievement, achievement: newAchievement, onClose: () => {
|
|
253
|
+
setNewAchievement(null);
|
|
254
|
+
setShowConfetti(false);
|
|
255
|
+
} }),
|
|
256
|
+
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) }),
|
|
257
|
+
React.createElement(BadgesButton$1, { onClick: showBadgesModal, position: badgesButtonPosition }),
|
|
258
|
+
React.createElement(ConfettiWrapper, { show: showConfetti })));
|
|
160
259
|
};
|
|
161
260
|
const useAchievement = () => {
|
|
162
261
|
const context = React.useContext(AchievementContext);
|
|
@@ -166,22 +265,6 @@ const useAchievement = () => {
|
|
|
166
265
|
return context;
|
|
167
266
|
};
|
|
168
267
|
|
|
169
|
-
const Achievement = ({ metric, threshold, onAchieve, message, children }) => {
|
|
170
|
-
const { setMetric, achievedLevels, levels, handleAchieve } = useAchievement();
|
|
171
|
-
React.useEffect(() => {
|
|
172
|
-
if (metric >= threshold && !achievedLevels.includes(threshold)) {
|
|
173
|
-
onAchieve();
|
|
174
|
-
const levelConfig = levels.find(level => level.threshold === threshold);
|
|
175
|
-
if (levelConfig) {
|
|
176
|
-
setMetric(metric);
|
|
177
|
-
handleAchieve(levelConfig.level, message);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}, [metric, threshold, onAchieve, achievedLevels, levels, message, setMetric, handleAchieve]);
|
|
181
|
-
return React.createElement(React.Fragment, null, children);
|
|
182
|
-
};
|
|
183
|
-
var Achievement$1 = React.memo(Achievement);
|
|
184
|
-
|
|
185
|
-
exports.Achievement = Achievement$1;
|
|
186
268
|
exports.AchievementProvider = AchievementProvider;
|
|
269
|
+
exports.ConfettiWrapper = ConfettiWrapper;
|
|
187
270
|
exports.useAchievement = useAchievement;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { AchievementProvider, useAchievement } from './context/AchievementContext';
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
export { AchievementProvider, useAchievement, Achievement, BadgeConfig, LevelConfig };
|
|
2
|
+
import { Metrics, AchievementConfig, AchievementData, AchievementCondition } from './types';
|
|
3
|
+
import ConfettiWrapper from './components/ConfettiWrapper';
|
|
4
|
+
export { AchievementProvider, useAchievement, Metrics, AchievementConfig, AchievementData, AchievementCondition, ConfettiWrapper };
|