@freegamestore/games 0.15.1 → 0.18.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 +61 -8
- package/TOKENS.md +132 -0
- package/dist/Confetti.d.ts +20 -0
- package/dist/Confetti.d.ts.map +1 -0
- package/dist/Confetti.js +76 -0
- package/dist/Confetti.js.map +1 -0
- package/dist/GameConfirm.d.ts +1 -1
- package/dist/GameConfirm.d.ts.map +1 -1
- package/dist/GameModal.d.ts +1 -1
- package/dist/GameModal.d.ts.map +1 -1
- package/dist/GameOverScreen.d.ts +1 -1
- package/dist/GameOverScreen.d.ts.map +1 -1
- package/dist/GameResultScreen.d.ts +46 -0
- package/dist/GameResultScreen.d.ts.map +1 -0
- package/dist/GameResultScreen.js +157 -0
- package/dist/GameResultScreen.js.map +1 -0
- package/dist/GameTextSizeToggle.d.ts +1 -1
- package/dist/GameTextSizeToggle.d.ts.map +1 -1
- package/dist/GameThemeToggle.d.ts +1 -1
- package/dist/GameThemeToggle.d.ts.map +1 -1
- package/dist/GameThemeToggle.js +43 -7
- package/dist/GameThemeToggle.js.map +1 -1
- package/dist/GameTopbar.d.ts +19 -7
- package/dist/GameTopbar.d.ts.map +1 -1
- package/dist/GameTopbar.js +113 -168
- package/dist/GameTopbar.js.map +1 -1
- package/dist/GameTopbar.module.css +201 -0
- package/dist/StartScreen.d.ts +48 -0
- package/dist/StartScreen.d.ts.map +1 -0
- package/dist/StartScreen.js +159 -0
- package/dist/StartScreen.js.map +1 -0
- package/dist/feel/ScorePopup.d.ts +25 -0
- package/dist/feel/ScorePopup.d.ts.map +1 -0
- package/dist/feel/ScorePopup.js +67 -0
- package/dist/feel/ScorePopup.js.map +1 -0
- package/dist/feel/easing.d.ts +14 -0
- package/dist/feel/easing.d.ts.map +1 -0
- package/dist/feel/easing.js +12 -0
- package/dist/feel/easing.js.map +1 -0
- package/dist/feel/haptics.d.ts +19 -0
- package/dist/feel/haptics.d.ts.map +1 -0
- package/dist/feel/haptics.js +24 -0
- package/dist/feel/haptics.js.map +1 -0
- package/dist/feel/index.d.ts +17 -0
- package/dist/feel/index.d.ts.map +1 -0
- package/dist/feel/index.js +17 -0
- package/dist/feel/index.js.map +1 -0
- package/dist/feel/particles.d.ts +46 -0
- package/dist/feel/particles.d.ts.map +1 -0
- package/dist/feel/particles.js +61 -0
- package/dist/feel/particles.js.map +1 -0
- package/dist/feel/reducedMotion.d.ts +6 -0
- package/dist/feel/reducedMotion.d.ts.map +1 -0
- package/dist/feel/reducedMotion.js +10 -0
- package/dist/feel/reducedMotion.js.map +1 -0
- package/dist/feel/shake.d.ts +6 -0
- package/dist/feel/shake.d.ts.map +1 -0
- package/dist/feel/shake.js +17 -0
- package/dist/feel/shake.js.map +1 -0
- package/dist/feel/tween.d.ts +9 -0
- package/dist/feel/tween.d.ts.map +1 -0
- package/dist/feel/tween.js +15 -0
- package/dist/feel/tween.js.map +1 -0
- package/dist/feel/useHaptics.d.ts +12 -0
- package/dist/feel/useHaptics.d.ts.map +1 -0
- package/dist/feel/useHaptics.js +16 -0
- package/dist/feel/useHaptics.js.map +1 -0
- package/dist/feel/useParticles.d.ts +18 -0
- package/dist/feel/useParticles.d.ts.map +1 -0
- package/dist/feel/useParticles.js +79 -0
- package/dist/feel/useParticles.js.map +1 -0
- package/dist/feel/useShake.d.ts +14 -0
- package/dist/feel/useShake.d.ts.map +1 -0
- package/dist/feel/useShake.js +17 -0
- package/dist/feel/useShake.js.map +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -2
- package/dist/index.js.map +1 -1
- package/dist/tokens.d.ts +112 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +106 -0
- package/dist/tokens.js.map +1 -0
- package/dist/useGameSounds.d.ts.map +1 -1
- package/dist/useGameSounds.js +37 -15
- package/dist/useGameSounds.js.map +1 -1
- package/dist/useLeaderboard.d.ts +8 -1
- package/dist/useLeaderboard.d.ts.map +1 -1
- package/dist/useLeaderboard.js +21 -11
- package/dist/useLeaderboard.js.map +1 -1
- package/package.json +21 -6
package/dist/GameThemeToggle.js
CHANGED
|
@@ -1,20 +1,40 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useState } from 'react';
|
|
3
3
|
const THEME_KEY = 'stores-theme';
|
|
4
|
+
// Storage can be unavailable: privacy modes, blocked third-party storage in an
|
|
5
|
+
// iframe, or disabled cookies make even reading `window.localStorage` throw a
|
|
6
|
+
// SecurityError. This runs during render, so an unguarded access crashed the
|
|
7
|
+
// whole game (#99) — the toggle must degrade to an unsaved preference instead.
|
|
4
8
|
function getStoredPref() {
|
|
5
9
|
if (typeof window === 'undefined')
|
|
6
10
|
return 'system';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
try {
|
|
12
|
+
const s = window.localStorage.getItem(THEME_KEY);
|
|
13
|
+
if (s === 'light' || s === 'dark' || s === 'system')
|
|
14
|
+
return s;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Storage blocked — fall back to the default.
|
|
18
|
+
}
|
|
10
19
|
return 'system';
|
|
11
20
|
}
|
|
21
|
+
function storePref(pref) {
|
|
22
|
+
try {
|
|
23
|
+
window.localStorage.setItem(THEME_KEY, pref);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
// Storage blocked or full — the theme still applies for this visit.
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function darkQuery() {
|
|
30
|
+
if (typeof window === 'undefined' || typeof window.matchMedia !== 'function')
|
|
31
|
+
return null;
|
|
32
|
+
return window.matchMedia('(prefers-color-scheme: dark)');
|
|
33
|
+
}
|
|
12
34
|
function resolve(pref) {
|
|
13
35
|
if (pref !== 'system')
|
|
14
36
|
return pref;
|
|
15
|
-
return
|
|
16
|
-
? 'dark'
|
|
17
|
-
: 'light';
|
|
37
|
+
return darkQuery()?.matches ? 'dark' : 'light';
|
|
18
38
|
}
|
|
19
39
|
function apply(pref) {
|
|
20
40
|
if (typeof document === 'undefined')
|
|
@@ -26,7 +46,7 @@ function apply(pref) {
|
|
|
26
46
|
else {
|
|
27
47
|
delete document.documentElement.dataset.theme;
|
|
28
48
|
}
|
|
29
|
-
|
|
49
|
+
storePref(pref);
|
|
30
50
|
}
|
|
31
51
|
/**
|
|
32
52
|
* Compact theme toggle for game topbars. Sun/moon icon, 28px square.
|
|
@@ -40,6 +60,22 @@ export function GameThemeToggle() {
|
|
|
40
60
|
useEffect(() => {
|
|
41
61
|
apply(pref);
|
|
42
62
|
}, [pref]);
|
|
63
|
+
// "system" follows the OS: re-apply when the OS theme changes, rather than
|
|
64
|
+
// only on reload.
|
|
65
|
+
const [, setOsTick] = useState(0);
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (pref !== 'system')
|
|
68
|
+
return;
|
|
69
|
+
const mq = darkQuery();
|
|
70
|
+
if (!mq)
|
|
71
|
+
return;
|
|
72
|
+
const onChange = () => {
|
|
73
|
+
apply('system');
|
|
74
|
+
setOsTick((n) => n + 1); // re-render so the icon matches
|
|
75
|
+
};
|
|
76
|
+
mq.addEventListener('change', onChange);
|
|
77
|
+
return () => mq.removeEventListener('change', onChange);
|
|
78
|
+
}, [pref]);
|
|
43
79
|
const cycle = useCallback(() => {
|
|
44
80
|
const order = ['system', 'light', 'dark'];
|
|
45
81
|
const next = order[(order.indexOf(pref) + 1) % order.length];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GameThemeToggle.js","sourceRoot":"","sources":["../src/GameThemeToggle.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEzD,MAAM,SAAS,GAAG,cAAc,CAAC;AAGjC,SAAS,aAAa;IACpB,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,QAAQ,CAAC;IACnD,MAAM,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"GameThemeToggle.js","sourceRoot":"","sources":["../src/GameThemeToggle.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEzD,MAAM,SAAS,GAAG,cAAc,CAAC;AAGjC,+EAA+E;AAC/E,8EAA8E;AAC9E,6EAA6E;AAC7E,+EAA+E;AAC/E,SAAS,aAAa;IACpB,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO,QAAQ,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,QAAQ;YAAE,OAAO,CAAC,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,8CAA8C;IAChD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,SAAS,CAAC,IAAU;IAC3B,IAAI,CAAC;QACH,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,oEAAoE;IACtE,CAAC;AACH,CAAC;AAED,SAAS,SAAS;IAChB,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,UAAU;QAAE,OAAO,IAAI,CAAC;IAC1F,OAAO,MAAM,CAAC,UAAU,CAAC,8BAA8B,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,OAAO,CAAC,IAAU;IACzB,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACnC,OAAO,SAAS,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;AACjD,CAAC;AAED,SAAS,KAAK,CAAC,IAAU;IACvB,IAAI,OAAO,QAAQ,KAAK,WAAW;QAAE,OAAO;IAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACrB,QAAQ,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC;IAClD,CAAC;SAAM,CAAC;QACN,OAAO,QAAQ,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC;IAChD,CAAC;IACD,SAAS,CAAC,IAAI,CAAC,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAO,aAAa,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B,2EAA2E;IAC3E,gEAAgE;IAChE,SAAS,CAAC,GAAG,EAAE;QACb,KAAK,CAAC,IAAI,CAAC,CAAC;IACd,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,2EAA2E;IAC3E,kBAAkB;IAClB,MAAM,CAAC,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAClC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,IAAI,KAAK,QAAQ;YAAE,OAAO;QAC9B,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;QACvB,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,MAAM,QAAQ,GAAG,GAAG,EAAE;YACpB,KAAK,CAAC,QAAQ,CAAC,CAAC;YAChB,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,gCAAgC;QAC3D,CAAC,CAAC;QACF,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACxC,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC1D,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,MAAM,KAAK,GAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAE,CAAC;QAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,wBAAwB;IACzC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,CACL,iBACE,OAAO,EAAE,KAAK,gBACF,UAAU,IAAI,EAAE,EAC5B,KAAK,EAAE,UAAU,IAAI,EAAE,EACvB,KAAK,EAAE;YACL,KAAK,EAAE,EAAE;YACT,MAAM,EAAE,EAAE;YACV,YAAY,EAAE,CAAC;YACf,MAAM,EAAE,gCAAgC;YACxC,UAAU,EAAE,uBAAuB;YACnC,KAAK,EAAE,qBAAqB;YAC5B,OAAO,EAAE,aAAa;YACtB,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,QAAQ;YACxB,MAAM,EAAE,SAAS;YACjB,OAAO,EAAE,CAAC;YACV,UAAU,EAAE,SAAS;SACtB,YAEA,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,CAClB,eACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,aAEtB,iBAAQ,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,CAAC,EAAC,GAAG,GAAG,EAChC,eAAM,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,GAAG,GAAG,EACtC,eAAM,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,GAAG,EACxC,eAAM,EAAE,EAAC,MAAM,EAAC,EAAE,EAAC,MAAM,EAAC,EAAE,EAAC,MAAM,EAAC,EAAE,EAAC,MAAM,GAAG,EAChD,eAAM,EAAE,EAAC,OAAO,EAAC,EAAE,EAAC,OAAO,EAAC,EAAE,EAAC,OAAO,EAAC,EAAE,EAAC,OAAO,GAAG,EACpD,eAAM,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,IAAI,GAAG,EACtC,eAAM,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,GAAG,EACxC,eAAM,EAAE,EAAC,MAAM,EAAC,EAAE,EAAC,OAAO,EAAC,EAAE,EAAC,MAAM,EAAC,EAAE,EAAC,OAAO,GAAG,EAClD,eAAM,EAAE,EAAC,OAAO,EAAC,EAAE,EAAC,MAAM,EAAC,EAAE,EAAC,OAAO,EAAC,EAAE,EAAC,MAAM,GAAG,IAC9C,CACP,CAAC,CAAC,CAAC,CACF,cACE,KAAK,EAAC,IAAI,EACV,MAAM,EAAC,IAAI,EACX,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAC,GAAG,EACf,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,YAEtB,eAAM,CAAC,EAAC,iDAAiD,GAAG,GACxD,CACP,GACM,CACV,CAAC;AACJ,CAAC"}
|
package/dist/GameTopbar.d.ts
CHANGED
|
@@ -15,14 +15,19 @@ export interface GameTopbarProps {
|
|
|
15
15
|
/** The game's display name. Shows on the left in Manrope. */
|
|
16
16
|
title?: string;
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* value: score, accent: true }]`.
|
|
18
|
+
* The live score shown in the score pill. Only rendered when `showScore` is
|
|
19
|
+
* true. Without `showScore`, the pill stays hidden (#348).
|
|
21
20
|
*/
|
|
22
21
|
score?: number;
|
|
23
22
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* Show the live score pill (#348). Off by default, so the topbar stays clean
|
|
24
|
+
* for games that do not use it. Games that want the pill set this to true
|
|
25
|
+
* and pass `score`.
|
|
26
|
+
*/
|
|
27
|
+
showScore?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Custom stat lineup, e.g. lives, level or time. Each entry renders as a
|
|
30
|
+
* stat pill in the topbar.
|
|
26
31
|
*/
|
|
27
32
|
stats?: GameTopbarStat[];
|
|
28
33
|
/**
|
|
@@ -35,6 +40,13 @@ export interface GameTopbarProps {
|
|
|
35
40
|
* topbar. Tapping it opens a fullscreen overlay with the rules content.
|
|
36
41
|
*/
|
|
37
42
|
rules?: ReactNode;
|
|
43
|
+
/**
|
|
44
|
+
* Optional extra content for the About panel (credits, a one-line pitch,
|
|
45
|
+
* links). The About (i) button is ALWAYS shown regardless — it also displays
|
|
46
|
+
* the game's deployed version + timestamp, read from `/version.json`. Pass
|
|
47
|
+
* this only to add your own content above that.
|
|
48
|
+
*/
|
|
49
|
+
about?: ReactNode;
|
|
38
50
|
/**
|
|
39
51
|
* For interactive/real-time games (Tetris, Snake, etc.). When provided,
|
|
40
52
|
* the SDK renders standard play/pause + restart icon buttons in the topbar.
|
|
@@ -53,10 +65,10 @@ export interface GameTopbarProps {
|
|
|
53
65
|
}
|
|
54
66
|
/**
|
|
55
67
|
* The single allowed topbar shape for FreeGameStore games. Brand
|
|
56
|
-
* consistency: same font, same paddings, same
|
|
68
|
+
* consistency: same font, same paddings, same colour tokens, same stat
|
|
57
69
|
* layout across every game on the storefront.
|
|
58
70
|
*
|
|
59
71
|
* Use inside <GameShell topbar={<GameTopbar … />}>.
|
|
60
72
|
*/
|
|
61
|
-
export declare function GameTopbar({ title, score, stats, actions, rules, onPlayPause, paused, onRestart, }: GameTopbarProps): React.JSX.Element;
|
|
73
|
+
export declare function GameTopbar({ title, score, showScore, stats, actions, rules, about, onPlayPause, paused, onRestart, }: GameTopbarProps): React.JSX.Element;
|
|
62
74
|
//# sourceMappingURL=GameTopbar.d.ts.map
|
package/dist/GameTopbar.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GameTopbar.d.ts","sourceRoot":"","sources":["../src/GameTopbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"GameTopbar.d.ts","sourceRoot":"","sources":["../src/GameTopbar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,mDAAmD;IACnD,KAAK,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IAEzB;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,CAAC;IAEpB;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IAEzB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAkED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,KAAK,EACL,SAAiB,EACjB,KAAK,EACL,OAAO,EACP,KAAK,EACL,KAAK,EACL,WAAW,EACX,MAAM,EACN,SAAS,GACV,EAAE,eAAe,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAwKrC"}
|
package/dist/GameTopbar.js
CHANGED
|
@@ -1,184 +1,129 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
2
|
+
import { forwardRef, useEffect, useRef, useState } from 'react';
|
|
3
|
+
import styles from './GameTopbar.module.css';
|
|
3
4
|
import { useSound } from './SoundContext.js';
|
|
5
|
+
/**
|
|
6
|
+
* Shared icon button for topbar controls. All buttons in the topbar (catalog,
|
|
7
|
+
* rules, play/pause, restart, about, sound, close) use this consistent sizing
|
|
8
|
+
* and behaviour. The `data-fgs-tb-btn` attribute is kept on every control so
|
|
9
|
+
* games that already target it keep working.
|
|
10
|
+
*/
|
|
11
|
+
const TopbarIconButton = forwardRef(function TopbarIconButton({ onClick, href, target, rel, tone = 'muted', ariaLabel, ariaPressed, children }, ref) {
|
|
12
|
+
const className = `${styles.button} ${toneClass(tone)}`;
|
|
13
|
+
if (href) {
|
|
14
|
+
return (_jsx("a", { "data-fgs-tb-btn": true, href: href, target: target, rel: rel, className: `${className} ${styles.link}`, "aria-label": ariaLabel, children: children }));
|
|
15
|
+
}
|
|
16
|
+
return (_jsx("button", { ref: ref, "data-fgs-tb-btn": true, onClick: onClick, className: className, "aria-label": ariaLabel, "aria-pressed": ariaPressed, children: children }));
|
|
17
|
+
});
|
|
18
|
+
function toneClass(tone) {
|
|
19
|
+
if (tone === 'ink')
|
|
20
|
+
return styles.toneInk ?? '';
|
|
21
|
+
if (tone === 'accent')
|
|
22
|
+
return styles.toneAccent ?? '';
|
|
23
|
+
return styles.toneMuted ?? '';
|
|
24
|
+
}
|
|
4
25
|
/**
|
|
5
26
|
* The single allowed topbar shape for FreeGameStore games. Brand
|
|
6
|
-
* consistency: same font, same paddings, same
|
|
27
|
+
* consistency: same font, same paddings, same colour tokens, same stat
|
|
7
28
|
* layout across every game on the storefront.
|
|
8
29
|
*
|
|
9
30
|
* Use inside <GameShell topbar={<GameTopbar … />}>.
|
|
10
31
|
*/
|
|
11
|
-
export function GameTopbar({ title, score, stats, actions, rules, onPlayPause, paused, onRestart, }) {
|
|
32
|
+
export function GameTopbar({ title, score, showScore = false, stats, actions, rules, about, onPlayPause, paused, onRestart, }) {
|
|
12
33
|
const [showRules, setShowRules] = useState(false);
|
|
34
|
+
const [showAbout, setShowAbout] = useState(false);
|
|
13
35
|
const sound = useSound();
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
? [{ label: 'Score', value: score, accent: true }]
|
|
18
|
-
: [];
|
|
19
|
-
return (_jsxs(_Fragment, { children: [_jsx("style", { children: TOPBAR_BUTTON_CSS }), _jsxs("div", { style: {
|
|
20
|
-
display: 'flex',
|
|
21
|
-
alignItems: 'center',
|
|
22
|
-
justifyContent: 'space-between',
|
|
23
|
-
gap: '0.75rem',
|
|
24
|
-
padding: '0.25rem 0.75rem',
|
|
25
|
-
height: '2rem',
|
|
26
|
-
}, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '0.25rem', minWidth: 0 }, children: [_jsx("a", { "data-fgs-tb-btn": true, href: "https://freegamestore.online", target: "_blank", rel: "noopener noreferrer", style: {
|
|
27
|
-
background: 'none',
|
|
28
|
-
border: 'none',
|
|
29
|
-
cursor: 'pointer',
|
|
30
|
-
padding: 0,
|
|
31
|
-
minWidth: '2.75rem',
|
|
32
|
-
minHeight: '2.75rem',
|
|
33
|
-
display: 'flex',
|
|
34
|
-
alignItems: 'center',
|
|
35
|
-
justifyContent: 'center',
|
|
36
|
-
color: 'var(--muted, #999)',
|
|
37
|
-
WebkitTapHighlightColor: 'transparent',
|
|
38
|
-
textDecoration: 'none',
|
|
39
|
-
}, "aria-label": "Browse all games", children: _jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("rect", { x: "2", y: "2", width: "5", height: "5", rx: "1" }), _jsx("rect", { x: "9", y: "2", width: "5", height: "5", rx: "1" }), _jsx("rect", { x: "2", y: "9", width: "5", height: "5", rx: "1" }), _jsx("rect", { x: "9", y: "9", width: "5", height: "5", rx: "1" })] }) }), rules !== undefined && (_jsx("button", { "data-fgs-tb-btn": true, onClick: () => setShowRules(true), style: {
|
|
40
|
-
background: 'none',
|
|
41
|
-
border: 'none',
|
|
42
|
-
cursor: 'pointer',
|
|
43
|
-
padding: 0,
|
|
44
|
-
minWidth: '2.75rem',
|
|
45
|
-
minHeight: '2.75rem',
|
|
46
|
-
display: 'flex',
|
|
47
|
-
alignItems: 'center',
|
|
48
|
-
justifyContent: 'center',
|
|
49
|
-
color: 'var(--muted, #999)',
|
|
50
|
-
lineHeight: 1,
|
|
51
|
-
WebkitTapHighlightColor: 'transparent',
|
|
52
|
-
}, "aria-label": "Game rules", children: _jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("circle", { cx: "8", cy: "8", r: "6.5" }), _jsx("path", { d: "M8 11.5v0M8 5v4" })] }) })), title !== undefined && (_jsx("span", { style: {
|
|
53
|
-
fontFamily: '"Manrope", system-ui, sans-serif',
|
|
54
|
-
fontWeight: 600,
|
|
55
|
-
fontSize: '0.8rem',
|
|
56
|
-
letterSpacing: '-0.01em',
|
|
57
|
-
whiteSpace: 'nowrap',
|
|
58
|
-
overflow: 'hidden',
|
|
59
|
-
textOverflow: 'ellipsis',
|
|
60
|
-
}, children: title }))] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '0.75rem' }, children: [resolvedStats.map((s) => (_jsx(Stat, { stat: s }, s.label))), onPlayPause !== undefined && (_jsx("button", { "data-fgs-tb-btn": true, onClick: onPlayPause, style: {
|
|
61
|
-
background: 'none',
|
|
62
|
-
border: 'none',
|
|
63
|
-
cursor: 'pointer',
|
|
64
|
-
padding: 0,
|
|
65
|
-
minWidth: '2.75rem',
|
|
66
|
-
minHeight: '2.75rem',
|
|
67
|
-
display: 'flex',
|
|
68
|
-
alignItems: 'center',
|
|
69
|
-
justifyContent: 'center',
|
|
70
|
-
color: 'var(--ink, #f0f0f0)',
|
|
71
|
-
WebkitTapHighlightColor: 'transparent',
|
|
72
|
-
}, "aria-label": "Pause", "aria-pressed": paused === true, children: paused ? (_jsx("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "currentColor", children: _jsx("path", { d: "M4 2l10 6-10 6V2z" }) })) : (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "currentColor", children: [_jsx("rect", { x: "2", y: "2", width: "4", height: "12", rx: "1" }), _jsx("rect", { x: "10", y: "2", width: "4", height: "12", rx: "1" })] })) })), onRestart !== undefined && (_jsx("button", { "data-fgs-tb-btn": true, onClick: onRestart, style: {
|
|
73
|
-
background: 'none',
|
|
74
|
-
border: 'none',
|
|
75
|
-
cursor: 'pointer',
|
|
76
|
-
padding: 0,
|
|
77
|
-
minWidth: '2.75rem',
|
|
78
|
-
minHeight: '2.75rem',
|
|
79
|
-
display: 'flex',
|
|
80
|
-
alignItems: 'center',
|
|
81
|
-
justifyContent: 'center',
|
|
82
|
-
color: 'var(--muted, #999)',
|
|
83
|
-
WebkitTapHighlightColor: 'transparent',
|
|
84
|
-
}, "aria-label": "Restart", children: _jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M2 8a6 6 0 0111.5-2.5" }), _jsx("path", { d: "M14 8a6 6 0 01-11.5 2.5" }), _jsx("path", { d: "M14 2v3.5h-3.5" }), _jsx("path", { d: "M2 14v-3.5h3.5" })] }) })), _jsx("button", { "data-fgs-tb-btn": true, onClick: sound.toggle, style: {
|
|
85
|
-
background: 'none',
|
|
86
|
-
border: 'none',
|
|
87
|
-
cursor: 'pointer',
|
|
88
|
-
padding: 0,
|
|
89
|
-
minWidth: '2.75rem',
|
|
90
|
-
minHeight: '2.75rem',
|
|
91
|
-
display: 'flex',
|
|
92
|
-
alignItems: 'center',
|
|
93
|
-
justifyContent: 'center',
|
|
94
|
-
color: sound.muted ? 'var(--muted, #999)' : 'var(--accent, #10b981)',
|
|
95
|
-
WebkitTapHighlightColor: 'transparent',
|
|
96
|
-
}, "aria-label": "Mute", "aria-pressed": sound.muted, children: sound.muted ? (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M8 2L4 5.5H1.5v5H4L8 14V2z" }), _jsx("path", { d: "M12 5.5l4 5M16 5.5l-4 5" })] })) : (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M8 2L4 5.5H1.5v5H4L8 14V2z" }), _jsx("path", { d: "M11.5 5a4.5 4.5 0 010 6" }), _jsx("path", { d: "M13.5 3a7.5 7.5 0 010 10" })] })) }), actions !== undefined && (_jsx("div", { style: { display: 'flex', gap: '0.4rem', alignItems: 'center' }, children: actions }))] })] }), showRules && rules !== undefined && (_jsx(RulesOverlay, { onClose: () => setShowRules(false), children: rules }))] }));
|
|
36
|
+
const scorePill = showScore && score !== undefined ? [{ label: 'Score', value: score, accent: true }] : [];
|
|
37
|
+
const resolvedStats = [...scorePill, ...(stats ?? [])];
|
|
38
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: styles.bar, children: [_jsxs("div", { className: styles.group, children: [_jsx(TopbarIconButton, { href: "https://freegamestore.online", target: "_blank", rel: "noopener noreferrer", ariaLabel: "Browse all games", children: _jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("rect", { x: "2", y: "2", width: "5", height: "5", rx: "1" }), _jsx("rect", { x: "9", y: "2", width: "5", height: "5", rx: "1" }), _jsx("rect", { x: "2", y: "9", width: "5", height: "5", rx: "1" }), _jsx("rect", { x: "9", y: "9", width: "5", height: "5", rx: "1" })] }) }), rules !== undefined && (_jsx(TopbarIconButton, { onClick: () => setShowRules(true), ariaLabel: "Game rules", children: _jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("circle", { cx: "8", cy: "8", r: "6.5" }), _jsx("path", { d: "M8 11.5v0M8 5v4" })] }) })), title !== undefined && _jsx("span", { className: styles.title, children: title })] }), _jsxs("div", { className: `${styles.group} ${styles.groupEnd}`, children: [resolvedStats.map((s) => (_jsx(Stat, { stat: s }, s.label))), onPlayPause !== undefined && (_jsx(TopbarIconButton, { onClick: onPlayPause, tone: "ink", ariaLabel: "Pause", ariaPressed: paused === true, children: paused ? (_jsx("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "currentColor", children: _jsx("path", { d: "M4 2l10 6-10 6V2z" }) })) : (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "currentColor", children: [_jsx("rect", { x: "2", y: "2", width: "4", height: "12", rx: "1" }), _jsx("rect", { x: "10", y: "2", width: "4", height: "12", rx: "1" })] })) })), onRestart !== undefined && (_jsx(TopbarIconButton, { onClick: onRestart, ariaLabel: "Restart", children: _jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M2 8a6 6 0 0111.5-2.5" }), _jsx("path", { d: "M14 8a6 6 0 01-11.5 2.5" }), _jsx("path", { d: "M14 2v3.5h-3.5" }), _jsx("path", { d: "M2 14v-3.5h3.5" })] }) })), _jsx(TopbarIconButton, { onClick: () => setShowAbout(true), ariaLabel: "About this game", children: _jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("circle", { cx: "8", cy: "8", r: "6.5" }), _jsx("path", { d: "M8 7.25v3.5" }), _jsx("path", { d: "M8 5.15v0" })] }) }), _jsx(TopbarIconButton, { onClick: sound.toggle, tone: sound.muted ? 'muted' : 'accent', ariaLabel: "Mute", ariaPressed: sound.muted, children: sound.muted ? (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M8 2L4 5.5H1.5v5H4L8 14V2z" }), _jsx("path", { d: "M12 5.5l4 5M16 5.5l-4 5" })] })) : (_jsxs("svg", { width: "14", height: "14", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M8 2L4 5.5H1.5v5H4L8 14V2z" }), _jsx("path", { d: "M11.5 5a4.5 4.5 0 010 6" }), _jsx("path", { d: "M13.5 3a7.5 7.5 0 010 10" })] })) }), actions !== undefined && _jsx("div", { className: styles.actions, children: actions })] })] }), showRules && rules !== undefined && (_jsx(RulesOverlay, { onClose: () => setShowRules(false), children: rules })), showAbout && (_jsx(AboutOverlay, { title: title, extra: about, onClose: () => setShowAbout(false) }))] }));
|
|
97
39
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
minWidth: '2.75rem',
|
|
126
|
-
minHeight: '2.75rem',
|
|
127
|
-
display: 'flex',
|
|
128
|
-
alignItems: 'center',
|
|
129
|
-
justifyContent: 'center',
|
|
130
|
-
WebkitTapHighlightColor: 'transparent',
|
|
131
|
-
}, "aria-label": "Close rules", children: "\u00D7" })] }), _jsx("div", { style: {
|
|
132
|
-
flex: 1,
|
|
133
|
-
overflowY: 'auto',
|
|
134
|
-
padding: '1rem',
|
|
135
|
-
fontFamily: '"Manrope", system-ui, sans-serif',
|
|
136
|
-
fontSize: '0.9rem',
|
|
137
|
-
lineHeight: 1.6,
|
|
138
|
-
}, children: children })] }));
|
|
139
|
-
}
|
|
140
|
-
function Stat({ stat }) {
|
|
141
|
-
return (_jsxs("div", { style: { textAlign: 'right', lineHeight: 1.05 }, children: [_jsx("div", { style: {
|
|
142
|
-
fontFamily: '"Manrope", system-ui, sans-serif',
|
|
143
|
-
fontWeight: 800,
|
|
144
|
-
fontSize: '0.85rem',
|
|
145
|
-
color: stat.accent === true ? 'var(--accent)' : 'var(--ink)',
|
|
146
|
-
fontVariantNumeric: 'tabular-nums',
|
|
147
|
-
lineHeight: 1,
|
|
148
|
-
}, children: stat.value }), _jsx("div", { style: {
|
|
149
|
-
// Was 0.5rem (~8px) — too small to read in sunlight or for
|
|
150
|
-
// anyone with even mild low vision. 0.65rem (~10.4px) keeps
|
|
151
|
-
// the visual hierarchy (value still dominates at 0.85rem)
|
|
152
|
-
// while staying legible.
|
|
153
|
-
fontSize: '0.65rem',
|
|
154
|
-
fontWeight: 700,
|
|
155
|
-
textTransform: 'uppercase',
|
|
156
|
-
letterSpacing: '0.06em',
|
|
157
|
-
color: 'var(--muted)',
|
|
158
|
-
lineHeight: 1,
|
|
159
|
-
}, children: stat.label })] }));
|
|
40
|
+
/** Compact "3 hours ago" style relative time — no dependency, no locale data. */
|
|
41
|
+
function relativeTime(iso) {
|
|
42
|
+
const then = Date.parse(iso);
|
|
43
|
+
if (Number.isNaN(then))
|
|
44
|
+
return '';
|
|
45
|
+
const secs = Math.max(0, Math.round((Date.now() - then) / 1000));
|
|
46
|
+
const units = [
|
|
47
|
+
[60, 'second'],
|
|
48
|
+
[60, 'minute'],
|
|
49
|
+
[24, 'hour'],
|
|
50
|
+
[30, 'day'],
|
|
51
|
+
[12, 'month'],
|
|
52
|
+
[Number.POSITIVE_INFINITY, 'year'],
|
|
53
|
+
];
|
|
54
|
+
let n = secs;
|
|
55
|
+
let unit = 'second';
|
|
56
|
+
for (const [div, name] of units) {
|
|
57
|
+
if (n < div) {
|
|
58
|
+
unit = name;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
n = Math.floor(n / div);
|
|
62
|
+
unit = name;
|
|
63
|
+
}
|
|
64
|
+
if (secs < 45)
|
|
65
|
+
return 'just now';
|
|
66
|
+
return `${n} ${unit}${n === 1 ? '' : 's'} ago`;
|
|
160
67
|
}
|
|
161
68
|
/**
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
* :active — opacity dip so taps feel anchored on touch devices that
|
|
167
|
-
* otherwise give no feedback (we already disable the
|
|
168
|
-
* default tap-highlight via WebkitTapHighlightColor).
|
|
169
|
-
*
|
|
170
|
-
* :focus-visible — accent outline so keyboard users see where focus
|
|
171
|
-
* is. -2px outline-offset draws inside the button's
|
|
172
|
-
* 2.75rem touch target so the ring doesn't bleed
|
|
173
|
-
* into adjacent controls.
|
|
69
|
+
* The About panel: the game's deployed version + when it shipped (read from
|
|
70
|
+
* `/version.json`, which every FreeGameStore game serves), plus any custom
|
|
71
|
+
* `extra` content and the store link. Version fetch is lazy — only when opened —
|
|
72
|
+
* and fails silently (a local `pnpm dev` build has no version.json).
|
|
174
73
|
*/
|
|
175
|
-
|
|
176
|
-
[
|
|
177
|
-
[
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
74
|
+
function AboutOverlay({ title, extra, onClose, }) {
|
|
75
|
+
const [info, setInfo] = useState(null);
|
|
76
|
+
const [loaded, setLoaded] = useState(false);
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
let cancelled = false;
|
|
79
|
+
fetch('/version.json', { cache: 'no-cache' })
|
|
80
|
+
.then((r) => r.ok ? r.json() : Promise.reject(new Error(String(r.status))))
|
|
81
|
+
.then((d) => {
|
|
82
|
+
if (!cancelled)
|
|
83
|
+
setInfo(d);
|
|
84
|
+
})
|
|
85
|
+
.catch(() => {
|
|
86
|
+
/* dev build / unreachable — show "development build" below */
|
|
87
|
+
})
|
|
88
|
+
.finally(() => {
|
|
89
|
+
if (!cancelled)
|
|
90
|
+
setLoaded(true);
|
|
91
|
+
});
|
|
92
|
+
return () => {
|
|
93
|
+
cancelled = true;
|
|
94
|
+
};
|
|
95
|
+
}, []);
|
|
96
|
+
const version = (info?.version ?? '').slice(0, 7);
|
|
97
|
+
const deployedAt = info?.deployedAt;
|
|
98
|
+
return (_jsxs(RulesOverlay, { title: "About", onClose: onClose, children: [title !== undefined && _jsx("h1", { className: styles.aboutHeading, children: title }), extra !== undefined && _jsx("div", { className: styles.aboutExtra, children: extra }), _jsxs("dl", { className: styles.aboutGrid, children: [_jsx("dt", { children: "Version" }), _jsx("dd", { children: version ? (_jsx("code", { className: styles.code, children: version })) : loaded ? ('development build') : ('…') }), deployedAt && (_jsxs(_Fragment, { children: [_jsx("dt", { children: "Deployed" }), _jsx("dd", { title: new Date(deployedAt).toLocaleString(), children: relativeTime(deployedAt) })] }))] }), _jsxs("p", { className: styles.aboutNote, children: ["A free game on", ' ', _jsx("a", { href: "https://freegamestore.online", target: "_blank", rel: "noopener noreferrer", className: styles.aboutLink, children: "FreeGameStore" }), "."] })] }));
|
|
99
|
+
}
|
|
100
|
+
function RulesOverlay({ children, title = 'How to Play', onClose, }) {
|
|
101
|
+
const overlayRef = useRef(null);
|
|
102
|
+
const closeButtonRef = useRef(null);
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
// Focus the close button when the overlay opens for keyboard accessibility
|
|
105
|
+
closeButtonRef.current?.focus();
|
|
106
|
+
// Handle Escape key to close the overlay, and prevent other keys from
|
|
107
|
+
// reaching game key handlers (which would continue game input while playing)
|
|
108
|
+
const handleKeyDown = (e) => {
|
|
109
|
+
if (e.key === 'Escape') {
|
|
110
|
+
e.preventDefault();
|
|
111
|
+
onClose();
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// Prevent any other key events from reaching the game
|
|
115
|
+
e.preventDefault();
|
|
116
|
+
e.stopPropagation();
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
document.addEventListener('keydown', handleKeyDown, true);
|
|
120
|
+
return () => {
|
|
121
|
+
document.removeEventListener('keydown', handleKeyDown, true);
|
|
122
|
+
};
|
|
123
|
+
}, [onClose]);
|
|
124
|
+
return (_jsxs("div", { ref: overlayRef, role: "dialog", "aria-modal": "true", "aria-label": title, className: styles.overlay, children: [_jsxs("div", { className: styles.overlayHeader, children: [_jsx("span", { className: styles.overlayTitle, children: title }), _jsx(TopbarIconButton, { ref: closeButtonRef, onClick: onClose, ariaLabel: "Close", children: "\u00D7" })] }), _jsx("div", { className: styles.overlayBody, children: children })] }));
|
|
125
|
+
}
|
|
126
|
+
function Stat({ stat }) {
|
|
127
|
+
return (_jsxs("div", { className: styles.stat, children: [_jsx("div", { className: `${styles.statValue} ${stat.accent === true ? styles.statAccent : ''}`, children: stat.value }), _jsx("div", { className: styles.statLabel, children: stat.label })] }));
|
|
182
128
|
}
|
|
183
|
-
`;
|
|
184
129
|
//# sourceMappingURL=GameTopbar.js.map
|
package/dist/GameTopbar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GameTopbar.js","sourceRoot":"","sources":["../src/GameTopbar.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"GameTopbar.js","sourceRoot":"","sources":["../src/GameTopbar.tsx"],"names":[],"mappings":"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"}
|