@freegamestore/games 0.18.0 → 0.19.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 +51 -6
- package/dist/Confetti.d.ts +4 -6
- package/dist/Confetti.d.ts.map +1 -1
- package/dist/Confetti.js +16 -49
- package/dist/Confetti.js.map +1 -1
- package/dist/GameAuth.d.ts.map +1 -1
- package/dist/GameAuth.js +5 -87
- package/dist/GameAuth.js.map +1 -1
- package/dist/GameButton.d.ts +2 -1
- package/dist/GameButton.d.ts.map +1 -1
- package/dist/GameButton.js +16 -67
- package/dist/GameButton.js.map +1 -1
- package/dist/GameConfirm.d.ts.map +1 -1
- package/dist/GameConfirm.js +1 -7
- package/dist/GameConfirm.js.map +1 -1
- package/dist/GameModal.d.ts +2 -1
- package/dist/GameModal.d.ts.map +1 -1
- package/dist/GameModal.js +3 -40
- package/dist/GameModal.js.map +1 -1
- package/dist/GameOverScreen.d.ts +2 -1
- package/dist/GameOverScreen.d.ts.map +1 -1
- package/dist/GameOverScreen.js +3 -37
- package/dist/GameOverScreen.js.map +1 -1
- package/dist/GameResultScreen.d.ts +3 -8
- package/dist/GameResultScreen.d.ts.map +1 -1
- package/dist/GameResultScreen.js +8 -140
- package/dist/GameResultScreen.js.map +1 -1
- package/dist/GameShell.d.ts +3 -0
- package/dist/GameShell.d.ts.map +1 -1
- package/dist/GameShell.js +4 -43
- package/dist/GameShell.js.map +1 -1
- package/dist/GameTextSizeToggle.d.ts.map +1 -1
- package/dist/GameTextSizeToggle.js +1 -16
- package/dist/GameTextSizeToggle.js.map +1 -1
- package/dist/GameThemeToggle.d.ts.map +1 -1
- package/dist/GameThemeToggle.js +1 -14
- package/dist/GameThemeToggle.js.map +1 -1
- package/dist/Leaderboard.d.ts.map +1 -1
- package/dist/Leaderboard.js +2 -5
- package/dist/Leaderboard.js.map +1 -1
- package/dist/StartScreen.d.ts +3 -10
- package/dist/StartScreen.d.ts.map +1 -1
- package/dist/StartScreen.js +7 -136
- package/dist/StartScreen.js.map +1 -1
- package/dist/feel/ScorePopup.d.ts +0 -5
- package/dist/feel/ScorePopup.d.ts.map +1 -1
- package/dist/feel/ScorePopup.js +4 -20
- package/dist/feel/ScorePopup.js.map +1 -1
- package/dist/feel/index.d.ts +1 -1
- package/dist/feel/index.d.ts.map +1 -1
- package/dist/feel/index.js +1 -1
- package/dist/feel/index.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/theme.css +93 -0
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Shared React UI primitives for games on **freegamestore.online**. Brand-consistent layout, scroll-free viewport lock, touch-friendly controls, and synthesized sound effects.
|
|
4
4
|
|
|
5
|
-
**Version:** 0.
|
|
5
|
+
**Version:** 0.19.0
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
@@ -14,6 +14,50 @@ pnpm add @freegamestore/games
|
|
|
14
14
|
|
|
15
15
|
Peer dependency: React 19+.
|
|
16
16
|
|
|
17
|
+
## Styling (Tailwind 4 on tokens)
|
|
18
|
+
|
|
19
|
+
The components are styled with **Tailwind utilities on the platform tokens**
|
|
20
|
+
([ADR-001](https://github.com/freegamestore-online/platform/blob/main/docs/adr/001-tailwind-on-fgs-tokens.md)).
|
|
21
|
+
The package ships class names, not CSS, so **your game compiles them**. In the
|
|
22
|
+
game's `web/src/index.css`, directly after `@import "tailwindcss"`:
|
|
23
|
+
|
|
24
|
+
```css
|
|
25
|
+
@import "tailwindcss";
|
|
26
|
+
@import "@freegamestore/games/theme.css";
|
|
27
|
+
@source "../node_modules/@freegamestore/games/dist";
|
|
28
|
+
|
|
29
|
+
@theme inline {
|
|
30
|
+
--color-paper: var(--paper);
|
|
31
|
+
--color-panel: var(--panel);
|
|
32
|
+
--color-ink: var(--ink);
|
|
33
|
+
--color-muted: var(--muted);
|
|
34
|
+
--color-line: var(--line);
|
|
35
|
+
--color-accent: var(--accent);
|
|
36
|
+
--color-danger: var(--danger);
|
|
37
|
+
--font-display: "Fraunces", serif;
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- `@source` makes Tailwind scan this package's `dist` for the classes the
|
|
42
|
+
components use. Without it the SDK renders unstyled.
|
|
43
|
+
- `theme.css` adds what the components need beyond the token mapping: the
|
|
44
|
+
`animate-fgs-*` animations and their keyframes (it replaces the CSS the
|
|
45
|
+
components used to inject), `accent-ink`, `accent-soft` and the `fgs` radius
|
|
46
|
+
and text sizes. Durations and easings read the `--motion-*` tokens.
|
|
47
|
+
- The `@theme inline` block is the token mapping every `template-game-*` carries.
|
|
48
|
+
A game on the templates already has it.
|
|
49
|
+
- Floating UI (`GameModal`, `GameConfirm`, `StartScreen`, `GameResultScreen`)
|
|
50
|
+
sits on the opaque `bg-panel` surface. Only the scrim behind it is translucent.
|
|
51
|
+
- Nothing is injected at runtime. The `*_CSS` strings (`CONFETTI_CSS`,
|
|
52
|
+
`SCORE_POP_CSS`, `RESULT_SCREEN_CSS`, `START_SCREEN_CSS`) are removed in 0.19.0;
|
|
53
|
+
`GAME_TOKENS_CSS` stays as the documented token helper.
|
|
54
|
+
- Inline `style` remains only for values computed at runtime (confetti piece
|
|
55
|
+
positions, score-popup coordinates, stagger indexes), each marked
|
|
56
|
+
`// Dynamic: …`. `src/styling.test.ts` fails on anything else.
|
|
57
|
+
- Hooks for tests and overrides are `data-fgs="…"` attributes
|
|
58
|
+
(`result`, `confetti`, `start`, `start-artwork`, `score-popup`). The old
|
|
59
|
+
`fgs-*` class names are gone.
|
|
60
|
+
|
|
17
61
|
## Quick Start
|
|
18
62
|
|
|
19
63
|
```tsx
|
|
@@ -186,11 +230,12 @@ An animated result screen for a finished level or game. A win shows falling conf
|
|
|
186
230
|
| `action` | `{ label, onClick }` | The primary button. It is focused when the screen opens |
|
|
187
231
|
| `children` | `ReactNode?` | Extra content between the badge and the action |
|
|
188
232
|
|
|
189
|
-
The screen covers the viewport and has `role="dialog"`. Motion is
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
233
|
+
The screen covers the viewport and has `role="dialog"`. Motion is the
|
|
234
|
+
`animate-fgs-*` utilities from `theme.css` (see [Styling](#styling-tailwind-4-on-tokens)),
|
|
235
|
+
which stop under `prefers-reduced-motion`, and the confetti is hidden for players
|
|
236
|
+
who ask for less motion. Its colours come from the platform tokens and its
|
|
237
|
+
durations from the `--motion-*` tokens in [TOKENS.md](./TOKENS.md), with the
|
|
238
|
+
light-theme fallbacks in `theme.css`.
|
|
194
239
|
|
|
195
240
|
`Confetti` is exported on its own, for a game that wants the celebration
|
|
196
241
|
somewhere else.
|
package/dist/Confetti.d.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
import type * as React from 'react';
|
|
2
2
|
/** The default palette: the four status-and-accent colours, following the theme. */
|
|
3
3
|
export declare const CONFETTI_COLOURS: readonly string[];
|
|
4
|
-
/**
|
|
5
|
-
* Styles for the falling pieces. Each piece's duration and delay are set
|
|
6
|
-
* inline. Under prefers-reduced-motion the layer is hidden, because the
|
|
7
|
-
* falling pieces are decoration only.
|
|
8
|
-
*/
|
|
9
|
-
export declare const CONFETTI_CSS = "\n.fgs-confetti {\n position: absolute;\n inset: 0;\n z-index: 0;\n pointer-events: none;\n overflow: hidden;\n}\n.fgs-confetti-piece {\n position: absolute;\n top: -12px;\n left: var(--x);\n width: 0.5rem;\n height: 0.8rem;\n border-radius: 2px;\n background: var(--colour);\n animation: fgs-confetti-fall var(--duration, 1.6s) cubic-bezier(0.3, 0, 0.7, 1) var(--delay, 0ms) both;\n}\n.fgs-confetti-piece:nth-child(3n) {\n width: 0.6rem;\n height: 0.6rem;\n border-radius: 999px;\n}\n@keyframes fgs-confetti-fall {\n from { transform: translate3d(0, 0, 0) rotate(0deg); opacity: 1; }\n 80% { opacity: 1; }\n to { transform: translate3d(var(--drift, 0px), 620px, 0) rotate(var(--spin, 360deg)); opacity: 0; }\n}\n@media (prefers-reduced-motion: reduce) {\n .fgs-confetti {\n display: none;\n }\n}\n";
|
|
10
4
|
export interface ConfettiProps {
|
|
11
5
|
/** Colours cycled across the pieces. Default: the accent and the status colours. */
|
|
12
6
|
colours?: readonly string[];
|
|
@@ -15,6 +9,10 @@ export interface ConfettiProps {
|
|
|
15
9
|
* Falling confetti for a win. Each piece's position, drift, spin and timing
|
|
16
10
|
* come from its index, so the render is the same every time. Renders nothing
|
|
17
11
|
* under prefers-reduced-motion.
|
|
12
|
+
*
|
|
13
|
+
* The falling motion is the `animate-fgs-confetti` utility from the SDK's
|
|
14
|
+
* `theme.css`. Only the per-piece values below are inline, because they are
|
|
15
|
+
* computed from the piece's index.
|
|
18
16
|
*/
|
|
19
17
|
export declare function Confetti({ colours }: ConfettiProps): React.JSX.Element | null;
|
|
20
18
|
//# sourceMappingURL=Confetti.d.ts.map
|
package/dist/Confetti.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Confetti.d.ts","sourceRoot":"","sources":["../src/Confetti.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AASpC,oFAAoF;AACpF,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EAK7C,CAAC;
|
|
1
|
+
{"version":3,"file":"Confetti.d.ts","sourceRoot":"","sources":["../src/Confetti.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AASpC,oFAAoF;AACpF,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EAK7C,CAAC;AASF,MAAM,WAAW,aAAa;IAC5B,oFAAoF;IACpF,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,EAAE,OAA0B,EAAE,EAAE,aAAa,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CA4BhG"}
|
package/dist/Confetti.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { LIGHT_COLOURS } from './tokens.js';
|
|
3
3
|
/** Number of falling pieces. */
|
|
4
4
|
const PIECES = 30;
|
|
@@ -9,47 +9,8 @@ export const CONFETTI_COLOURS = [
|
|
|
9
9
|
v('accent', LIGHT_COLOURS.accent),
|
|
10
10
|
v('success', LIGHT_COLOURS.success),
|
|
11
11
|
v('warning', LIGHT_COLOURS.warning),
|
|
12
|
-
v('
|
|
12
|
+
v('danger', LIGHT_COLOURS.error),
|
|
13
13
|
];
|
|
14
|
-
/**
|
|
15
|
-
* Styles for the falling pieces. Each piece's duration and delay are set
|
|
16
|
-
* inline. Under prefers-reduced-motion the layer is hidden, because the
|
|
17
|
-
* falling pieces are decoration only.
|
|
18
|
-
*/
|
|
19
|
-
export const CONFETTI_CSS = `
|
|
20
|
-
.fgs-confetti {
|
|
21
|
-
position: absolute;
|
|
22
|
-
inset: 0;
|
|
23
|
-
z-index: 0;
|
|
24
|
-
pointer-events: none;
|
|
25
|
-
overflow: hidden;
|
|
26
|
-
}
|
|
27
|
-
.fgs-confetti-piece {
|
|
28
|
-
position: absolute;
|
|
29
|
-
top: -12px;
|
|
30
|
-
left: var(--x);
|
|
31
|
-
width: 0.5rem;
|
|
32
|
-
height: 0.8rem;
|
|
33
|
-
border-radius: 2px;
|
|
34
|
-
background: var(--colour);
|
|
35
|
-
animation: fgs-confetti-fall var(--duration, 1.6s) cubic-bezier(0.3, 0, 0.7, 1) var(--delay, 0ms) both;
|
|
36
|
-
}
|
|
37
|
-
.fgs-confetti-piece:nth-child(3n) {
|
|
38
|
-
width: 0.6rem;
|
|
39
|
-
height: 0.6rem;
|
|
40
|
-
border-radius: 999px;
|
|
41
|
-
}
|
|
42
|
-
@keyframes fgs-confetti-fall {
|
|
43
|
-
from { transform: translate3d(0, 0, 0) rotate(0deg); opacity: 1; }
|
|
44
|
-
80% { opacity: 1; }
|
|
45
|
-
to { transform: translate3d(var(--drift, 0px), 620px, 0) rotate(var(--spin, 360deg)); opacity: 0; }
|
|
46
|
-
}
|
|
47
|
-
@media (prefers-reduced-motion: reduce) {
|
|
48
|
-
.fgs-confetti {
|
|
49
|
-
display: none;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
`;
|
|
53
14
|
/** True when the player has asked for less motion. False on the server, where there is no window. */
|
|
54
15
|
function prefersReducedMotion() {
|
|
55
16
|
return typeof window !== 'undefined' && typeof window.matchMedia === 'function'
|
|
@@ -60,17 +21,23 @@ function prefersReducedMotion() {
|
|
|
60
21
|
* Falling confetti for a win. Each piece's position, drift, spin and timing
|
|
61
22
|
* come from its index, so the render is the same every time. Renders nothing
|
|
62
23
|
* under prefers-reduced-motion.
|
|
24
|
+
*
|
|
25
|
+
* The falling motion is the `animate-fgs-confetti` utility from the SDK's
|
|
26
|
+
* `theme.css`. Only the per-piece values below are inline, because they are
|
|
27
|
+
* computed from the piece's index.
|
|
63
28
|
*/
|
|
64
29
|
export function Confetti({ colours = CONFETTI_COLOURS }) {
|
|
65
30
|
if (prefersReducedMotion())
|
|
66
31
|
return null;
|
|
67
|
-
return (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
32
|
+
return (_jsx("div", { "data-fgs": "confetti", className: "pointer-events-none absolute inset-0 z-0 overflow-hidden motion-reduce:hidden", "aria-hidden": "true", children: Array.from({ length: PIECES }, (_, i) => (_jsx("span", { "data-fgs": "confetti-piece", className: "absolute -top-3 left-(--x) h-[0.8rem] w-2 animate-fgs-confetti rounded-[2px] bg-(--colour) nth-[3n]:size-[0.6rem] nth-[3n]:rounded-full",
|
|
33
|
+
// Dynamic: position, drift, spin, timing and colour all come from the piece index.
|
|
34
|
+
style: {
|
|
35
|
+
'--x': `${(i * 37) % 100}%`,
|
|
36
|
+
'--drift': `${((i * 53) % 41) - 20}px`,
|
|
37
|
+
'--spin': `${((i * 97) % 720) - 360}deg`,
|
|
38
|
+
'--delay': `${(i % 7) * 70}ms`,
|
|
39
|
+
'--duration': `${1500 + (i % 5) * 200}ms`,
|
|
40
|
+
'--colour': colours[i % colours.length],
|
|
41
|
+
} }, i))) }));
|
|
75
42
|
}
|
|
76
43
|
//# sourceMappingURL=Confetti.js.map
|
package/dist/Confetti.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Confetti.js","sourceRoot":"","sources":["../src/Confetti.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,gCAAgC;AAChC,MAAM,MAAM,GAAG,EAAE,CAAC;AAElB,uEAAuE;AACvE,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,QAAgB,EAAE,EAAE,CAAC,SAAS,IAAI,KAAK,QAAQ,GAAG,CAAC;AAE5E,oFAAoF;AACpF,MAAM,CAAC,MAAM,gBAAgB,GAAsB;IACjD,CAAC,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC;IACjC,CAAC,CAAC,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC;IACnC,CAAC,CAAC,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC;IACnC,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"Confetti.js","sourceRoot":"","sources":["../src/Confetti.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,gCAAgC;AAChC,MAAM,MAAM,GAAG,EAAE,CAAC;AAElB,uEAAuE;AACvE,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,QAAgB,EAAE,EAAE,CAAC,SAAS,IAAI,KAAK,QAAQ,GAAG,CAAC;AAE5E,oFAAoF;AACpF,MAAM,CAAC,MAAM,gBAAgB,GAAsB;IACjD,CAAC,CAAC,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC;IACjC,CAAC,CAAC,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC;IACnC,CAAC,CAAC,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC;IACnC,CAAC,CAAC,QAAQ,EAAE,aAAa,CAAC,KAAK,CAAC;CACjC,CAAC;AAEF,qGAAqG;AACrG,SAAS,oBAAoB;IAC3B,OAAO,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,UAAU;QAC7E,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,CAAC,OAAO;QAC/D,CAAC,CAAC,KAAK,CAAC;AACZ,CAAC;AAOD;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAE,OAAO,GAAG,gBAAgB,EAAiB;IACpE,IAAI,oBAAoB,EAAE;QAAE,OAAO,IAAI,CAAC;IACxC,OAAO,CACL,0BACW,UAAU,EACnB,SAAS,EAAC,+EAA+E,iBAC7E,MAAM,YAEjB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CACxC,2BAEW,gBAAgB,EACzB,SAAS,EAAC,yIAAyI;YACnJ,mFAAmF;YACnF,KAAK,EACH;gBACE,KAAK,EAAE,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,GAAG,GAAG;gBAC3B,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,IAAI;gBACtC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,KAAK;gBACxC,SAAS,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI;gBAC9B,YAAY,EAAE,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,IAAI;gBACzC,UAAU,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;aACjB,IAZrB,CAAC,CAcN,CACH,CAAC,GACE,CACP,CAAC;AACJ,CAAC"}
|
package/dist/GameAuth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GameAuth.d.ts","sourceRoot":"","sources":["../src/GameAuth.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"GameAuth.d.ts","sourceRoot":"","sources":["../src/GameAuth.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAQpC;;;;;;GAMG;AACH,wBAAgB,QAAQ,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,CAsE5C"}
|
package/dist/GameAuth.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef, useState } from 'react';
|
|
3
3
|
import { useAuth } from './useAuth.js';
|
|
4
|
+
/** Shared by the sign-in and avatar buttons: bare, 44px minimum touch target. */
|
|
5
|
+
const BARE_BUTTON = 'm-0 inline-flex min-h-11 min-w-11 cursor-pointer touch-manipulation items-center justify-center border-0 bg-transparent p-0 [-webkit-tap-highlight-color:transparent]';
|
|
4
6
|
/**
|
|
5
7
|
* Sign-in / avatar widget for the GameTopbar `actions` slot.
|
|
6
8
|
*
|
|
@@ -27,100 +29,16 @@ export function GameAuth() {
|
|
|
27
29
|
if (loading)
|
|
28
30
|
return _jsx("div", {});
|
|
29
31
|
if (user === null) {
|
|
30
|
-
return (_jsx("button", { onClick: signIn,
|
|
31
|
-
background: 'none',
|
|
32
|
-
border: 'none',
|
|
33
|
-
cursor: 'pointer',
|
|
34
|
-
fontFamily: '"Manrope", system-ui, sans-serif',
|
|
35
|
-
fontSize: '0.7rem',
|
|
36
|
-
fontWeight: 600,
|
|
37
|
-
color: 'var(--muted, #6b7280)',
|
|
38
|
-
padding: 0,
|
|
39
|
-
margin: 0,
|
|
40
|
-
// 44px minimum touch target
|
|
41
|
-
minWidth: '44px',
|
|
42
|
-
minHeight: '44px',
|
|
43
|
-
display: 'inline-flex',
|
|
44
|
-
alignItems: 'center',
|
|
45
|
-
justifyContent: 'center',
|
|
46
|
-
WebkitTapHighlightColor: 'transparent',
|
|
47
|
-
touchAction: 'manipulation',
|
|
48
|
-
}, children: "Sign in" }));
|
|
32
|
+
return (_jsx("button", { onClick: signIn, className: `${BARE_BUTTON} text-[0.7rem] font-semibold text-muted`, children: "Sign in" }));
|
|
49
33
|
}
|
|
50
34
|
const firstName = user.name.split(' ')[0] ?? user.name;
|
|
51
35
|
// Google accounts without a profile picture have an empty avatar URL;
|
|
52
36
|
// render an initial-letter circle instead of a broken <img>.
|
|
53
37
|
const avatarUrl = user.avatar?.trim();
|
|
54
38
|
const initial = (firstName.charAt(0) || '?').toUpperCase();
|
|
55
|
-
return (_jsxs("div", { ref: ref,
|
|
56
|
-
background: 'none',
|
|
57
|
-
border: 'none',
|
|
58
|
-
cursor: 'pointer',
|
|
59
|
-
display: 'inline-flex',
|
|
60
|
-
alignItems: 'center',
|
|
61
|
-
gap: '0.35rem',
|
|
62
|
-
padding: 0,
|
|
63
|
-
margin: 0,
|
|
64
|
-
minWidth: '44px',
|
|
65
|
-
minHeight: '44px',
|
|
66
|
-
justifyContent: 'center',
|
|
67
|
-
WebkitTapHighlightColor: 'transparent',
|
|
68
|
-
touchAction: 'manipulation',
|
|
69
|
-
}, children: [avatarUrl ? (_jsx("img", { src: avatarUrl, alt: "", width: 24, height: 24, style: {
|
|
70
|
-
width: '24px',
|
|
71
|
-
height: '24px',
|
|
72
|
-
borderRadius: '50%',
|
|
73
|
-
objectFit: 'cover',
|
|
74
|
-
flexShrink: 0,
|
|
75
|
-
} })) : (_jsx("span", { "aria-hidden": "true", style: {
|
|
76
|
-
width: '24px',
|
|
77
|
-
height: '24px',
|
|
78
|
-
borderRadius: '50%',
|
|
79
|
-
flexShrink: 0,
|
|
80
|
-
display: 'inline-flex',
|
|
81
|
-
alignItems: 'center',
|
|
82
|
-
justifyContent: 'center',
|
|
83
|
-
background: 'var(--accent, #6b7280)',
|
|
84
|
-
color: '#fff',
|
|
85
|
-
fontFamily: '"Manrope", system-ui, sans-serif',
|
|
86
|
-
fontSize: '0.65rem',
|
|
87
|
-
fontWeight: 700,
|
|
88
|
-
lineHeight: 1,
|
|
89
|
-
}, children: initial })), _jsx("span", { style: {
|
|
90
|
-
fontFamily: '"Manrope", system-ui, sans-serif',
|
|
91
|
-
fontSize: '0.7rem',
|
|
92
|
-
fontWeight: 600,
|
|
93
|
-
color: 'var(--ink, #1a1a1a)',
|
|
94
|
-
whiteSpace: 'nowrap',
|
|
95
|
-
}, children: firstName })] }), open && (_jsx("div", { style: {
|
|
96
|
-
position: 'absolute',
|
|
97
|
-
top: '100%',
|
|
98
|
-
right: 0,
|
|
99
|
-
marginTop: '0.25rem',
|
|
100
|
-
background: 'var(--panel, #fff)',
|
|
101
|
-
border: '1px solid var(--line, #e5e5e5)',
|
|
102
|
-
borderRadius: '0.5rem',
|
|
103
|
-
boxShadow: '0 4px 12px rgba(0,0,0,0.1)',
|
|
104
|
-
zIndex: 100,
|
|
105
|
-
minWidth: '7rem',
|
|
106
|
-
}, children: _jsx("button", { onClick: () => {
|
|
39
|
+
return (_jsxs("div", { ref: ref, className: "relative", children: [_jsxs("button", { onClick: () => setOpen((v) => !v), className: `${BARE_BUTTON} gap-[0.35rem]`, children: [avatarUrl ? (_jsx("img", { src: avatarUrl, alt: "", width: 24, height: 24, className: "size-6 shrink-0 rounded-full object-cover" })) : (_jsx("span", { "aria-hidden": "true", className: "inline-flex size-6 shrink-0 items-center justify-center rounded-full bg-accent text-[0.65rem] font-bold leading-none text-white", children: initial })), _jsx("span", { className: "whitespace-nowrap text-[0.7rem] font-semibold text-ink", children: firstName })] }), open && (_jsx("div", { className: "absolute right-0 top-full z-[100] mt-1 min-w-28 rounded-lg border border-line bg-panel shadow-[0_4px_12px_rgb(0_0_0/0.1)]", children: _jsx("button", { onClick: () => {
|
|
107
40
|
setOpen(false);
|
|
108
41
|
signOut();
|
|
109
|
-
},
|
|
110
|
-
display: 'flex',
|
|
111
|
-
alignItems: 'center',
|
|
112
|
-
width: '100%',
|
|
113
|
-
background: 'none',
|
|
114
|
-
border: 'none',
|
|
115
|
-
cursor: 'pointer',
|
|
116
|
-
fontFamily: '"Manrope", system-ui, sans-serif',
|
|
117
|
-
fontSize: '0.7rem',
|
|
118
|
-
fontWeight: 600,
|
|
119
|
-
color: 'var(--ink, #1a1a1a)',
|
|
120
|
-
padding: '0.5rem 0.75rem',
|
|
121
|
-
minHeight: '44px',
|
|
122
|
-
WebkitTapHighlightColor: 'transparent',
|
|
123
|
-
touchAction: 'manipulation',
|
|
124
|
-
}, children: "Sign out" }) }))] }));
|
|
42
|
+
}, className: "flex min-h-11 w-full cursor-pointer touch-manipulation items-center border-0 bg-transparent px-3 py-2 text-[0.7rem] font-semibold text-ink [-webkit-tap-highlight-color:transparent]", children: "Sign out" }) }))] }));
|
|
125
43
|
}
|
|
126
44
|
//# sourceMappingURL=GameAuth.js.map
|
package/dist/GameAuth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GameAuth.js","sourceRoot":"","sources":["../src/GameAuth.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ;IACtB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;IACrD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAEzC,uCAAuC;IACvC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,MAAM,OAAO,GAAG,CAAC,CAAa,EAAE,EAAE;YAChC,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAc,CAAC,EAAE,CAAC;gBAC3D,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;QACH,CAAC,CAAC;QACF,QAAQ,CAAC,gBAAgB,CAAC,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QACxD,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC1E,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,IAAI,OAAO;QAAE,OAAO,eAAO,CAAC;IAE5B,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,CACL,
|
|
1
|
+
{"version":3,"file":"GameAuth.js","sourceRoot":"","sources":["../src/GameAuth.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,iFAAiF;AACjF,MAAM,WAAW,GACf,uKAAuK,CAAC;AAE1K;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ;IACtB,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC;IACrD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAEzC,uCAAuC;IACvC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,MAAM,OAAO,GAAG,CAAC,CAAa,EAAE,EAAE;YAChC,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAc,CAAC,EAAE,CAAC;gBAC3D,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;QACH,CAAC,CAAC;QACF,QAAQ,CAAC,gBAAgB,CAAC,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QACxD,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IAC1E,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,IAAI,OAAO;QAAE,OAAO,eAAO,CAAC;IAE5B,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,CACL,iBAAQ,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,WAAW,yCAAyC,wBAElF,CACV,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC;IACvD,sEAAsE;IACtE,6DAA6D;IAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAE3D,OAAO,CACL,eAAK,GAAG,EAAE,GAAG,EAAE,SAAS,EAAC,UAAU,aACjC,kBAAQ,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,WAAW,gBAAgB,aACjF,SAAS,CAAC,CAAC,CAAC,CACX,cACE,GAAG,EAAE,SAAS,EACd,GAAG,EAAC,EAAE,EACN,KAAK,EAAE,EAAE,EACT,MAAM,EAAE,EAAE,EACV,SAAS,EAAC,2CAA2C,GACrD,CACH,CAAC,CAAC,CAAC,CACF,8BACc,MAAM,EAClB,SAAS,EAAC,iIAAiI,YAE1I,OAAO,GACH,CACR,EACD,eAAM,SAAS,EAAC,wDAAwD,YAAE,SAAS,GAAQ,IACpF,EAER,IAAI,IAAI,CACP,cAAK,SAAS,EAAC,2HAA2H,YACxI,iBACE,OAAO,EAAE,GAAG,EAAE;wBACZ,OAAO,CAAC,KAAK,CAAC,CAAC;wBACf,OAAO,EAAE,CAAC;oBACZ,CAAC,EACD,SAAS,EAAC,sLAAsL,yBAGzL,GACL,CACP,IACG,CACP,CAAC;AACJ,CAAC"}
|
package/dist/GameButton.d.ts
CHANGED
|
@@ -15,7 +15,8 @@ export interface GameButtonProps {
|
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* Prescribed game button. Touch-friendly (min 44px target), brand-consistent
|
|
18
|
-
* styling.
|
|
18
|
+
* styling. Four variants, three sizes — all opinionated, nothing custom.
|
|
19
|
+
* Utilities on the platform tokens; the press feedback is `active:scale`.
|
|
19
20
|
*/
|
|
20
21
|
export declare function GameButton({ children, variant, size, onClick, disabled, block, }: GameButtonProps): React.JSX.Element;
|
|
21
22
|
//# sourceMappingURL=GameButton.d.ts.map
|
package/dist/GameButton.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GameButton.d.ts","sourceRoot":"","sources":["../src/GameButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AAC7E,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,SAAS,CAAC;IACpB,wCAAwC;IACxC,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,yEAAyE;IACzE,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"GameButton.d.ts","sourceRoot":"","sources":["../src/GameButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAC;AAC7E,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,SAAS,CAAC;IACpB,wCAAwC;IACxC,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,yEAAyE;IACzE,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kBAAkB;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAeD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,OAAmB,EACnB,IAAW,EACX,OAAO,EACP,QAAgB,EAChB,KAAa,GACd,EAAE,eAAe,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAerC"}
|
package/dist/GameButton.js
CHANGED
|
@@ -1,76 +1,25 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
const SIZE = {
|
|
3
|
-
sm:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
fontSize: '0.9rem',
|
|
13
|
-
borderRadius: '0.75rem',
|
|
14
|
-
},
|
|
15
|
-
lg: {
|
|
16
|
-
minHeight: '3.5rem',
|
|
17
|
-
padding: '0.75rem 1.75rem',
|
|
18
|
-
fontSize: '1rem',
|
|
19
|
-
borderRadius: '0.875rem',
|
|
20
|
-
},
|
|
3
|
+
sm: 'min-h-11 px-4 py-2 text-[0.85rem] rounded-[0.625rem]',
|
|
4
|
+
md: 'min-h-12 px-5 py-[0.625rem] text-[0.9rem] rounded-xl',
|
|
5
|
+
lg: 'min-h-14 px-7 py-3 text-base rounded-[0.875rem]',
|
|
6
|
+
};
|
|
7
|
+
const VARIANT = {
|
|
8
|
+
primary: 'bg-accent text-white',
|
|
9
|
+
secondary: 'bg-panel text-ink ring-1 ring-inset ring-line',
|
|
10
|
+
ghost: 'bg-transparent text-muted',
|
|
11
|
+
danger: 'bg-danger text-white',
|
|
21
12
|
};
|
|
22
13
|
/**
|
|
23
14
|
* Prescribed game button. Touch-friendly (min 44px target), brand-consistent
|
|
24
|
-
* styling.
|
|
15
|
+
* styling. Four variants, three sizes — all opinionated, nothing custom.
|
|
16
|
+
* Utilities on the platform tokens; the press feedback is `active:scale`.
|
|
25
17
|
*/
|
|
26
18
|
export function GameButton({ children, variant = 'primary', size = 'md', onClick, disabled = false, block = false, }) {
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
justifyContent: 'center',
|
|
33
|
-
gap: '0.5rem',
|
|
34
|
-
minHeight: s.minHeight,
|
|
35
|
-
padding: s.padding,
|
|
36
|
-
fontSize: s.fontSize,
|
|
37
|
-
fontFamily: '"Manrope", system-ui, sans-serif',
|
|
38
|
-
fontWeight: 700,
|
|
39
|
-
lineHeight: 1,
|
|
40
|
-
borderRadius: s.borderRadius,
|
|
41
|
-
border: 'none',
|
|
42
|
-
cursor: disabled ? 'default' : 'pointer',
|
|
43
|
-
opacity: disabled ? 0.4 : 1,
|
|
44
|
-
transition: 'transform 120ms ease, opacity 120ms ease',
|
|
45
|
-
WebkitTapHighlightColor: 'transparent',
|
|
46
|
-
touchAction: 'manipulation',
|
|
47
|
-
};
|
|
48
|
-
const variantStyles = {
|
|
49
|
-
primary: {
|
|
50
|
-
background: 'var(--accent, #10b981)',
|
|
51
|
-
color: '#fff',
|
|
52
|
-
},
|
|
53
|
-
secondary: {
|
|
54
|
-
background: 'var(--panel, #f5f3f0)',
|
|
55
|
-
color: 'var(--ink, #1a1a1a)',
|
|
56
|
-
boxShadow: 'inset 0 0 0 1px var(--line, #e5e5e5)',
|
|
57
|
-
},
|
|
58
|
-
ghost: {
|
|
59
|
-
background: 'transparent',
|
|
60
|
-
color: 'var(--muted, #6b7280)',
|
|
61
|
-
},
|
|
62
|
-
danger: {
|
|
63
|
-
background: '#dc2626',
|
|
64
|
-
color: '#ffffff',
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
return (_jsx("button", { style: { ...base, ...variantStyles[variant] }, onClick: disabled ? undefined : onClick, disabled: disabled, onPointerDown: (e) => {
|
|
68
|
-
if (!disabled)
|
|
69
|
-
e.currentTarget.style.transform = 'scale(0.96)';
|
|
70
|
-
}, onPointerUp: (e) => {
|
|
71
|
-
e.currentTarget.style.transform = '';
|
|
72
|
-
}, onPointerLeave: (e) => {
|
|
73
|
-
e.currentTarget.style.transform = '';
|
|
74
|
-
}, children: children }));
|
|
19
|
+
const layout = block ? 'flex w-full' : 'inline-flex';
|
|
20
|
+
const state = disabled
|
|
21
|
+
? 'cursor-default opacity-40'
|
|
22
|
+
: 'cursor-pointer enabled:active:scale-[0.96]';
|
|
23
|
+
return (_jsx("button", { className: `${layout} ${SIZE[size]} ${VARIANT[variant]} ${state} touch-manipulation items-center justify-center gap-2 border-0 font-bold leading-none transition-[transform,opacity] duration-[120ms] [-webkit-tap-highlight-color:transparent]`, onClick: disabled ? undefined : onClick, disabled: disabled, children: children }));
|
|
75
24
|
}
|
|
76
25
|
//# sourceMappingURL=GameButton.js.map
|
package/dist/GameButton.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GameButton.js","sourceRoot":"","sources":["../src/GameButton.tsx"],"names":[],"mappings":";AAkBA,MAAM,IAAI,
|
|
1
|
+
{"version":3,"file":"GameButton.js","sourceRoot":"","sources":["../src/GameButton.tsx"],"names":[],"mappings":";AAkBA,MAAM,IAAI,GAAmC;IAC3C,EAAE,EAAE,sDAAsD;IAC1D,EAAE,EAAE,sDAAsD;IAC1D,EAAE,EAAE,iDAAiD;CACtD,CAAC;AAEF,MAAM,OAAO,GAAsC;IACjD,OAAO,EAAE,sBAAsB;IAC/B,SAAS,EAAE,+CAA+C;IAC1D,KAAK,EAAE,2BAA2B;IAClC,MAAM,EAAE,sBAAsB;CAC/B,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,QAAQ,EACR,OAAO,GAAG,SAAS,EACnB,IAAI,GAAG,IAAI,EACX,OAAO,EACP,QAAQ,GAAG,KAAK,EAChB,KAAK,GAAG,KAAK,GACG;IAChB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC;IACrD,MAAM,KAAK,GAAG,QAAQ;QACpB,CAAC,CAAC,2BAA2B;QAC7B,CAAC,CAAC,4CAA4C,CAAC;IAEjD,OAAO,CACL,iBACE,SAAS,EAAE,GAAG,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,KAAK,iLAAiL,EAChP,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,EACvC,QAAQ,EAAE,QAAQ,YAEjB,QAAQ,GACF,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GameConfirm.d.ts","sourceRoot":"","sources":["../src/GameConfirm.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,KAAK,EACL,OAAO,EACP,YAAwB,EACxB,WAAsB,EACtB,SAAS,EACT,QAAQ,EACR,OAAmB,GACpB,EAAE,gBAAgB,+
|
|
1
|
+
{"version":3,"file":"GameConfirm.d.ts","sourceRoot":"","sources":["../src/GameConfirm.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,KAAK,EACL,OAAO,EACP,YAAwB,EACxB,WAAsB,EACtB,SAAS,EACT,QAAQ,EACR,OAAmB,GACpB,EAAE,gBAAgB,+BAkBlB"}
|
package/dist/GameConfirm.js
CHANGED
|
@@ -6,12 +6,6 @@ import { GameModal } from './GameModal.js';
|
|
|
6
6
|
* Use for: quit game, restart, delete save, etc.
|
|
7
7
|
*/
|
|
8
8
|
export function GameConfirm({ open, title, message, confirmLabel = 'Confirm', cancelLabel = 'Cancel', onConfirm, onCancel, variant = 'default', }) {
|
|
9
|
-
return (_jsxs(GameModal, { open: open, onClose: onCancel, title: title, children: [_jsx("p", {
|
|
10
|
-
fontSize: '0.9rem',
|
|
11
|
-
color: 'var(--muted, #64748b)',
|
|
12
|
-
margin: '0 0 1.25rem',
|
|
13
|
-
lineHeight: 1.5,
|
|
14
|
-
fontFamily: '"Manrope", system-ui, sans-serif',
|
|
15
|
-
}, children: message }), _jsxs("div", { style: { display: 'flex', gap: '0.5rem', justifyContent: 'flex-end' }, children: [_jsx(GameButton, { onClick: onCancel, variant: "secondary", size: "md", children: cancelLabel }), _jsx(GameButton, { onClick: onConfirm, variant: variant === 'danger' ? 'danger' : 'primary', size: "md", children: confirmLabel })] })] }));
|
|
9
|
+
return (_jsxs(GameModal, { open: open, onClose: onCancel, title: title, children: [_jsx("p", { className: "m-0 mb-5 text-[0.9rem] leading-normal text-muted", children: message }), _jsxs("div", { className: "flex justify-end gap-2", children: [_jsx(GameButton, { onClick: onCancel, variant: "secondary", size: "md", children: cancelLabel }), _jsx(GameButton, { onClick: onConfirm, variant: variant === 'danger' ? 'danger' : 'primary', size: "md", children: confirmLabel })] })] }));
|
|
16
10
|
}
|
|
17
11
|
//# sourceMappingURL=GameConfirm.js.map
|
package/dist/GameConfirm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GameConfirm.js","sourceRoot":"","sources":["../src/GameConfirm.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAa3C;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,IAAI,EACJ,KAAK,EACL,OAAO,EACP,YAAY,GAAG,SAAS,EACxB,WAAW,GAAG,QAAQ,EACtB,SAAS,EACT,QAAQ,EACR,OAAO,GAAG,SAAS,GACF;IACjB,OAAO,CACL,MAAC,SAAS,IAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,aACpD,
|
|
1
|
+
{"version":3,"file":"GameConfirm.js","sourceRoot":"","sources":["../src/GameConfirm.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAa3C;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,IAAI,EACJ,KAAK,EACL,OAAO,EACP,YAAY,GAAG,SAAS,EACxB,WAAW,GAAG,QAAQ,EACtB,SAAS,EACT,QAAQ,EACR,OAAO,GAAG,SAAS,GACF;IACjB,OAAO,CACL,MAAC,SAAS,IAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,aACpD,YAAG,SAAS,EAAC,kDAAkD,YAAE,OAAO,GAAK,EAC7E,eAAK,SAAS,EAAC,wBAAwB,aACrC,KAAC,UAAU,IAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,IAAI,YACzD,WAAW,GACD,EACb,KAAC,UAAU,IACT,OAAO,EAAE,SAAS,EAClB,OAAO,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EACpD,IAAI,EAAC,IAAI,YAER,YAAY,GACF,IACT,IACI,CACb,CAAC;AACJ,CAAC"}
|
package/dist/GameModal.d.ts
CHANGED
|
@@ -8,7 +8,8 @@ export interface GameModalProps {
|
|
|
8
8
|
/**
|
|
9
9
|
* Fullscreen modal overlay for games. Used for rules, settings, confirmations.
|
|
10
10
|
* Closes on backdrop click or Escape key.
|
|
11
|
-
* Styled with platform
|
|
11
|
+
* Styled with Tailwind utilities on the platform tokens. The dialog sits on an
|
|
12
|
+
* opaque surface (`bg-panel`); only the scrim behind it is translucent.
|
|
12
13
|
*/
|
|
13
14
|
export declare function GameModal({ open, onClose, title, children }: GameModalProps): import("react").JSX.Element | null;
|
|
14
15
|
//# sourceMappingURL=GameModal.d.ts.map
|
package/dist/GameModal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GameModal.d.ts","sourceRoot":"","sources":["../src/GameModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,OAAO,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED
|
|
1
|
+
{"version":3,"file":"GameModal.d.ts","sourceRoot":"","sources":["../src/GameModal.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,OAAO,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,cAAc,sCAqC3E"}
|
package/dist/GameModal.js
CHANGED
|
@@ -3,7 +3,8 @@ import { useEffect } from 'react';
|
|
|
3
3
|
/**
|
|
4
4
|
* Fullscreen modal overlay for games. Used for rules, settings, confirmations.
|
|
5
5
|
* Closes on backdrop click or Escape key.
|
|
6
|
-
* Styled with platform
|
|
6
|
+
* Styled with Tailwind utilities on the platform tokens. The dialog sits on an
|
|
7
|
+
* opaque surface (`bg-panel`); only the scrim behind it is translucent.
|
|
7
8
|
*/
|
|
8
9
|
export function GameModal({ open, onClose, title, children }) {
|
|
9
10
|
useEffect(() => {
|
|
@@ -18,44 +19,6 @@ export function GameModal({ open, onClose, title, children }) {
|
|
|
18
19
|
}, [open, onClose]);
|
|
19
20
|
if (!open)
|
|
20
21
|
return null;
|
|
21
|
-
return (_jsx("div", { onClick: onClose,
|
|
22
|
-
position: 'fixed',
|
|
23
|
-
inset: 0,
|
|
24
|
-
zIndex: 900,
|
|
25
|
-
background: 'rgba(0,0,0,0.6)',
|
|
26
|
-
backdropFilter: 'blur(4px)',
|
|
27
|
-
display: 'flex',
|
|
28
|
-
alignItems: 'center',
|
|
29
|
-
justifyContent: 'center',
|
|
30
|
-
padding: '1rem',
|
|
31
|
-
}, children: _jsxs("div", { onClick: (e) => e.stopPropagation(), style: {
|
|
32
|
-
background: 'var(--panel, #ffffff)',
|
|
33
|
-
border: '1px solid var(--line, #e2e8f0)',
|
|
34
|
-
borderRadius: '1rem',
|
|
35
|
-
maxWidth: 400,
|
|
36
|
-
width: '100%',
|
|
37
|
-
maxHeight: '80dvh',
|
|
38
|
-
overflow: 'auto',
|
|
39
|
-
}, children: [title && (_jsxs("div", { style: {
|
|
40
|
-
display: 'flex',
|
|
41
|
-
alignItems: 'center',
|
|
42
|
-
justifyContent: 'space-between',
|
|
43
|
-
padding: '0.85rem 1rem',
|
|
44
|
-
borderBottom: '1px solid var(--line, #e2e8f0)',
|
|
45
|
-
}, children: [_jsx("span", { style: {
|
|
46
|
-
fontWeight: 700,
|
|
47
|
-
fontSize: '1rem',
|
|
48
|
-
color: 'var(--ink, #1e293b)',
|
|
49
|
-
fontFamily: '"Manrope", system-ui, sans-serif',
|
|
50
|
-
}, children: title }), _jsx("button", { onClick: onClose, "aria-label": "Close", style: {
|
|
51
|
-
background: 'none',
|
|
52
|
-
border: 'none',
|
|
53
|
-
cursor: 'pointer',
|
|
54
|
-
fontSize: '1.25rem',
|
|
55
|
-
lineHeight: 1,
|
|
56
|
-
color: 'var(--muted, #64748b)',
|
|
57
|
-
padding: '0.25rem',
|
|
58
|
-
fontFamily: 'inherit',
|
|
59
|
-
}, children: "\u00D7" })] })), _jsx("div", { style: { padding: '1rem' }, children: children })] }) }));
|
|
22
|
+
return (_jsx("div", { onClick: onClose, className: "fixed inset-0 z-[900] flex items-center justify-center bg-black/60 p-4 backdrop-blur-xs", children: _jsxs("div", { onClick: (e) => e.stopPropagation(), className: "max-h-[80dvh] w-full max-w-[400px] overflow-auto rounded-2xl border border-line bg-panel", children: [title && (_jsxs("div", { className: "flex items-center justify-between border-b border-line px-4 py-[0.85rem]", children: [_jsx("span", { className: "text-base font-bold text-ink", children: title }), _jsx("button", { onClick: onClose, "aria-label": "Close", className: "cursor-pointer border-0 bg-transparent p-1 text-xl leading-none text-muted", children: "\u00D7" })] })), _jsx("div", { className: "p-4", children: children })] }) }));
|
|
60
23
|
}
|
|
61
24
|
//# sourceMappingURL=GameModal.js.map
|
package/dist/GameModal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GameModal.js","sourceRoot":"","sources":["../src/GameModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAkB,SAAS,EAAE,MAAM,OAAO,CAAC;AASlD
|
|
1
|
+
{"version":3,"file":"GameModal.js","sourceRoot":"","sources":["../src/GameModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAkB,SAAS,EAAE,MAAM,OAAO,CAAC;AASlD;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAkB;IAC1E,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,MAAM,OAAO,GAAG,CAAC,CAAgB,EAAE,EAAE;YACnC,IAAI,CAAC,CAAC,GAAG,KAAK,QAAQ;gBAAE,OAAO,EAAE,CAAC;QACpC,CAAC,CAAC;QACF,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC9C,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAEpB,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,OAAO,CACL,cACE,OAAO,EAAE,OAAO,EAChB,SAAS,EAAC,yFAAyF,YAEnG,eACE,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE,EACnC,SAAS,EAAC,0FAA0F,aAEnG,KAAK,IAAI,CACR,eAAK,SAAS,EAAC,0EAA0E,aACvF,eAAM,SAAS,EAAC,8BAA8B,YAAE,KAAK,GAAQ,EAC7D,iBACE,OAAO,EAAE,OAAO,gBACL,OAAO,EAClB,SAAS,EAAC,4EAA4E,uBAG/E,IACL,CACP,EACD,cAAK,SAAS,EAAC,KAAK,YAAE,QAAQ,GAAO,IACjC,GACF,CACP,CAAC;AACJ,CAAC"}
|
package/dist/GameOverScreen.d.ts
CHANGED
|
@@ -12,7 +12,8 @@ export interface GameOverScreenProps {
|
|
|
12
12
|
/**
|
|
13
13
|
* Standard game-over overlay. Shows score, optional high score,
|
|
14
14
|
* play again button, and optional extra content.
|
|
15
|
-
* Renders as a centered overlay on top of the game board.
|
|
15
|
+
* Renders as a centered overlay on top of the game board. The text sits on a
|
|
16
|
+
* dark scrim, so it uses white rather than the page tokens.
|
|
16
17
|
*/
|
|
17
18
|
export declare function GameOverScreen({ score, highScore, onPlayAgain, children }: GameOverScreenProps): import("react").JSX.Element;
|
|
18
19
|
//# sourceMappingURL=GameOverScreen.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GameOverScreen.d.ts","sourceRoot":"","sources":["../src/GameOverScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,mBAAmB;IAClC,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED
|
|
1
|
+
{"version":3,"file":"GameOverScreen.d.ts","sourceRoot":"","sources":["../src/GameOverScreen.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,mBAAmB;IAClC,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0CAA0C;IAC1C,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,mBAAmB,+BAgC9F"}
|