react-achievements 4.3.0 → 4.4.0
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 +33 -0
- package/dist/headless.cjs.map +1 -1
- package/dist/headless.d.ts +25 -5
- package/dist/headless.esm.js.map +1 -1
- package/dist/index.cjs +181 -105
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +32 -12
- package/dist/index.esm.js +182 -106
- package/dist/index.esm.js.map +1 -1
- package/dist/web.cjs +181 -105
- package/dist/web.cjs.map +1 -1
- package/dist/web.d.ts +32 -12
- package/dist/web.esm.js +182 -106
- package/dist/web.esm.js.map +1 -1
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -127,6 +127,12 @@ Provider-level icons and UI options are shared across notifications, widgets, mo
|
|
|
127
127
|
ui={{
|
|
128
128
|
theme: 'minimal',
|
|
129
129
|
notificationDuration: 8000,
|
|
130
|
+
enableConfetti: true,
|
|
131
|
+
confetti: {
|
|
132
|
+
colors: ['#22d3ee', '#f97316', '#facc15'],
|
|
133
|
+
particleCount: 120,
|
|
134
|
+
spread: 80,
|
|
135
|
+
},
|
|
130
136
|
NotificationComponent: MyNotification,
|
|
131
137
|
ModalComponent: MyAchievementsModal,
|
|
132
138
|
ConfettiComponent: MyConfetti,
|
|
@@ -136,6 +142,33 @@ Provider-level icons and UI options are shared across notifications, widgets, mo
|
|
|
136
142
|
</AchievementProvider>
|
|
137
143
|
```
|
|
138
144
|
|
|
145
|
+
Set `ui.enableConfetti` to `false` to disable the built-in celebration. Omit `ConfettiComponent` when you only want to tune the default `canvas-confetti` animation through `ui.confetti`.
|
|
146
|
+
|
|
147
|
+
Rewards can optionally override the global confetti settings. Omit `confetti` to use the provider defaults, or set `confetti: false` for quieter rewards:
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
const achievements = {
|
|
151
|
+
score: {
|
|
152
|
+
100: {
|
|
153
|
+
title: 'Century!',
|
|
154
|
+
description: 'Score 100 points',
|
|
155
|
+
icon: '🏆',
|
|
156
|
+
},
|
|
157
|
+
1000: {
|
|
158
|
+
title: 'Boss Finale!',
|
|
159
|
+
description: 'Score 1,000 points',
|
|
160
|
+
icon: '👑',
|
|
161
|
+
confetti: {
|
|
162
|
+
particleCount: 240,
|
|
163
|
+
spread: 100,
|
|
164
|
+
startVelocity: 60,
|
|
165
|
+
scalar: 1.4,
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
```
|
|
171
|
+
|
|
139
172
|
## Hooks
|
|
140
173
|
|
|
141
174
|
```tsx
|
package/dist/headless.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headless.cjs","sources":["../src/core/types.ts","../src/core/utils/deprecation.ts","../src/providers/AchievementProvider.tsx","../src/hooks/useAchievements.ts","../src/hooks/useAchievementState.ts","../src/hooks/useSimpleAchievements.ts","../src/hooks/useAchievementEngine.ts"],"sourcesContent":[null,null,null,null,null,null,null],"names":["createContext","useState","AchievementEngine","useCallback","useEffect","useContext"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"headless.cjs","sources":["../src/core/types.ts","../src/core/utils/deprecation.ts","../src/providers/AchievementProvider.tsx","../src/hooks/useAchievements.ts","../src/hooks/useAchievementState.ts","../src/hooks/useSimpleAchievements.ts","../src/hooks/useAchievementEngine.ts"],"sourcesContent":[null,null,null,null,null,null,null],"names":["createContext","useState","AchievementEngine","useCallback","useEffect","useContext"],"mappings":"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"}
|
package/dist/headless.d.ts
CHANGED
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import * as achievements_engine from 'achievements-engine';
|
|
3
|
-
import {
|
|
3
|
+
import { AchievementSnapshot, ImportOptions, ImportResult, AchievementEngine, AchievementStorage as AchievementStorage$1, AsyncAchievementStorage as AsyncAchievementStorage$1, StorageType, RestApiStorageConfig, EventMapping, AchievementError } from 'achievements-engine';
|
|
4
4
|
export { AchievementBuilder, AchievementEngine, AchievementEngineApi, AchievementError, AchievementSnapshot, AchievementUnlockedEvent, AchievementUpdateResult, AsyncStorageAdapter, AwardDetails, ConfigurationError, EngineConfig, EngineEvent, ErrorEvent, EventMapping, ExportedData, ImportOptions, ImportResult, ImportValidationError, IndexedDBStorage, LocalStorage, MemoryStorage, MetricUpdatedEvent, MetricUpdater, OfflineQueueStorage, RestApiStorage, RestApiStorageConfig, StateChangedEvent, StorageError, StorageQuotaError, StorageType, SyncError, UnsubscribeFn, createConfigHash, exportAchievementData, importAchievementData, isAchievementError, isRecoverableError, isSimpleConfig, normalizeAchievements } from 'achievements-engine';
|
|
5
5
|
|
|
6
|
+
type ConfettiShape = 'square' | 'circle' | 'star';
|
|
7
|
+
interface ConfettiOptions {
|
|
8
|
+
/**
|
|
9
|
+
* Duration in milliseconds before the built-in confetti marker is removed.
|
|
10
|
+
* Custom confetti components receive this value through `duration`.
|
|
11
|
+
*/
|
|
12
|
+
duration?: number;
|
|
13
|
+
particleCount?: number;
|
|
14
|
+
colors?: string[];
|
|
15
|
+
shapes?: ConfettiShape[];
|
|
16
|
+
spread?: number;
|
|
17
|
+
startVelocity?: number;
|
|
18
|
+
gravity?: number;
|
|
19
|
+
scalar?: number;
|
|
20
|
+
zIndex?: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
6
23
|
type AchievementMetricValue = number | string | boolean | Date | null | undefined;
|
|
7
24
|
type AchievementMetricArrayValue = AchievementMetricValue | AchievementMetricValue[];
|
|
8
25
|
interface AchievementMetrics {
|
|
@@ -13,10 +30,12 @@ interface AchievementDetails {
|
|
|
13
30
|
achievementTitle: string;
|
|
14
31
|
achievementDescription: string;
|
|
15
32
|
achievementIconKey?: string;
|
|
33
|
+
confetti?: AchievementConfetti;
|
|
16
34
|
}
|
|
17
35
|
interface AchievementWithStatus extends AchievementDetails {
|
|
18
36
|
isUnlocked: boolean;
|
|
19
37
|
}
|
|
38
|
+
type AchievementConfetti = false | ConfettiOptions;
|
|
20
39
|
interface AchievementCondition {
|
|
21
40
|
isConditionMet: (value: AchievementMetricArrayValue, state: AchievementState) => boolean;
|
|
22
41
|
achievementDetails: AchievementDetails | AchievementWithStatus;
|
|
@@ -28,6 +47,7 @@ interface SimpleAchievementDetails {
|
|
|
28
47
|
title: string;
|
|
29
48
|
description?: string;
|
|
30
49
|
icon?: string;
|
|
50
|
+
confetti?: AchievementConfetti;
|
|
31
51
|
}
|
|
32
52
|
interface CustomAchievementDetails extends SimpleAchievementDetails {
|
|
33
53
|
condition: (metrics: Record<string, any>) => boolean;
|
|
@@ -86,7 +106,7 @@ interface AchievementContextType {
|
|
|
86
106
|
update: (metrics: Record<string, any>) => void;
|
|
87
107
|
achievements: {
|
|
88
108
|
unlocked: string[];
|
|
89
|
-
all: Record<string, AchievementWithStatus
|
|
109
|
+
all: Record<string, AchievementWithStatus>;
|
|
90
110
|
};
|
|
91
111
|
snapshot: AchievementSnapshot;
|
|
92
112
|
reset: () => void;
|
|
@@ -96,7 +116,7 @@ interface AchievementContextType {
|
|
|
96
116
|
};
|
|
97
117
|
exportData: () => string;
|
|
98
118
|
importData: (jsonString: string, options?: ImportOptions) => ImportResult;
|
|
99
|
-
getAllAchievements: () => AchievementWithStatus
|
|
119
|
+
getAllAchievements: () => AchievementWithStatus[];
|
|
100
120
|
engine: AchievementEngine;
|
|
101
121
|
icons: Record<string, string>;
|
|
102
122
|
/**
|
|
@@ -107,7 +127,7 @@ interface AchievementContextType {
|
|
|
107
127
|
}
|
|
108
128
|
declare const AchievementContext: React.Context<AchievementContextType | undefined>;
|
|
109
129
|
interface AchievementProviderProps {
|
|
110
|
-
achievements?: AchievementConfigurationType
|
|
130
|
+
achievements?: AchievementConfigurationType;
|
|
111
131
|
storage?: AchievementStorage$1 | AsyncAchievementStorage$1 | StorageType;
|
|
112
132
|
restApiConfig?: RestApiStorageConfig;
|
|
113
133
|
eventMapping?: EventMapping;
|
|
@@ -174,4 +194,4 @@ declare const useAchievementState: () => {
|
|
|
174
194
|
*/
|
|
175
195
|
declare const useAchievementEngine: () => AchievementEngine;
|
|
176
196
|
|
|
177
|
-
export { AchievementCondition, AchievementConfiguration, AchievementConfigurationType, AchievementContext, AchievementContextType, AchievementContextValue, AchievementDetails, AchievementMetricArrayValue, AchievementMetricValue, AchievementMetrics, AchievementProvider, AchievementProviderProps, AchievementState, AchievementStorage, AchievementWithStatus, AnyAchievementStorage, AsyncAchievementStorage, CustomAchievementDetails, InitialAchievementMetrics, SimpleAchievementConfig, SimpleAchievementDetails, isAsyncStorage, useAchievementEngine, useAchievementState, useAchievements, useSimpleAchievements };
|
|
197
|
+
export { AchievementCondition, AchievementConfetti, AchievementConfiguration, AchievementConfigurationType, AchievementContext, AchievementContextType, AchievementContextValue, AchievementDetails, AchievementMetricArrayValue, AchievementMetricValue, AchievementMetrics, AchievementProvider, AchievementProviderProps, AchievementState, AchievementStorage, AchievementWithStatus, AnyAchievementStorage, AsyncAchievementStorage, CustomAchievementDetails, InitialAchievementMetrics, SimpleAchievementConfig, SimpleAchievementDetails, isAsyncStorage, useAchievementEngine, useAchievementState, useAchievements, useSimpleAchievements };
|
package/dist/headless.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headless.esm.js","sources":["../src/core/types.ts","../src/core/utils/deprecation.ts","../src/providers/AchievementProvider.tsx","../src/hooks/useAchievements.ts","../src/hooks/useAchievementState.ts","../src/hooks/useSimpleAchievements.ts","../src/hooks/useAchievementEngine.ts"],"sourcesContent":[null,null,null,null,null,null,null],"names":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"headless.esm.js","sources":["../src/core/types.ts","../src/core/utils/deprecation.ts","../src/providers/AchievementProvider.tsx","../src/hooks/useAchievements.ts","../src/hooks/useAchievementState.ts","../src/hooks/useSimpleAchievements.ts","../src/hooks/useAchievementEngine.ts"],"sourcesContent":[null,null,null,null,null,null,null],"names":[],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var achievementsEngine = require('achievements-engine');
|
|
4
4
|
var React = require('react');
|
|
5
|
+
var confetti = require('canvas-confetti');
|
|
5
6
|
|
|
6
7
|
// Type guard to detect async storage
|
|
7
8
|
function isAsyncStorage(storage) {
|
|
@@ -214,7 +215,7 @@ const builtInThemes = {
|
|
|
214
215
|
},
|
|
215
216
|
confetti: {
|
|
216
217
|
colors: ['#FFD700', '#4CAF50', '#2196F3', '#FF6B6B'],
|
|
217
|
-
particleCount:
|
|
218
|
+
particleCount: 80,
|
|
218
219
|
shapes: ['circle', 'square'],
|
|
219
220
|
},
|
|
220
221
|
},
|
|
@@ -246,7 +247,7 @@ const builtInThemes = {
|
|
|
246
247
|
},
|
|
247
248
|
confetti: {
|
|
248
249
|
colors: ['#4CAF50', '#2196F3'],
|
|
249
|
-
particleCount:
|
|
250
|
+
particleCount: 40,
|
|
250
251
|
shapes: ['circle'],
|
|
251
252
|
},
|
|
252
253
|
},
|
|
@@ -281,7 +282,7 @@ const builtInThemes = {
|
|
|
281
282
|
},
|
|
282
283
|
confetti: {
|
|
283
284
|
colors: ['#22d3ee', '#f97316', '#a855f7', '#eab308'], // Cyan, orange, purple, yellow
|
|
284
|
-
particleCount:
|
|
285
|
+
particleCount: 120,
|
|
285
286
|
shapes: ['circle', 'square'],
|
|
286
287
|
},
|
|
287
288
|
},
|
|
@@ -437,129 +438,159 @@ const BuiltInNotification = ({ achievement, onClose, duration = 5000, position =
|
|
|
437
438
|
React.createElement("button", { onClick: closeAfterExit, style: closeButtonStyles, onMouseEnter: (e) => (e.currentTarget.style.opacity = '1'), onMouseLeave: (e) => (e.currentTarget.style.opacity = '0.6'), "aria-label": "Close notification" }, "\u00D7")));
|
|
438
439
|
};
|
|
439
440
|
|
|
441
|
+
const DEFAULT_COLORS = ['#FFD700', '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'];
|
|
442
|
+
const DEFAULT_DURATION_MS = 5000;
|
|
443
|
+
const DEFAULT_PARTICLE_COUNT = 80;
|
|
444
|
+
const DEFAULT_SHAPES = ['square', 'circle'];
|
|
445
|
+
const DEFAULT_SPREAD = 70;
|
|
446
|
+
const DEFAULT_START_VELOCITY = 45;
|
|
447
|
+
const DEFAULT_GRAVITY = 1;
|
|
448
|
+
const DEFAULT_SCALAR = 1;
|
|
449
|
+
const DEFAULT_Z_INDEX = 10001;
|
|
450
|
+
const getSafeParticleCount = (count) => Math.max(0, Math.floor(count));
|
|
440
451
|
/**
|
|
441
|
-
*
|
|
442
|
-
*
|
|
443
|
-
*
|
|
444
|
-
* @returns Object with width and height properties
|
|
445
|
-
*
|
|
446
|
-
* @example
|
|
447
|
-
* ```tsx
|
|
448
|
-
* const { width, height } = useWindowSize();
|
|
449
|
-
* console.log(`Window size: ${width}x${height}`);
|
|
450
|
-
* ```
|
|
452
|
+
* Built-in confetti component
|
|
453
|
+
* Canvas-based confetti animation powered by canvas-confetti.
|
|
451
454
|
*/
|
|
452
|
-
|
|
453
|
-
const [
|
|
454
|
-
width: typeof window !== 'undefined' ? window.innerWidth : 0,
|
|
455
|
-
height: typeof window !== 'undefined' ? window.innerHeight : 0,
|
|
456
|
-
});
|
|
455
|
+
const BuiltInConfetti = ({ show, duration = DEFAULT_DURATION_MS, particleCount = DEFAULT_PARTICLE_COUNT, colors = DEFAULT_COLORS, shapes = DEFAULT_SHAPES, spread = DEFAULT_SPREAD, startVelocity = DEFAULT_START_VELOCITY, gravity = DEFAULT_GRAVITY, scalar = DEFAULT_SCALAR, zIndex = DEFAULT_Z_INDEX, }) => {
|
|
456
|
+
const [isVisible, setIsVisible] = React.useState(false);
|
|
457
457
|
React.useEffect(() => {
|
|
458
|
-
|
|
459
|
-
|
|
458
|
+
if (!show) {
|
|
459
|
+
setIsVisible(false);
|
|
460
|
+
confetti.reset();
|
|
460
461
|
return;
|
|
461
462
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
463
|
+
setIsVisible(true);
|
|
464
|
+
const totalParticles = getSafeParticleCount(particleCount);
|
|
465
|
+
const resolvedColors = colors.length > 0 ? colors : DEFAULT_COLORS;
|
|
466
|
+
const resolvedShapes = shapes.length > 0 ? shapes : DEFAULT_SHAPES;
|
|
467
|
+
const baseOptions = {
|
|
468
|
+
colors: resolvedColors,
|
|
469
|
+
shapes: resolvedShapes,
|
|
470
|
+
spread,
|
|
471
|
+
startVelocity,
|
|
472
|
+
gravity,
|
|
473
|
+
scalar,
|
|
474
|
+
zIndex,
|
|
475
|
+
disableForReducedMotion: true,
|
|
467
476
|
};
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
};
|
|
476
|
-
}, []);
|
|
477
|
-
return size;
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
/**
|
|
481
|
-
* Built-in confetti component
|
|
482
|
-
* Lightweight CSS-based confetti animation
|
|
483
|
-
*/
|
|
484
|
-
const BuiltInConfetti = ({ show, duration = 5000, particleCount = 50, colors = ['#FFD700', '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'], }) => {
|
|
485
|
-
const [isVisible, setIsVisible] = React.useState(false);
|
|
486
|
-
const { width, height } = useWindowSize();
|
|
487
|
-
React.useEffect(() => {
|
|
488
|
-
if (show) {
|
|
489
|
-
setIsVisible(true);
|
|
490
|
-
const timer = setTimeout(() => setIsVisible(false), duration);
|
|
491
|
-
return () => clearTimeout(timer);
|
|
477
|
+
if (totalParticles > 0) {
|
|
478
|
+
const centerParticles = Math.ceil(totalParticles * 0.5);
|
|
479
|
+
const leftParticles = Math.floor((totalParticles - centerParticles) / 2);
|
|
480
|
+
const rightParticles = totalParticles - centerParticles - leftParticles;
|
|
481
|
+
confetti(Object.assign(Object.assign({}, baseOptions), { particleCount: centerParticles, origin: { x: 0.5, y: 0.58 } }));
|
|
482
|
+
confetti(Object.assign(Object.assign({}, baseOptions), { particleCount: leftParticles, angle: 60, spread: Math.max(45, spread * 0.8), origin: { x: 0, y: 0.72 } }));
|
|
483
|
+
confetti(Object.assign(Object.assign({}, baseOptions), { particleCount: rightParticles, angle: 120, spread: Math.max(45, spread * 0.8), origin: { x: 1, y: 0.72 } }));
|
|
492
484
|
}
|
|
493
|
-
|
|
485
|
+
const timer = setTimeout(() => {
|
|
494
486
|
setIsVisible(false);
|
|
495
|
-
|
|
496
|
-
|
|
487
|
+
confetti.reset();
|
|
488
|
+
}, duration);
|
|
489
|
+
return () => {
|
|
490
|
+
clearTimeout(timer);
|
|
491
|
+
confetti.reset();
|
|
492
|
+
};
|
|
493
|
+
}, [
|
|
494
|
+
show,
|
|
495
|
+
duration,
|
|
496
|
+
particleCount,
|
|
497
|
+
colors,
|
|
498
|
+
shapes,
|
|
499
|
+
spread,
|
|
500
|
+
startVelocity,
|
|
501
|
+
gravity,
|
|
502
|
+
scalar,
|
|
503
|
+
zIndex,
|
|
504
|
+
]);
|
|
497
505
|
if (!isVisible)
|
|
498
506
|
return null;
|
|
499
|
-
|
|
500
|
-
position: 'fixed',
|
|
501
|
-
top: 0,
|
|
502
|
-
left: 0,
|
|
503
|
-
width: '100%',
|
|
504
|
-
height: '100%',
|
|
505
|
-
pointerEvents: 'none',
|
|
506
|
-
zIndex: 10001,
|
|
507
|
-
overflow: 'hidden',
|
|
508
|
-
};
|
|
509
|
-
// Generate particles
|
|
510
|
-
const particles = Array.from({ length: particleCount }, (_, i) => {
|
|
511
|
-
const color = colors[Math.floor(Math.random() * colors.length)];
|
|
512
|
-
const startX = Math.random() * width;
|
|
513
|
-
const rotation = Math.random() * 360;
|
|
514
|
-
const fallDuration = 3 + Math.random() * 2; // 3-5 seconds
|
|
515
|
-
const delay = Math.random() * 0.5; // 0-0.5s delay
|
|
516
|
-
const shape = Math.random() > 0.5 ? 'circle' : 'square';
|
|
517
|
-
const particleStyles = {
|
|
518
|
-
position: 'absolute',
|
|
519
|
-
top: '-20px',
|
|
520
|
-
left: `${startX}px`,
|
|
521
|
-
width: '10px',
|
|
522
|
-
height: '10px',
|
|
523
|
-
backgroundColor: color,
|
|
524
|
-
borderRadius: shape === 'circle' ? '50%' : '0',
|
|
525
|
-
transform: `rotate(${rotation}deg)`,
|
|
526
|
-
animation: `confettiFall ${fallDuration}s linear ${delay}s forwards`,
|
|
527
|
-
opacity: 0.9,
|
|
528
|
-
};
|
|
529
|
-
return React.createElement("div", { key: i, style: particleStyles, "data-testid": "confetti-particle" });
|
|
530
|
-
});
|
|
531
|
-
return (React.createElement(React.Fragment, null,
|
|
532
|
-
React.createElement("style", null, `
|
|
533
|
-
@keyframes confettiFall {
|
|
534
|
-
0% {
|
|
535
|
-
transform: translateY(0) rotate(0deg);
|
|
536
|
-
opacity: 1;
|
|
537
|
-
}
|
|
538
|
-
100% {
|
|
539
|
-
transform: translateY(${height + 50}px) rotate(720deg);
|
|
540
|
-
opacity: 0;
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
`),
|
|
544
|
-
React.createElement("div", { style: containerStyles, "data-testid": "built-in-confetti" }, particles)));
|
|
507
|
+
return React.createElement("div", { "data-testid": "built-in-confetti", style: { display: 'none' } });
|
|
545
508
|
};
|
|
546
509
|
|
|
547
510
|
const DEFAULT_NOTIFICATION_DURATION_MS = 5000;
|
|
548
511
|
const CONFETTI_DURATION_MS = 5000;
|
|
512
|
+
const hasConfiguredConfetti = (confetti) => {
|
|
513
|
+
return confetti === false || (typeof confetti === 'object' && confetti !== null);
|
|
514
|
+
};
|
|
515
|
+
const collectComplexConfetti = (achievements, confettiByAchievementId) => {
|
|
516
|
+
Object.values(achievements).forEach((metricAchievements) => {
|
|
517
|
+
metricAchievements.forEach(({ achievementDetails }) => {
|
|
518
|
+
const confetti = achievementDetails.confetti;
|
|
519
|
+
if (hasConfiguredConfetti(confetti)) {
|
|
520
|
+
confettiByAchievementId.set(achievementDetails.achievementId, confetti);
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
};
|
|
525
|
+
const simpleConfigHasRewardConfetti = (achievements) => {
|
|
526
|
+
return Object.values(achievements).some((metricAchievements) => Object.values(metricAchievements).some((achievement) => hasConfiguredConfetti(achievement.confetti)));
|
|
527
|
+
};
|
|
528
|
+
const prepareAchievementsForConfetti = (achievements) => {
|
|
529
|
+
const confettiByAchievementId = new Map();
|
|
530
|
+
if (!achievements) {
|
|
531
|
+
return { achievements, confettiByAchievementId };
|
|
532
|
+
}
|
|
533
|
+
if (!achievementsEngine.isSimpleConfig(achievements)) {
|
|
534
|
+
collectComplexConfetti(achievements, confettiByAchievementId);
|
|
535
|
+
return { achievements, confettiByAchievementId };
|
|
536
|
+
}
|
|
537
|
+
const simpleAchievements = achievements;
|
|
538
|
+
if (!simpleConfigHasRewardConfetti(simpleAchievements)) {
|
|
539
|
+
return { achievements, confettiByAchievementId };
|
|
540
|
+
}
|
|
541
|
+
const normalizedAchievements = achievementsEngine.normalizeAchievements(simpleAchievements);
|
|
542
|
+
Object.entries(simpleAchievements).forEach(([metric, metricAchievements]) => {
|
|
543
|
+
const normalizedMetricAchievements = normalizedAchievements[metric] || [];
|
|
544
|
+
Object.values(metricAchievements).forEach((achievement, index) => {
|
|
545
|
+
const confetti = achievement.confetti;
|
|
546
|
+
const normalizedAchievement = normalizedMetricAchievements[index];
|
|
547
|
+
if (normalizedAchievement && hasConfiguredConfetti(confetti)) {
|
|
548
|
+
normalizedAchievement.achievementDetails.confetti = confetti;
|
|
549
|
+
confettiByAchievementId.set(normalizedAchievement.achievementDetails.achievementId, confetti);
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
return { achievements: normalizedAchievements, confettiByAchievementId };
|
|
554
|
+
};
|
|
549
555
|
const AchievementUIContext = React.createContext({
|
|
550
556
|
icons: {},
|
|
551
557
|
ui: {},
|
|
552
558
|
});
|
|
553
|
-
const AchievementEffects = ({ icons, ui }) => {
|
|
554
|
-
var _a;
|
|
559
|
+
const AchievementEffects = ({ icons, ui, achievementConfetti }) => {
|
|
560
|
+
var _a, _b;
|
|
555
561
|
const engine = useAchievementEngine();
|
|
556
562
|
const seenAchievementsRef = React.useRef(new Set(engine.getUnlocked()));
|
|
557
563
|
const confettiTimerRef = React.useRef(null);
|
|
564
|
+
const achievementConfettiRef = React.useRef(achievementConfetti);
|
|
558
565
|
const [showConfetti, setShowConfetti] = React.useState(false);
|
|
566
|
+
const [activeConfettiConfig, setActiveConfettiConfig] = React.useState(null);
|
|
559
567
|
const [notifications, setNotifications] = React.useState([]);
|
|
560
568
|
const notificationDuration = (_a = ui.notificationDuration) !== null && _a !== void 0 ? _a : DEFAULT_NOTIFICATION_DURATION_MS;
|
|
569
|
+
const themeName = ui.theme || 'modern';
|
|
570
|
+
const themeConfig = React.useMemo(() => getTheme(themeName) || builtInThemes.modern, [themeName]);
|
|
571
|
+
const globalConfettiConfig = React.useMemo(() => (Object.assign(Object.assign({}, themeConfig.confetti), ui.confetti)), [themeConfig, ui.confetti]);
|
|
572
|
+
const globalConfettiConfigRef = React.useRef(globalConfettiConfig);
|
|
573
|
+
const renderedConfettiConfig = showConfetti && activeConfettiConfig ? activeConfettiConfig : globalConfettiConfig;
|
|
574
|
+
const renderedConfettiDuration = (_b = renderedConfettiConfig.duration) !== null && _b !== void 0 ? _b : CONFETTI_DURATION_MS;
|
|
575
|
+
React.useEffect(() => {
|
|
576
|
+
achievementConfettiRef.current = achievementConfetti;
|
|
577
|
+
}, [achievementConfetti]);
|
|
578
|
+
React.useEffect(() => {
|
|
579
|
+
globalConfettiConfigRef.current = globalConfettiConfig;
|
|
580
|
+
}, [globalConfettiConfig]);
|
|
581
|
+
React.useEffect(() => {
|
|
582
|
+
if (ui.enableConfetti === false) {
|
|
583
|
+
if (confettiTimerRef.current) {
|
|
584
|
+
clearTimeout(confettiTimerRef.current);
|
|
585
|
+
confettiTimerRef.current = null;
|
|
586
|
+
}
|
|
587
|
+
setShowConfetti(false);
|
|
588
|
+
setActiveConfettiConfig(null);
|
|
589
|
+
}
|
|
590
|
+
}, [ui.enableConfetti]);
|
|
561
591
|
React.useEffect(() => {
|
|
562
592
|
const unsubscribeUnlocked = engine.on('achievement:unlocked', (event) => {
|
|
593
|
+
var _a;
|
|
563
594
|
if (seenAchievementsRef.current.has(event.achievementId)) {
|
|
564
595
|
return;
|
|
565
596
|
}
|
|
@@ -579,15 +610,19 @@ const AchievementEffects = ({ icons, ui }) => {
|
|
|
579
610
|
return [...currentNotifications, unlockedAchievement];
|
|
580
611
|
});
|
|
581
612
|
}
|
|
582
|
-
|
|
613
|
+
const rewardConfetti = achievementConfettiRef.current.get(event.achievementId);
|
|
614
|
+
if (ui.enableConfetti !== false && rewardConfetti !== false) {
|
|
583
615
|
if (confettiTimerRef.current) {
|
|
584
616
|
clearTimeout(confettiTimerRef.current);
|
|
585
617
|
}
|
|
618
|
+
const resolvedConfettiConfig = Object.assign(Object.assign({}, globalConfettiConfigRef.current), (rewardConfetti || {}));
|
|
619
|
+
const resolvedConfettiDuration = (_a = resolvedConfettiConfig.duration) !== null && _a !== void 0 ? _a : CONFETTI_DURATION_MS;
|
|
620
|
+
setActiveConfettiConfig(resolvedConfettiConfig);
|
|
586
621
|
setShowConfetti(true);
|
|
587
622
|
confettiTimerRef.current = setTimeout(() => {
|
|
588
623
|
setShowConfetti(false);
|
|
589
624
|
confettiTimerRef.current = null;
|
|
590
|
-
},
|
|
625
|
+
}, resolvedConfettiDuration);
|
|
591
626
|
}
|
|
592
627
|
});
|
|
593
628
|
const unsubscribeStateChanged = engine.on('state:changed', () => {
|
|
@@ -611,18 +646,19 @@ const AchievementEffects = ({ icons, ui }) => {
|
|
|
611
646
|
return (React.createElement(React.Fragment, null,
|
|
612
647
|
ui.enableNotifications !== false &&
|
|
613
648
|
notifications.map((notification, index) => (React.createElement(NotificationComponent, { key: notification.achievementId, achievement: notification, onClose: () => setNotifications((currentNotifications) => currentNotifications.filter((currentNotification) => currentNotification.achievementId !== notification.achievementId)), duration: notificationDuration, position: ui.notificationPosition || 'top-center', theme: ui.theme || 'modern', icons: icons, stackIndex: index }))),
|
|
614
|
-
ui.enableConfetti !== false && (React.createElement(ConfettiComponentResolved, { show: showConfetti, duration:
|
|
649
|
+
ui.enableConfetti !== false && (React.createElement(ConfettiComponentResolved, Object.assign({ show: showConfetti }, renderedConfettiConfig, { duration: renderedConfettiDuration })))));
|
|
615
650
|
};
|
|
616
651
|
const AchievementProvider = (_a) => {
|
|
617
652
|
var { children, icons = {}, ui = {}, useBuiltInUI } = _a, providerProps = __rest(_a, ["children", "icons", "ui", "useBuiltInUI"]);
|
|
618
653
|
if (useBuiltInUI !== undefined) {
|
|
619
654
|
warnDeprecation('`useBuiltInUI` is deprecated and is now a no-op because built-in UI is the default. It will be removed in 5.0.');
|
|
620
655
|
}
|
|
656
|
+
const [{ achievements: preparedAchievements, confettiByAchievementId }] = React.useState(() => prepareAchievementsForConfetti(providerProps.achievements));
|
|
621
657
|
const uiContextValue = React.useMemo(() => ({ icons, ui }), [icons, ui]);
|
|
622
658
|
return (React.createElement(AchievementUIContext.Provider, { value: uiContextValue },
|
|
623
|
-
React.createElement(AchievementProvider$1, Object.assign({}, providerProps, { icons: icons }),
|
|
659
|
+
React.createElement(AchievementProvider$1, Object.assign({}, providerProps, { achievements: preparedAchievements, icons: icons }),
|
|
624
660
|
children,
|
|
625
|
-
React.createElement(AchievementEffects, { icons: icons, ui: ui }))));
|
|
661
|
+
React.createElement(AchievementEffects, { achievementConfetti: confettiByAchievementId, icons: icons, ui: ui }))));
|
|
626
662
|
};
|
|
627
663
|
|
|
628
664
|
const useAchievements = () => {
|
|
@@ -1398,6 +1434,46 @@ const BuiltInModal = ({ isOpen, onClose, achievements, icons = {}, theme = 'mode
|
|
|
1398
1434
|
})))))));
|
|
1399
1435
|
};
|
|
1400
1436
|
|
|
1437
|
+
/**
|
|
1438
|
+
* Hook to track window dimensions
|
|
1439
|
+
* Replacement for react-use's useWindowSize
|
|
1440
|
+
*
|
|
1441
|
+
* @returns Object with width and height properties
|
|
1442
|
+
*
|
|
1443
|
+
* @example
|
|
1444
|
+
* ```tsx
|
|
1445
|
+
* const { width, height } = useWindowSize();
|
|
1446
|
+
* console.log(`Window size: ${width}x${height}`);
|
|
1447
|
+
* ```
|
|
1448
|
+
*/
|
|
1449
|
+
function useWindowSize() {
|
|
1450
|
+
const [size, setSize] = React.useState({
|
|
1451
|
+
width: typeof window !== 'undefined' ? window.innerWidth : 0,
|
|
1452
|
+
height: typeof window !== 'undefined' ? window.innerHeight : 0,
|
|
1453
|
+
});
|
|
1454
|
+
React.useEffect(() => {
|
|
1455
|
+
// Handle SSR - window may not be defined
|
|
1456
|
+
if (typeof window === 'undefined') {
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1459
|
+
const handleResize = () => {
|
|
1460
|
+
setSize({
|
|
1461
|
+
width: window.innerWidth,
|
|
1462
|
+
height: window.innerHeight,
|
|
1463
|
+
});
|
|
1464
|
+
};
|
|
1465
|
+
// Set initial size
|
|
1466
|
+
handleResize();
|
|
1467
|
+
// Add event listener
|
|
1468
|
+
window.addEventListener('resize', handleResize);
|
|
1469
|
+
// Cleanup
|
|
1470
|
+
return () => {
|
|
1471
|
+
window.removeEventListener('resize', handleResize);
|
|
1472
|
+
};
|
|
1473
|
+
}, []);
|
|
1474
|
+
return size;
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1401
1477
|
Object.defineProperty(exports, 'AchievementBuilder', {
|
|
1402
1478
|
enumerable: true,
|
|
1403
1479
|
get: function () { return achievementsEngine.AchievementBuilder; }
|