react-achievements 1.0.1 → 1.0.2

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.
@@ -3,6 +3,7 @@ interface AchievementProps {
3
3
  metric: number;
4
4
  threshold: number;
5
5
  onAchieve: () => void;
6
+ message: string;
6
7
  children: React.ReactNode;
7
8
  }
8
9
  declare const Achievement: React.FC<AchievementProps>;
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ interface AchievementModalProps {
3
+ show: boolean;
4
+ message: string;
5
+ onClose: () => void;
6
+ }
7
+ declare const AchievementModal: React.FC<AchievementModalProps>;
8
+ export default AchievementModal;
@@ -7,6 +7,7 @@ interface AchievementContextProps {
7
7
  badges: BadgeConfig[];
8
8
  levels: LevelConfig[];
9
9
  achievedLevels: number[];
10
+ handleAchieve: (level: number, message: string) => void;
10
11
  }
11
12
  declare const AchievementProvider: React.FC<{
12
13
  children: ReactNode;
package/dist/index.cjs.js CHANGED
@@ -115,6 +115,37 @@ const ConfettiWrapper = ({ show }) => {
115
115
  return show ? React.createElement(Confetti, { width: width, height: height }) : null;
116
116
  };
117
117
 
118
+ const AchievementModal = ({ show, message, onClose }) => {
119
+ if (!show)
120
+ return null;
121
+ const modalStyle = {
122
+ position: 'fixed',
123
+ top: '50%',
124
+ left: '50%',
125
+ transform: 'translate(-50%, -50%)',
126
+ backgroundColor: '#fff',
127
+ padding: '20px',
128
+ borderRadius: '8px',
129
+ boxShadow: '0 0 10px rgba(0,0,0,0.1)',
130
+ zIndex: 1000,
131
+ };
132
+ const overlayStyle = {
133
+ position: 'fixed',
134
+ top: 0,
135
+ left: 0,
136
+ right: 0,
137
+ bottom: 0,
138
+ backgroundColor: 'rgba(0,0,0,0.5)',
139
+ zIndex: 999,
140
+ };
141
+ return (React.createElement(React.Fragment, null,
142
+ React.createElement("div", { style: overlayStyle, onClick: onClose }),
143
+ React.createElement("div", { style: modalStyle },
144
+ React.createElement("h2", null, "Achievement Unlocked!"),
145
+ React.createElement("p", null, message),
146
+ React.createElement("button", { onClick: onClose }, "Okay"))));
147
+ };
148
+
118
149
  const Badge = ({ icon, title, description, position = 'top-right' }) => {
119
150
  const badgeStyle = {
120
151
  position: 'fixed',
@@ -140,13 +171,26 @@ const AchievementProvider = ({ children }) => {
140
171
  const [metric, setMetric] = React.useState(0);
141
172
  const [achievedLevels, setAchievedLevels] = React.useState([]);
142
173
  const [showConfetti, setShowConfetti] = React.useState(false);
143
- return (React.createElement(AchievementContext.Provider, { value: { metric, setMetric, badges: defaultBadges, levels, achievedLevels } },
174
+ const [modalMessage, setModalMessage] = React.useState('');
175
+ const handleAchieve = (level, message) => {
176
+ if (!achievedLevels.includes(level)) {
177
+ setAchievedLevels([...achievedLevels, level]);
178
+ setShowConfetti(true);
179
+ setModalMessage(message);
180
+ }
181
+ };
182
+ const handleCloseModal = () => {
183
+ setShowConfetti(false);
184
+ setModalMessage('');
185
+ };
186
+ return (React.createElement(AchievementContext.Provider, { value: { metric, setMetric, badges: defaultBadges, levels, achievedLevels, handleAchieve } },
144
187
  children,
145
188
  levels.map(levelConfig => {
146
189
  var _a, _b, _c;
147
190
  return achievedLevels.includes(levelConfig.level) ? (React.createElement(Badge, { key: levelConfig.level, icon: ((_a = defaultBadges.find(badge => badge.id === levelConfig.badgeId)) === null || _a === void 0 ? void 0 : _a.icon) || '', title: ((_b = defaultBadges.find(badge => badge.id === levelConfig.badgeId)) === null || _b === void 0 ? void 0 : _b.title) || '', description: ((_c = defaultBadges.find(badge => badge.id === levelConfig.badgeId)) === null || _c === void 0 ? void 0 : _c.description) || '' })) : null;
148
191
  }),
149
- React.createElement(ConfettiWrapper, { show: showConfetti })));
192
+ React.createElement(ConfettiWrapper, { show: showConfetti }),
193
+ React.createElement(AchievementModal, { show: !!modalMessage, message: modalMessage, onClose: handleCloseModal })));
150
194
  };
151
195
  const useAchievement = () => {
152
196
  const context = React.useContext(AchievementContext);
@@ -156,17 +200,18 @@ const useAchievement = () => {
156
200
  return context;
157
201
  };
158
202
 
159
- const Achievement = ({ metric, threshold, onAchieve, children }) => {
160
- const { setMetric, achievedLevels, levels } = useAchievement();
203
+ const Achievement = ({ metric, threshold, onAchieve, message, children }) => {
204
+ const { setMetric, achievedLevels, levels, handleAchieve } = useAchievement();
161
205
  React.useEffect(() => {
162
206
  if (metric >= threshold && !achievedLevels.includes(threshold)) {
163
207
  onAchieve();
164
208
  const levelConfig = levels.find(level => level.threshold === threshold);
165
209
  if (levelConfig) {
166
- setMetric(metric); // Update the metric in the context
210
+ setMetric(metric);
211
+ handleAchieve(levelConfig.level, message);
167
212
  }
168
213
  }
169
- }, [metric, threshold, onAchieve, setMetric, achievedLevels, levels]);
214
+ }, [metric, threshold, onAchieve, setMetric, achievedLevels, levels, message, handleAchieve]);
170
215
  return React.createElement("div", null, children);
171
216
  };
172
217
 
package/dist/index.esm.js CHANGED
@@ -113,6 +113,37 @@ const ConfettiWrapper = ({ show }) => {
113
113
  return show ? React.createElement(Confetti, { width: width, height: height }) : null;
114
114
  };
115
115
 
116
+ const AchievementModal = ({ show, message, onClose }) => {
117
+ if (!show)
118
+ return null;
119
+ const modalStyle = {
120
+ position: 'fixed',
121
+ top: '50%',
122
+ left: '50%',
123
+ transform: 'translate(-50%, -50%)',
124
+ backgroundColor: '#fff',
125
+ padding: '20px',
126
+ borderRadius: '8px',
127
+ boxShadow: '0 0 10px rgba(0,0,0,0.1)',
128
+ zIndex: 1000,
129
+ };
130
+ const overlayStyle = {
131
+ position: 'fixed',
132
+ top: 0,
133
+ left: 0,
134
+ right: 0,
135
+ bottom: 0,
136
+ backgroundColor: 'rgba(0,0,0,0.5)',
137
+ zIndex: 999,
138
+ };
139
+ return (React.createElement(React.Fragment, null,
140
+ React.createElement("div", { style: overlayStyle, onClick: onClose }),
141
+ React.createElement("div", { style: modalStyle },
142
+ React.createElement("h2", null, "Achievement Unlocked!"),
143
+ React.createElement("p", null, message),
144
+ React.createElement("button", { onClick: onClose }, "Okay"))));
145
+ };
146
+
116
147
  const Badge = ({ icon, title, description, position = 'top-right' }) => {
117
148
  const badgeStyle = {
118
149
  position: 'fixed',
@@ -138,13 +169,26 @@ const AchievementProvider = ({ children }) => {
138
169
  const [metric, setMetric] = useState(0);
139
170
  const [achievedLevels, setAchievedLevels] = useState([]);
140
171
  const [showConfetti, setShowConfetti] = useState(false);
141
- return (React.createElement(AchievementContext.Provider, { value: { metric, setMetric, badges: defaultBadges, levels, achievedLevels } },
172
+ const [modalMessage, setModalMessage] = useState('');
173
+ const handleAchieve = (level, message) => {
174
+ if (!achievedLevels.includes(level)) {
175
+ setAchievedLevels([...achievedLevels, level]);
176
+ setShowConfetti(true);
177
+ setModalMessage(message);
178
+ }
179
+ };
180
+ const handleCloseModal = () => {
181
+ setShowConfetti(false);
182
+ setModalMessage('');
183
+ };
184
+ return (React.createElement(AchievementContext.Provider, { value: { metric, setMetric, badges: defaultBadges, levels, achievedLevels, handleAchieve } },
142
185
  children,
143
186
  levels.map(levelConfig => {
144
187
  var _a, _b, _c;
145
188
  return achievedLevels.includes(levelConfig.level) ? (React.createElement(Badge, { key: levelConfig.level, icon: ((_a = defaultBadges.find(badge => badge.id === levelConfig.badgeId)) === null || _a === void 0 ? void 0 : _a.icon) || '', title: ((_b = defaultBadges.find(badge => badge.id === levelConfig.badgeId)) === null || _b === void 0 ? void 0 : _b.title) || '', description: ((_c = defaultBadges.find(badge => badge.id === levelConfig.badgeId)) === null || _c === void 0 ? void 0 : _c.description) || '' })) : null;
146
189
  }),
147
- React.createElement(ConfettiWrapper, { show: showConfetti })));
190
+ React.createElement(ConfettiWrapper, { show: showConfetti }),
191
+ React.createElement(AchievementModal, { show: !!modalMessage, message: modalMessage, onClose: handleCloseModal })));
148
192
  };
149
193
  const useAchievement = () => {
150
194
  const context = useContext(AchievementContext);
@@ -154,17 +198,18 @@ const useAchievement = () => {
154
198
  return context;
155
199
  };
156
200
 
157
- const Achievement = ({ metric, threshold, onAchieve, children }) => {
158
- const { setMetric, achievedLevels, levels } = useAchievement();
201
+ const Achievement = ({ metric, threshold, onAchieve, message, children }) => {
202
+ const { setMetric, achievedLevels, levels, handleAchieve } = useAchievement();
159
203
  React.useEffect(() => {
160
204
  if (metric >= threshold && !achievedLevels.includes(threshold)) {
161
205
  onAchieve();
162
206
  const levelConfig = levels.find(level => level.threshold === threshold);
163
207
  if (levelConfig) {
164
- setMetric(metric); // Update the metric in the context
208
+ setMetric(metric);
209
+ handleAchieve(levelConfig.level, message);
165
210
  }
166
211
  }
167
- }, [metric, threshold, onAchieve, setMetric, achievedLevels, levels]);
212
+ }, [metric, threshold, onAchieve, setMetric, achievedLevels, levels, message, handleAchieve]);
168
213
  return React.createElement("div", null, children);
169
214
  };
170
215
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-achievements",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "This package allows users to transpose a React achievements engine over their React apps",
5
5
  "keywords": [
6
6
  "react",
@@ -5,21 +5,23 @@ interface AchievementProps {
5
5
  metric: number;
6
6
  threshold: number;
7
7
  onAchieve: () => void;
8
+ message: string;
8
9
  children: React.ReactNode;
9
10
  }
10
11
 
11
- const Achievement: React.FC<AchievementProps> = ({ metric, threshold, onAchieve, children }) => {
12
- const { setMetric, achievedLevels, levels } = useAchievement();
12
+ const Achievement: React.FC<AchievementProps> = ({ metric, threshold, onAchieve, message, children }) => {
13
+ const { setMetric, achievedLevels, levels, handleAchieve } = useAchievement();
13
14
 
14
15
  React.useEffect(() => {
15
16
  if (metric >= threshold && !achievedLevels.includes(threshold)) {
16
17
  onAchieve();
17
18
  const levelConfig = levels.find(level => level.threshold === threshold);
18
19
  if (levelConfig) {
19
- setMetric(metric); // Update the metric in the context
20
+ setMetric(metric);
21
+ handleAchieve(levelConfig.level, message);
20
22
  }
21
23
  }
22
- }, [metric, threshold, onAchieve, setMetric, achievedLevels, levels]);
24
+ }, [metric, threshold, onAchieve, setMetric, achievedLevels, levels, message, handleAchieve]);
23
25
 
24
26
  return <div>{children}</div>;
25
27
  };
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+
3
+ interface AchievementModalProps {
4
+ show: boolean;
5
+ message: string;
6
+ onClose: () => void;
7
+ }
8
+
9
+ const AchievementModal: React.FC<AchievementModalProps> = ({ show, message, onClose }) => {
10
+ if (!show) return null;
11
+
12
+ const modalStyle: React.CSSProperties = {
13
+ position: 'fixed',
14
+ top: '50%',
15
+ left: '50%',
16
+ transform: 'translate(-50%, -50%)',
17
+ backgroundColor: '#fff',
18
+ padding: '20px',
19
+ borderRadius: '8px',
20
+ boxShadow: '0 0 10px rgba(0,0,0,0.1)',
21
+ zIndex: 1000,
22
+ };
23
+
24
+ const overlayStyle: React.CSSProperties = {
25
+ position: 'fixed',
26
+ top: 0,
27
+ left: 0,
28
+ right: 0,
29
+ bottom: 0,
30
+ backgroundColor: 'rgba(0,0,0,0.5)',
31
+ zIndex: 999,
32
+ };
33
+
34
+ return (
35
+ <>
36
+ <div style={overlayStyle} onClick={onClose} />
37
+ <div style={modalStyle}>
38
+ <h2>Achievement Unlocked!</h2>
39
+ <p>{message}</p>
40
+ <button onClick={onClose}>Okay</button>
41
+ </div>
42
+ </>
43
+ );
44
+ };
45
+
46
+ export default AchievementModal;
@@ -2,6 +2,7 @@ import React, { createContext, useContext, useState, ReactNode } from 'react';
2
2
  import { defaultBadges, BadgeConfig } from '../badges';
3
3
  import { levels, LevelConfig } from '../levels';
4
4
  import ConfettiWrapper from '../components/ConfettiWrapper';
5
+ import AchievementModal from '../components/AchievementModal';
5
6
  import Badge from '../components/Badge';
6
7
 
7
8
  interface AchievementContextProps {
@@ -10,6 +11,7 @@ interface AchievementContextProps {
10
11
  badges: BadgeConfig[];
11
12
  levels: LevelConfig[];
12
13
  achievedLevels: number[];
14
+ handleAchieve: (level: number, message: string) => void;
13
15
  }
14
16
 
15
17
  const AchievementContext = createContext<AchievementContextProps | undefined>(undefined);
@@ -18,17 +20,23 @@ const AchievementProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
18
20
  const [metric, setMetric] = useState(0);
19
21
  const [achievedLevels, setAchievedLevels] = useState<number[]>([]);
20
22
  const [showConfetti, setShowConfetti] = useState(false);
23
+ const [modalMessage, setModalMessage] = useState('');
21
24
 
22
- const handleAchieve = (level: number) => {
25
+ const handleAchieve = (level: number, message: string) => {
23
26
  if (!achievedLevels.includes(level)) {
24
27
  setAchievedLevels([...achievedLevels, level]);
25
28
  setShowConfetti(true);
26
- setTimeout(() => setShowConfetti(false), 5000); // Confetti for 5 seconds
29
+ setModalMessage(message);
27
30
  }
28
31
  };
29
32
 
33
+ const handleCloseModal = () => {
34
+ setShowConfetti(false);
35
+ setModalMessage('');
36
+ };
37
+
30
38
  return (
31
- <AchievementContext.Provider value={{ metric, setMetric, badges: defaultBadges, levels, achievedLevels }}>
39
+ <AchievementContext.Provider value={{ metric, setMetric, badges: defaultBadges, levels, achievedLevels, handleAchieve }}>
32
40
  {children}
33
41
  {levels.map(levelConfig =>
34
42
  achievedLevels.includes(levelConfig.level) ? (
@@ -41,6 +49,7 @@ const AchievementProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
41
49
  ) : null
42
50
  )}
43
51
  <ConfettiWrapper show={showConfetti} />
52
+ <AchievementModal show={!!modalMessage} message={modalMessage} onClose={handleCloseModal} />
44
53
  </AchievementContext.Provider>
45
54
  );
46
55
  };