react-achievements 4.3.0 → 4.4.1
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 +38 -7
- 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/dist/web.esm.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { AchievementEngine } from 'achievements-engine';
|
|
1
|
+
import { AchievementEngine, isSimpleConfig, normalizeAchievements } from 'achievements-engine';
|
|
2
2
|
export { AchievementBuilder, AchievementEngine, AchievementError, AsyncStorageAdapter, ConfigurationError, ImportValidationError, IndexedDBStorage, LocalStorage, MemoryStorage, OfflineQueueStorage, RestApiStorage, StorageError, StorageQuotaError, StorageType, SyncError, createConfigHash, exportAchievementData, importAchievementData, isAchievementError, isRecoverableError, isSimpleConfig, normalizeAchievements } from 'achievements-engine';
|
|
3
3
|
import React, { createContext, useState, useCallback, useEffect, useContext, useRef, useMemo } from 'react';
|
|
4
|
+
import confetti from 'canvas-confetti';
|
|
4
5
|
|
|
5
6
|
// Type guard to detect async storage
|
|
6
7
|
function isAsyncStorage(storage) {
|
|
@@ -213,7 +214,7 @@ const builtInThemes = {
|
|
|
213
214
|
},
|
|
214
215
|
confetti: {
|
|
215
216
|
colors: ['#FFD700', '#4CAF50', '#2196F3', '#FF6B6B'],
|
|
216
|
-
particleCount:
|
|
217
|
+
particleCount: 80,
|
|
217
218
|
shapes: ['circle', 'square'],
|
|
218
219
|
},
|
|
219
220
|
},
|
|
@@ -245,7 +246,7 @@ const builtInThemes = {
|
|
|
245
246
|
},
|
|
246
247
|
confetti: {
|
|
247
248
|
colors: ['#4CAF50', '#2196F3'],
|
|
248
|
-
particleCount:
|
|
249
|
+
particleCount: 40,
|
|
249
250
|
shapes: ['circle'],
|
|
250
251
|
},
|
|
251
252
|
},
|
|
@@ -280,7 +281,7 @@ const builtInThemes = {
|
|
|
280
281
|
},
|
|
281
282
|
confetti: {
|
|
282
283
|
colors: ['#22d3ee', '#f97316', '#a855f7', '#eab308'], // Cyan, orange, purple, yellow
|
|
283
|
-
particleCount:
|
|
284
|
+
particleCount: 120,
|
|
284
285
|
shapes: ['circle', 'square'],
|
|
285
286
|
},
|
|
286
287
|
},
|
|
@@ -436,129 +437,159 @@ const BuiltInNotification = ({ achievement, onClose, duration = 5000, position =
|
|
|
436
437
|
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")));
|
|
437
438
|
};
|
|
438
439
|
|
|
440
|
+
const DEFAULT_COLORS = ['#FFD700', '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'];
|
|
441
|
+
const DEFAULT_DURATION_MS = 5000;
|
|
442
|
+
const DEFAULT_PARTICLE_COUNT = 80;
|
|
443
|
+
const DEFAULT_SHAPES = ['square', 'circle'];
|
|
444
|
+
const DEFAULT_SPREAD = 70;
|
|
445
|
+
const DEFAULT_START_VELOCITY = 45;
|
|
446
|
+
const DEFAULT_GRAVITY = 1;
|
|
447
|
+
const DEFAULT_SCALAR = 1;
|
|
448
|
+
const DEFAULT_Z_INDEX = 10001;
|
|
449
|
+
const getSafeParticleCount = (count) => Math.max(0, Math.floor(count));
|
|
439
450
|
/**
|
|
440
|
-
*
|
|
441
|
-
*
|
|
442
|
-
*
|
|
443
|
-
* @returns Object with width and height properties
|
|
444
|
-
*
|
|
445
|
-
* @example
|
|
446
|
-
* ```tsx
|
|
447
|
-
* const { width, height } = useWindowSize();
|
|
448
|
-
* console.log(`Window size: ${width}x${height}`);
|
|
449
|
-
* ```
|
|
451
|
+
* Built-in confetti component
|
|
452
|
+
* Canvas-based confetti animation powered by canvas-confetti.
|
|
450
453
|
*/
|
|
451
|
-
|
|
452
|
-
const [
|
|
453
|
-
width: typeof window !== 'undefined' ? window.innerWidth : 0,
|
|
454
|
-
height: typeof window !== 'undefined' ? window.innerHeight : 0,
|
|
455
|
-
});
|
|
454
|
+
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, }) => {
|
|
455
|
+
const [isVisible, setIsVisible] = useState(false);
|
|
456
456
|
useEffect(() => {
|
|
457
|
-
|
|
458
|
-
|
|
457
|
+
if (!show) {
|
|
458
|
+
setIsVisible(false);
|
|
459
|
+
confetti.reset();
|
|
459
460
|
return;
|
|
460
461
|
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
462
|
+
setIsVisible(true);
|
|
463
|
+
const totalParticles = getSafeParticleCount(particleCount);
|
|
464
|
+
const resolvedColors = colors.length > 0 ? colors : DEFAULT_COLORS;
|
|
465
|
+
const resolvedShapes = shapes.length > 0 ? shapes : DEFAULT_SHAPES;
|
|
466
|
+
const baseOptions = {
|
|
467
|
+
colors: resolvedColors,
|
|
468
|
+
shapes: resolvedShapes,
|
|
469
|
+
spread,
|
|
470
|
+
startVelocity,
|
|
471
|
+
gravity,
|
|
472
|
+
scalar,
|
|
473
|
+
zIndex,
|
|
474
|
+
disableForReducedMotion: true,
|
|
466
475
|
};
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
};
|
|
475
|
-
}, []);
|
|
476
|
-
return size;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
/**
|
|
480
|
-
* Built-in confetti component
|
|
481
|
-
* Lightweight CSS-based confetti animation
|
|
482
|
-
*/
|
|
483
|
-
const BuiltInConfetti = ({ show, duration = 5000, particleCount = 50, colors = ['#FFD700', '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7'], }) => {
|
|
484
|
-
const [isVisible, setIsVisible] = useState(false);
|
|
485
|
-
const { width, height } = useWindowSize();
|
|
486
|
-
useEffect(() => {
|
|
487
|
-
if (show) {
|
|
488
|
-
setIsVisible(true);
|
|
489
|
-
const timer = setTimeout(() => setIsVisible(false), duration);
|
|
490
|
-
return () => clearTimeout(timer);
|
|
476
|
+
if (totalParticles > 0) {
|
|
477
|
+
const centerParticles = Math.ceil(totalParticles * 0.5);
|
|
478
|
+
const leftParticles = Math.floor((totalParticles - centerParticles) / 2);
|
|
479
|
+
const rightParticles = totalParticles - centerParticles - leftParticles;
|
|
480
|
+
confetti(Object.assign(Object.assign({}, baseOptions), { particleCount: centerParticles, origin: { x: 0.5, y: 0.58 } }));
|
|
481
|
+
confetti(Object.assign(Object.assign({}, baseOptions), { particleCount: leftParticles, angle: 60, spread: Math.max(45, spread * 0.8), origin: { x: 0, y: 0.72 } }));
|
|
482
|
+
confetti(Object.assign(Object.assign({}, baseOptions), { particleCount: rightParticles, angle: 120, spread: Math.max(45, spread * 0.8), origin: { x: 1, y: 0.72 } }));
|
|
491
483
|
}
|
|
492
|
-
|
|
484
|
+
const timer = setTimeout(() => {
|
|
493
485
|
setIsVisible(false);
|
|
494
|
-
|
|
495
|
-
|
|
486
|
+
confetti.reset();
|
|
487
|
+
}, duration);
|
|
488
|
+
return () => {
|
|
489
|
+
clearTimeout(timer);
|
|
490
|
+
confetti.reset();
|
|
491
|
+
};
|
|
492
|
+
}, [
|
|
493
|
+
show,
|
|
494
|
+
duration,
|
|
495
|
+
particleCount,
|
|
496
|
+
colors,
|
|
497
|
+
shapes,
|
|
498
|
+
spread,
|
|
499
|
+
startVelocity,
|
|
500
|
+
gravity,
|
|
501
|
+
scalar,
|
|
502
|
+
zIndex,
|
|
503
|
+
]);
|
|
496
504
|
if (!isVisible)
|
|
497
505
|
return null;
|
|
498
|
-
|
|
499
|
-
position: 'fixed',
|
|
500
|
-
top: 0,
|
|
501
|
-
left: 0,
|
|
502
|
-
width: '100%',
|
|
503
|
-
height: '100%',
|
|
504
|
-
pointerEvents: 'none',
|
|
505
|
-
zIndex: 10001,
|
|
506
|
-
overflow: 'hidden',
|
|
507
|
-
};
|
|
508
|
-
// Generate particles
|
|
509
|
-
const particles = Array.from({ length: particleCount }, (_, i) => {
|
|
510
|
-
const color = colors[Math.floor(Math.random() * colors.length)];
|
|
511
|
-
const startX = Math.random() * width;
|
|
512
|
-
const rotation = Math.random() * 360;
|
|
513
|
-
const fallDuration = 3 + Math.random() * 2; // 3-5 seconds
|
|
514
|
-
const delay = Math.random() * 0.5; // 0-0.5s delay
|
|
515
|
-
const shape = Math.random() > 0.5 ? 'circle' : 'square';
|
|
516
|
-
const particleStyles = {
|
|
517
|
-
position: 'absolute',
|
|
518
|
-
top: '-20px',
|
|
519
|
-
left: `${startX}px`,
|
|
520
|
-
width: '10px',
|
|
521
|
-
height: '10px',
|
|
522
|
-
backgroundColor: color,
|
|
523
|
-
borderRadius: shape === 'circle' ? '50%' : '0',
|
|
524
|
-
transform: `rotate(${rotation}deg)`,
|
|
525
|
-
animation: `confettiFall ${fallDuration}s linear ${delay}s forwards`,
|
|
526
|
-
opacity: 0.9,
|
|
527
|
-
};
|
|
528
|
-
return React.createElement("div", { key: i, style: particleStyles, "data-testid": "confetti-particle" });
|
|
529
|
-
});
|
|
530
|
-
return (React.createElement(React.Fragment, null,
|
|
531
|
-
React.createElement("style", null, `
|
|
532
|
-
@keyframes confettiFall {
|
|
533
|
-
0% {
|
|
534
|
-
transform: translateY(0) rotate(0deg);
|
|
535
|
-
opacity: 1;
|
|
536
|
-
}
|
|
537
|
-
100% {
|
|
538
|
-
transform: translateY(${height + 50}px) rotate(720deg);
|
|
539
|
-
opacity: 0;
|
|
540
|
-
}
|
|
541
|
-
}
|
|
542
|
-
`),
|
|
543
|
-
React.createElement("div", { style: containerStyles, "data-testid": "built-in-confetti" }, particles)));
|
|
506
|
+
return React.createElement("div", { "data-testid": "built-in-confetti", style: { display: 'none' } });
|
|
544
507
|
};
|
|
545
508
|
|
|
546
509
|
const DEFAULT_NOTIFICATION_DURATION_MS = 5000;
|
|
547
510
|
const CONFETTI_DURATION_MS = 5000;
|
|
511
|
+
const hasConfiguredConfetti = (confetti) => {
|
|
512
|
+
return confetti === false || (typeof confetti === 'object' && confetti !== null);
|
|
513
|
+
};
|
|
514
|
+
const collectComplexConfetti = (achievements, confettiByAchievementId) => {
|
|
515
|
+
Object.values(achievements).forEach((metricAchievements) => {
|
|
516
|
+
metricAchievements.forEach(({ achievementDetails }) => {
|
|
517
|
+
const confetti = achievementDetails.confetti;
|
|
518
|
+
if (hasConfiguredConfetti(confetti)) {
|
|
519
|
+
confettiByAchievementId.set(achievementDetails.achievementId, confetti);
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
});
|
|
523
|
+
};
|
|
524
|
+
const simpleConfigHasRewardConfetti = (achievements) => {
|
|
525
|
+
return Object.values(achievements).some((metricAchievements) => Object.values(metricAchievements).some((achievement) => hasConfiguredConfetti(achievement.confetti)));
|
|
526
|
+
};
|
|
527
|
+
const prepareAchievementsForConfetti = (achievements) => {
|
|
528
|
+
const confettiByAchievementId = new Map();
|
|
529
|
+
if (!achievements) {
|
|
530
|
+
return { achievements, confettiByAchievementId };
|
|
531
|
+
}
|
|
532
|
+
if (!isSimpleConfig(achievements)) {
|
|
533
|
+
collectComplexConfetti(achievements, confettiByAchievementId);
|
|
534
|
+
return { achievements, confettiByAchievementId };
|
|
535
|
+
}
|
|
536
|
+
const simpleAchievements = achievements;
|
|
537
|
+
if (!simpleConfigHasRewardConfetti(simpleAchievements)) {
|
|
538
|
+
return { achievements, confettiByAchievementId };
|
|
539
|
+
}
|
|
540
|
+
const normalizedAchievements = normalizeAchievements(simpleAchievements);
|
|
541
|
+
Object.entries(simpleAchievements).forEach(([metric, metricAchievements]) => {
|
|
542
|
+
const normalizedMetricAchievements = normalizedAchievements[metric] || [];
|
|
543
|
+
Object.values(metricAchievements).forEach((achievement, index) => {
|
|
544
|
+
const confetti = achievement.confetti;
|
|
545
|
+
const normalizedAchievement = normalizedMetricAchievements[index];
|
|
546
|
+
if (normalizedAchievement && hasConfiguredConfetti(confetti)) {
|
|
547
|
+
normalizedAchievement.achievementDetails.confetti = confetti;
|
|
548
|
+
confettiByAchievementId.set(normalizedAchievement.achievementDetails.achievementId, confetti);
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
});
|
|
552
|
+
return { achievements: normalizedAchievements, confettiByAchievementId };
|
|
553
|
+
};
|
|
548
554
|
const AchievementUIContext = createContext({
|
|
549
555
|
icons: {},
|
|
550
556
|
ui: {},
|
|
551
557
|
});
|
|
552
|
-
const AchievementEffects = ({ icons, ui }) => {
|
|
553
|
-
var _a;
|
|
558
|
+
const AchievementEffects = ({ icons, ui, achievementConfetti }) => {
|
|
559
|
+
var _a, _b;
|
|
554
560
|
const engine = useAchievementEngine();
|
|
555
561
|
const seenAchievementsRef = useRef(new Set(engine.getUnlocked()));
|
|
556
562
|
const confettiTimerRef = useRef(null);
|
|
563
|
+
const achievementConfettiRef = useRef(achievementConfetti);
|
|
557
564
|
const [showConfetti, setShowConfetti] = useState(false);
|
|
565
|
+
const [activeConfettiConfig, setActiveConfettiConfig] = useState(null);
|
|
558
566
|
const [notifications, setNotifications] = useState([]);
|
|
559
567
|
const notificationDuration = (_a = ui.notificationDuration) !== null && _a !== void 0 ? _a : DEFAULT_NOTIFICATION_DURATION_MS;
|
|
568
|
+
const themeName = ui.theme || 'modern';
|
|
569
|
+
const themeConfig = useMemo(() => getTheme(themeName) || builtInThemes.modern, [themeName]);
|
|
570
|
+
const globalConfettiConfig = useMemo(() => (Object.assign(Object.assign({}, themeConfig.confetti), ui.confetti)), [themeConfig, ui.confetti]);
|
|
571
|
+
const globalConfettiConfigRef = useRef(globalConfettiConfig);
|
|
572
|
+
const renderedConfettiConfig = showConfetti && activeConfettiConfig ? activeConfettiConfig : globalConfettiConfig;
|
|
573
|
+
const renderedConfettiDuration = (_b = renderedConfettiConfig.duration) !== null && _b !== void 0 ? _b : CONFETTI_DURATION_MS;
|
|
574
|
+
useEffect(() => {
|
|
575
|
+
achievementConfettiRef.current = achievementConfetti;
|
|
576
|
+
}, [achievementConfetti]);
|
|
577
|
+
useEffect(() => {
|
|
578
|
+
globalConfettiConfigRef.current = globalConfettiConfig;
|
|
579
|
+
}, [globalConfettiConfig]);
|
|
580
|
+
useEffect(() => {
|
|
581
|
+
if (ui.enableConfetti === false) {
|
|
582
|
+
if (confettiTimerRef.current) {
|
|
583
|
+
clearTimeout(confettiTimerRef.current);
|
|
584
|
+
confettiTimerRef.current = null;
|
|
585
|
+
}
|
|
586
|
+
setShowConfetti(false);
|
|
587
|
+
setActiveConfettiConfig(null);
|
|
588
|
+
}
|
|
589
|
+
}, [ui.enableConfetti]);
|
|
560
590
|
useEffect(() => {
|
|
561
591
|
const unsubscribeUnlocked = engine.on('achievement:unlocked', (event) => {
|
|
592
|
+
var _a;
|
|
562
593
|
if (seenAchievementsRef.current.has(event.achievementId)) {
|
|
563
594
|
return;
|
|
564
595
|
}
|
|
@@ -578,15 +609,19 @@ const AchievementEffects = ({ icons, ui }) => {
|
|
|
578
609
|
return [...currentNotifications, unlockedAchievement];
|
|
579
610
|
});
|
|
580
611
|
}
|
|
581
|
-
|
|
612
|
+
const rewardConfetti = achievementConfettiRef.current.get(event.achievementId);
|
|
613
|
+
if (ui.enableConfetti !== false && rewardConfetti !== false) {
|
|
582
614
|
if (confettiTimerRef.current) {
|
|
583
615
|
clearTimeout(confettiTimerRef.current);
|
|
584
616
|
}
|
|
617
|
+
const resolvedConfettiConfig = Object.assign(Object.assign({}, globalConfettiConfigRef.current), (rewardConfetti || {}));
|
|
618
|
+
const resolvedConfettiDuration = (_a = resolvedConfettiConfig.duration) !== null && _a !== void 0 ? _a : CONFETTI_DURATION_MS;
|
|
619
|
+
setActiveConfettiConfig(resolvedConfettiConfig);
|
|
585
620
|
setShowConfetti(true);
|
|
586
621
|
confettiTimerRef.current = setTimeout(() => {
|
|
587
622
|
setShowConfetti(false);
|
|
588
623
|
confettiTimerRef.current = null;
|
|
589
|
-
},
|
|
624
|
+
}, resolvedConfettiDuration);
|
|
590
625
|
}
|
|
591
626
|
});
|
|
592
627
|
const unsubscribeStateChanged = engine.on('state:changed', () => {
|
|
@@ -610,18 +645,19 @@ const AchievementEffects = ({ icons, ui }) => {
|
|
|
610
645
|
return (React.createElement(React.Fragment, null,
|
|
611
646
|
ui.enableNotifications !== false &&
|
|
612
647
|
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 }))),
|
|
613
|
-
ui.enableConfetti !== false && (React.createElement(ConfettiComponentResolved, { show: showConfetti, duration:
|
|
648
|
+
ui.enableConfetti !== false && (React.createElement(ConfettiComponentResolved, Object.assign({ show: showConfetti }, renderedConfettiConfig, { duration: renderedConfettiDuration })))));
|
|
614
649
|
};
|
|
615
650
|
const AchievementProvider = (_a) => {
|
|
616
651
|
var { children, icons = {}, ui = {}, useBuiltInUI } = _a, providerProps = __rest(_a, ["children", "icons", "ui", "useBuiltInUI"]);
|
|
617
652
|
if (useBuiltInUI !== undefined) {
|
|
618
653
|
warnDeprecation('`useBuiltInUI` is deprecated and is now a no-op because built-in UI is the default. It will be removed in 5.0.');
|
|
619
654
|
}
|
|
655
|
+
const [{ achievements: preparedAchievements, confettiByAchievementId }] = useState(() => prepareAchievementsForConfetti(providerProps.achievements));
|
|
620
656
|
const uiContextValue = useMemo(() => ({ icons, ui }), [icons, ui]);
|
|
621
657
|
return (React.createElement(AchievementUIContext.Provider, { value: uiContextValue },
|
|
622
|
-
React.createElement(AchievementProvider$1, Object.assign({}, providerProps, { icons: icons }),
|
|
658
|
+
React.createElement(AchievementProvider$1, Object.assign({}, providerProps, { achievements: preparedAchievements, icons: icons }),
|
|
623
659
|
children,
|
|
624
|
-
React.createElement(AchievementEffects, { icons: icons, ui: ui }))));
|
|
660
|
+
React.createElement(AchievementEffects, { achievementConfetti: confettiByAchievementId, icons: icons, ui: ui }))));
|
|
625
661
|
};
|
|
626
662
|
|
|
627
663
|
const useAchievements = () => {
|
|
@@ -1397,5 +1433,45 @@ const BuiltInModal = ({ isOpen, onClose, achievements, icons = {}, theme = 'mode
|
|
|
1397
1433
|
})))))));
|
|
1398
1434
|
};
|
|
1399
1435
|
|
|
1436
|
+
/**
|
|
1437
|
+
* Hook to track window dimensions
|
|
1438
|
+
* Replacement for react-use's useWindowSize
|
|
1439
|
+
*
|
|
1440
|
+
* @returns Object with width and height properties
|
|
1441
|
+
*
|
|
1442
|
+
* @example
|
|
1443
|
+
* ```tsx
|
|
1444
|
+
* const { width, height } = useWindowSize();
|
|
1445
|
+
* console.log(`Window size: ${width}x${height}`);
|
|
1446
|
+
* ```
|
|
1447
|
+
*/
|
|
1448
|
+
function useWindowSize() {
|
|
1449
|
+
const [size, setSize] = useState({
|
|
1450
|
+
width: typeof window !== 'undefined' ? window.innerWidth : 0,
|
|
1451
|
+
height: typeof window !== 'undefined' ? window.innerHeight : 0,
|
|
1452
|
+
});
|
|
1453
|
+
useEffect(() => {
|
|
1454
|
+
// Handle SSR - window may not be defined
|
|
1455
|
+
if (typeof window === 'undefined') {
|
|
1456
|
+
return;
|
|
1457
|
+
}
|
|
1458
|
+
const handleResize = () => {
|
|
1459
|
+
setSize({
|
|
1460
|
+
width: window.innerWidth,
|
|
1461
|
+
height: window.innerHeight,
|
|
1462
|
+
});
|
|
1463
|
+
};
|
|
1464
|
+
// Set initial size
|
|
1465
|
+
handleResize();
|
|
1466
|
+
// Add event listener
|
|
1467
|
+
window.addEventListener('resize', handleResize);
|
|
1468
|
+
// Cleanup
|
|
1469
|
+
return () => {
|
|
1470
|
+
window.removeEventListener('resize', handleResize);
|
|
1471
|
+
};
|
|
1472
|
+
}, []);
|
|
1473
|
+
return size;
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1400
1476
|
export { AchievementContext, AchievementProvider, AchievementsList, AchievementsModal, AchievementsWidget, BadgesButton, BadgesButtonWithModal, BadgesModal, BuiltInConfetti, BuiltInModal, BuiltInNotification, ConfettiWrapper, AchievementProvider$1 as HeadlessAchievementProvider, LevelProgress, defaultAchievementIcons, defaultStyles, isAsyncStorage, useAchievementEngine, useAchievementState, useAchievements, useSimpleAchievements, useWindowSize };
|
|
1401
1477
|
//# sourceMappingURL=web.esm.js.map
|