@beta-gamer/react 0.1.10 → 0.1.12

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 CHANGED
@@ -68,7 +68,7 @@ export default function GamePage({ sessionToken }: { sessionToken: string }) {
68
68
 
69
69
  | Component | Props | Description |
70
70
  |-----------|-------|-------------|
71
- | `BetaGamerProvider` | `token`, `serverUrl?` | Wrap your game UI with this. Handles socket connection and theme. |
71
+ | `BetaGamerProvider` | `token`, `serverUrl?`, `connectSocket?` | Wrap your game UI with this. Handles socket connection and theme. |
72
72
  | `PlayerCard` | `player` (`"self"` \| `"opponent"`), `className?` | Player name + active-turn indicator |
73
73
  | `Timer` | `player`, `initialSeconds?`, `className?` | Live countdown clock, syncs with server |
74
74
 
@@ -76,20 +76,34 @@ export default function GamePage({ sessionToken }: { sessionToken: string }) {
76
76
 
77
77
  | Component | Props | Description |
78
78
  |-----------|-------|-------------|
79
- | `ChessBoard` | `className?` | Interactive chess board |
79
+ | `ChessBoard` | `className?`, `showAfkWarning?` | Interactive chess board |
80
80
  | `ChessMoveHistory` | `className?` | Scrollable move list in algebraic notation |
81
81
  | `ChessCapturedPieces` | `player`, `className?` | Pieces captured by the given player |
82
82
 
83
83
  ### Other games
84
84
 
85
- | Component | Game |
86
- |-----------|------|
87
- | `CheckersBoard` | checkers |
88
- | `Connect4Board`, `Connect4Score` | connect4 |
89
- | `TictactoeBoard` | tictactoe |
90
- | `SubwayRunnerGame`, `SubwayRunnerScore`, `SubwayRunnerLives` | subway-runner |
85
+ | Component | Props | Game |
86
+ |-----------|-------|------|
87
+ | `CheckersBoard` | `className?`, `showAfkWarning?` | checkers |
88
+ | `Connect4Board` | `className?`, `showAfkWarning?` | connect4 |
89
+ | `TictactoeBoard` | `className?`, `showAfkWarning?` | tictactoe |
90
+ | `SubwayRunnerGame`, `SubwayRunnerScore`, `SubwayRunnerLives` | `className?` | subway-runner |
91
91
 
92
- ## Hooks
92
+ > **`showAfkWarning`** (default `true`) — set to `false` to hide the built-in AFK countdown banner and implement your own using the `{game}:afk_warning` / `{game}:afk_warning_cleared` socket events.
93
+
94
+ > **`connectSocket`** (default `true`) — set to `false` when using only board components (`ChessBoard`, `CheckersBoard`, etc.). Board components load the game inside an iframe which manages its own socket connection. Creating a second socket with the same token causes duplicate connections and AFK/turn bugs.
95
+
96
+ ```tsx
97
+ // Using only board components — disable the outer socket
98
+ <BetaGamerProvider token={token} connectSocket={false}>
99
+ <ChessBoard className="board" />
100
+ </BetaGamerProvider>
101
+
102
+ // Using hooks (useSocket, useGameState) — keep socket enabled (default)
103
+ <BetaGamerProvider token={token}>
104
+ <MyCustomChessUI />
105
+ </BetaGamerProvider>
106
+ ```
93
107
 
94
108
  ```tsx
95
109
  import { useGameState, useSession, useSocket, useTheme } from '@beta-gamer/react';
package/dist/index.d.mts CHANGED
@@ -51,9 +51,10 @@ interface BetaGamerProviderProps {
51
51
  token: string;
52
52
  serverUrl?: string;
53
53
  socketPath?: string;
54
+ connectSocket?: boolean;
54
55
  children: React.ReactNode;
55
56
  }
56
- declare function BetaGamerProvider({ token, serverUrl, socketPath, children }: BetaGamerProviderProps): react_jsx_runtime.JSX.Element;
57
+ declare function BetaGamerProvider({ token, serverUrl, socketPath, connectSocket, children }: BetaGamerProviderProps): react_jsx_runtime.JSX.Element;
57
58
  declare function useBetaGamer(): BetaGamerContextValue;
58
59
 
59
60
  /** Returns the current game state (status, players, winner, etc.) */
@@ -85,8 +86,9 @@ declare function Timer({ player, initialSeconds, className }: TimerProps): react
85
86
 
86
87
  interface ChessBoardProps {
87
88
  className?: string;
89
+ showAfkWarning?: boolean;
88
90
  }
89
- declare function ChessBoard({ className }: ChessBoardProps): react_jsx_runtime.JSX.Element | null;
91
+ declare function ChessBoard({ className, showAfkWarning }: ChessBoardProps): react_jsx_runtime.JSX.Element | null;
90
92
 
91
93
  interface ChessMoveHistoryProps {
92
94
  className?: string;
@@ -101,19 +103,22 @@ interface ChessCapturedPiecesProps {
101
103
  /** Shows pieces captured by the given player. */
102
104
  declare function ChessCapturedPieces({ player, className }: ChessCapturedPiecesProps): react_jsx_runtime.JSX.Element;
103
105
 
104
- declare function CheckersBoard({ className }: {
106
+ declare function CheckersBoard({ className, showAfkWarning }: {
105
107
  className?: string;
108
+ showAfkWarning?: boolean;
106
109
  }): react_jsx_runtime.JSX.Element | null;
107
110
 
108
- declare function Connect4Board({ className }: {
111
+ declare function Connect4Board({ className, showAfkWarning }: {
109
112
  className?: string;
113
+ showAfkWarning?: boolean;
110
114
  }): react_jsx_runtime.JSX.Element | null;
111
115
  declare function Connect4Score({ className }: {
112
116
  className?: string;
113
117
  }): react_jsx_runtime.JSX.Element;
114
118
 
115
- declare function TictactoeBoard({ className }: {
119
+ declare function TictactoeBoard({ className, showAfkWarning }: {
116
120
  className?: string;
121
+ showAfkWarning?: boolean;
117
122
  }): react_jsx_runtime.JSX.Element | null;
118
123
 
119
124
  declare function SubwayRunnerScore({ className }: {
package/dist/index.d.ts CHANGED
@@ -51,9 +51,10 @@ interface BetaGamerProviderProps {
51
51
  token: string;
52
52
  serverUrl?: string;
53
53
  socketPath?: string;
54
+ connectSocket?: boolean;
54
55
  children: React.ReactNode;
55
56
  }
56
- declare function BetaGamerProvider({ token, serverUrl, socketPath, children }: BetaGamerProviderProps): react_jsx_runtime.JSX.Element;
57
+ declare function BetaGamerProvider({ token, serverUrl, socketPath, connectSocket, children }: BetaGamerProviderProps): react_jsx_runtime.JSX.Element;
57
58
  declare function useBetaGamer(): BetaGamerContextValue;
58
59
 
59
60
  /** Returns the current game state (status, players, winner, etc.) */
@@ -85,8 +86,9 @@ declare function Timer({ player, initialSeconds, className }: TimerProps): react
85
86
 
86
87
  interface ChessBoardProps {
87
88
  className?: string;
89
+ showAfkWarning?: boolean;
88
90
  }
89
- declare function ChessBoard({ className }: ChessBoardProps): react_jsx_runtime.JSX.Element | null;
91
+ declare function ChessBoard({ className, showAfkWarning }: ChessBoardProps): react_jsx_runtime.JSX.Element | null;
90
92
 
91
93
  interface ChessMoveHistoryProps {
92
94
  className?: string;
@@ -101,19 +103,22 @@ interface ChessCapturedPiecesProps {
101
103
  /** Shows pieces captured by the given player. */
102
104
  declare function ChessCapturedPieces({ player, className }: ChessCapturedPiecesProps): react_jsx_runtime.JSX.Element;
103
105
 
104
- declare function CheckersBoard({ className }: {
106
+ declare function CheckersBoard({ className, showAfkWarning }: {
105
107
  className?: string;
108
+ showAfkWarning?: boolean;
106
109
  }): react_jsx_runtime.JSX.Element | null;
107
110
 
108
- declare function Connect4Board({ className }: {
111
+ declare function Connect4Board({ className, showAfkWarning }: {
109
112
  className?: string;
113
+ showAfkWarning?: boolean;
110
114
  }): react_jsx_runtime.JSX.Element | null;
111
115
  declare function Connect4Score({ className }: {
112
116
  className?: string;
113
117
  }): react_jsx_runtime.JSX.Element;
114
118
 
115
- declare function TictactoeBoard({ className }: {
119
+ declare function TictactoeBoard({ className, showAfkWarning }: {
116
120
  className?: string;
121
+ showAfkWarning?: boolean;
117
122
  }): react_jsx_runtime.JSX.Element | null;
118
123
 
119
124
  declare function SubwayRunnerScore({ className }: {
package/dist/index.js CHANGED
@@ -56,7 +56,7 @@ function decodeToken(token) {
56
56
  return JSON.parse(atob(parts[1].replace(/-/g, "+").replace(/_/g, "/")));
57
57
  }
58
58
  var BetaGamerContext = (0, import_react.createContext)(null);
59
- function BetaGamerProvider({ token, serverUrl = "https://api.beta-gamer.com", socketPath = "/socket.io", children }) {
59
+ function BetaGamerProvider({ token, serverUrl = "https://api.beta-gamer.com", socketPath = "/socket.io", connectSocket = true, children }) {
60
60
  const session = decodeToken(token);
61
61
  const [socket, setSocket] = (0, import_react.useState)(null);
62
62
  const [gameState, setGameState] = (0, import_react.useState)({
@@ -64,6 +64,7 @@ function BetaGamerProvider({ token, serverUrl = "https://api.beta-gamer.com", so
64
64
  players: session.players
65
65
  });
66
66
  (0, import_react.useEffect)(() => {
67
+ if (!connectSocket) return;
67
68
  const s = (0, import_socket.io)(`${serverUrl}/${session.game}`, {
68
69
  auth: { token },
69
70
  path: socketPath,
@@ -169,7 +170,7 @@ function Timer({ player, initialSeconds = 600, className }) {
169
170
  // src/components/chess/ChessBoard.tsx
170
171
  var import_react3 = require("react");
171
172
  var import_jsx_runtime4 = require("react/jsx-runtime");
172
- function ChessBoard({ className }) {
173
+ function ChessBoard({ className, showAfkWarning = true }) {
173
174
  const { token, serverUrl, session } = useBetaGamer();
174
175
  const iframeRef = (0, import_react3.useRef)(null);
175
176
  (0, import_react3.useEffect)(() => {
@@ -180,11 +181,12 @@ function ChessBoard({ className }) {
180
181
  return () => iframe.removeEventListener("load", onLoad);
181
182
  }, [token]);
182
183
  if (session.game !== "chess") return null;
184
+ const src = showAfkWarning ? `${serverUrl}/embed/chess` : `${serverUrl}/embed/chess?afkWarning=0`;
183
185
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
184
186
  "iframe",
185
187
  {
186
188
  ref: iframeRef,
187
- src: `${serverUrl}/embed/chess`,
189
+ src,
188
190
  className,
189
191
  style: { border: "none", width: "100%", height: "100%" },
190
192
  allow: "autoplay",
@@ -261,7 +263,7 @@ function ChessCapturedPieces({ player, className }) {
261
263
  // src/components/checkers/index.tsx
262
264
  var import_react6 = require("react");
263
265
  var import_jsx_runtime7 = require("react/jsx-runtime");
264
- function CheckersBoard({ className }) {
266
+ function CheckersBoard({ className, showAfkWarning = true }) {
265
267
  const { token, serverUrl, session } = useBetaGamer();
266
268
  const iframeRef = (0, import_react6.useRef)(null);
267
269
  (0, import_react6.useEffect)(() => {
@@ -272,13 +274,14 @@ function CheckersBoard({ className }) {
272
274
  return () => iframe.removeEventListener("load", onLoad);
273
275
  }, [token]);
274
276
  if (session.game !== "checkers") return null;
275
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("iframe", { ref: iframeRef, src: `${serverUrl}/embed/checkers`, className, style: { border: "none", width: "100%", height: "100%" }, title: "Checkers" });
277
+ const src = showAfkWarning ? `${serverUrl}/embed/checkers` : `${serverUrl}/embed/checkers?afkWarning=0`;
278
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("iframe", { ref: iframeRef, src, className, style: { border: "none", width: "100%", height: "100%" }, title: "Checkers" });
276
279
  }
277
280
 
278
281
  // src/components/connect4/index.tsx
279
282
  var import_react7 = require("react");
280
283
  var import_jsx_runtime8 = require("react/jsx-runtime");
281
- function Connect4Board({ className }) {
284
+ function Connect4Board({ className, showAfkWarning = true }) {
282
285
  const { token, serverUrl, session } = useBetaGamer();
283
286
  const iframeRef = (0, import_react7.useRef)(null);
284
287
  (0, import_react7.useEffect)(() => {
@@ -289,7 +292,8 @@ function Connect4Board({ className }) {
289
292
  return () => iframe.removeEventListener("load", onLoad);
290
293
  }, [token]);
291
294
  if (session.game !== "connect4") return null;
292
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("iframe", { ref: iframeRef, src: `${serverUrl}/embed/connect4`, className, style: { border: "none", width: "100%", height: "100%" }, title: "Connect 4" });
295
+ const src = showAfkWarning ? `${serverUrl}/embed/connect4` : `${serverUrl}/embed/connect4?afkWarning=0`;
296
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("iframe", { ref: iframeRef, src, className, style: { border: "none", width: "100%", height: "100%" }, title: "Connect 4" });
293
297
  }
294
298
  function Connect4Score({ className }) {
295
299
  const { gameState } = useBetaGamer();
@@ -300,7 +304,7 @@ function Connect4Score({ className }) {
300
304
  // src/components/tictactoe/index.tsx
301
305
  var import_react8 = require("react");
302
306
  var import_jsx_runtime9 = require("react/jsx-runtime");
303
- function TictactoeBoard({ className }) {
307
+ function TictactoeBoard({ className, showAfkWarning = true }) {
304
308
  const { token, serverUrl, session } = useBetaGamer();
305
309
  const iframeRef = (0, import_react8.useRef)(null);
306
310
  (0, import_react8.useEffect)(() => {
@@ -311,7 +315,8 @@ function TictactoeBoard({ className }) {
311
315
  return () => iframe.removeEventListener("load", onLoad);
312
316
  }, [token]);
313
317
  if (session.game !== "tictactoe") return null;
314
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("iframe", { ref: iframeRef, src: `${serverUrl}/embed/tictactoe`, className, style: { border: "none", width: "100%", height: "100%" }, title: "Tic-tac-toe" });
318
+ const src = showAfkWarning ? `${serverUrl}/embed/tictactoe` : `${serverUrl}/embed/tictactoe?afkWarning=0`;
319
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("iframe", { ref: iframeRef, src, className, style: { border: "none", width: "100%", height: "100%" }, title: "Tic-tac-toe" });
315
320
  }
316
321
 
317
322
  // src/components/subway-runner/index.tsx
package/dist/index.mjs CHANGED
@@ -13,7 +13,7 @@ function decodeToken(token) {
13
13
  return JSON.parse(atob(parts[1].replace(/-/g, "+").replace(/_/g, "/")));
14
14
  }
15
15
  var BetaGamerContext = createContext(null);
16
- function BetaGamerProvider({ token, serverUrl = "https://api.beta-gamer.com", socketPath = "/socket.io", children }) {
16
+ function BetaGamerProvider({ token, serverUrl = "https://api.beta-gamer.com", socketPath = "/socket.io", connectSocket = true, children }) {
17
17
  const session = decodeToken(token);
18
18
  const [socket, setSocket] = useState(null);
19
19
  const [gameState, setGameState] = useState({
@@ -21,6 +21,7 @@ function BetaGamerProvider({ token, serverUrl = "https://api.beta-gamer.com", so
21
21
  players: session.players
22
22
  });
23
23
  useEffect(() => {
24
+ if (!connectSocket) return;
24
25
  const s = io(`${serverUrl}/${session.game}`, {
25
26
  auth: { token },
26
27
  path: socketPath,
@@ -126,7 +127,7 @@ function Timer({ player, initialSeconds = 600, className }) {
126
127
  // src/components/chess/ChessBoard.tsx
127
128
  import { useEffect as useEffect3, useRef } from "react";
128
129
  import { jsx as jsx4 } from "react/jsx-runtime";
129
- function ChessBoard({ className }) {
130
+ function ChessBoard({ className, showAfkWarning = true }) {
130
131
  const { token, serverUrl, session } = useBetaGamer();
131
132
  const iframeRef = useRef(null);
132
133
  useEffect3(() => {
@@ -137,11 +138,12 @@ function ChessBoard({ className }) {
137
138
  return () => iframe.removeEventListener("load", onLoad);
138
139
  }, [token]);
139
140
  if (session.game !== "chess") return null;
141
+ const src = showAfkWarning ? `${serverUrl}/embed/chess` : `${serverUrl}/embed/chess?afkWarning=0`;
140
142
  return /* @__PURE__ */ jsx4(
141
143
  "iframe",
142
144
  {
143
145
  ref: iframeRef,
144
- src: `${serverUrl}/embed/chess`,
146
+ src,
145
147
  className,
146
148
  style: { border: "none", width: "100%", height: "100%" },
147
149
  allow: "autoplay",
@@ -218,7 +220,7 @@ function ChessCapturedPieces({ player, className }) {
218
220
  // src/components/checkers/index.tsx
219
221
  import { useEffect as useEffect6, useRef as useRef2 } from "react";
220
222
  import { jsx as jsx7 } from "react/jsx-runtime";
221
- function CheckersBoard({ className }) {
223
+ function CheckersBoard({ className, showAfkWarning = true }) {
222
224
  const { token, serverUrl, session } = useBetaGamer();
223
225
  const iframeRef = useRef2(null);
224
226
  useEffect6(() => {
@@ -229,13 +231,14 @@ function CheckersBoard({ className }) {
229
231
  return () => iframe.removeEventListener("load", onLoad);
230
232
  }, [token]);
231
233
  if (session.game !== "checkers") return null;
232
- return /* @__PURE__ */ jsx7("iframe", { ref: iframeRef, src: `${serverUrl}/embed/checkers`, className, style: { border: "none", width: "100%", height: "100%" }, title: "Checkers" });
234
+ const src = showAfkWarning ? `${serverUrl}/embed/checkers` : `${serverUrl}/embed/checkers?afkWarning=0`;
235
+ return /* @__PURE__ */ jsx7("iframe", { ref: iframeRef, src, className, style: { border: "none", width: "100%", height: "100%" }, title: "Checkers" });
233
236
  }
234
237
 
235
238
  // src/components/connect4/index.tsx
236
239
  import { useEffect as useEffect7, useRef as useRef3 } from "react";
237
240
  import { jsx as jsx8 } from "react/jsx-runtime";
238
- function Connect4Board({ className }) {
241
+ function Connect4Board({ className, showAfkWarning = true }) {
239
242
  const { token, serverUrl, session } = useBetaGamer();
240
243
  const iframeRef = useRef3(null);
241
244
  useEffect7(() => {
@@ -246,7 +249,8 @@ function Connect4Board({ className }) {
246
249
  return () => iframe.removeEventListener("load", onLoad);
247
250
  }, [token]);
248
251
  if (session.game !== "connect4") return null;
249
- return /* @__PURE__ */ jsx8("iframe", { ref: iframeRef, src: `${serverUrl}/embed/connect4`, className, style: { border: "none", width: "100%", height: "100%" }, title: "Connect 4" });
252
+ const src = showAfkWarning ? `${serverUrl}/embed/connect4` : `${serverUrl}/embed/connect4?afkWarning=0`;
253
+ return /* @__PURE__ */ jsx8("iframe", { ref: iframeRef, src, className, style: { border: "none", width: "100%", height: "100%" }, title: "Connect 4" });
250
254
  }
251
255
  function Connect4Score({ className }) {
252
256
  const { gameState } = useBetaGamer();
@@ -257,7 +261,7 @@ function Connect4Score({ className }) {
257
261
  // src/components/tictactoe/index.tsx
258
262
  import { useEffect as useEffect8, useRef as useRef4 } from "react";
259
263
  import { jsx as jsx9 } from "react/jsx-runtime";
260
- function TictactoeBoard({ className }) {
264
+ function TictactoeBoard({ className, showAfkWarning = true }) {
261
265
  const { token, serverUrl, session } = useBetaGamer();
262
266
  const iframeRef = useRef4(null);
263
267
  useEffect8(() => {
@@ -268,7 +272,8 @@ function TictactoeBoard({ className }) {
268
272
  return () => iframe.removeEventListener("load", onLoad);
269
273
  }, [token]);
270
274
  if (session.game !== "tictactoe") return null;
271
- return /* @__PURE__ */ jsx9("iframe", { ref: iframeRef, src: `${serverUrl}/embed/tictactoe`, className, style: { border: "none", width: "100%", height: "100%" }, title: "Tic-tac-toe" });
275
+ const src = showAfkWarning ? `${serverUrl}/embed/tictactoe` : `${serverUrl}/embed/tictactoe?afkWarning=0`;
276
+ return /* @__PURE__ */ jsx9("iframe", { ref: iframeRef, src, className, style: { border: "none", width: "100%", height: "100%" }, title: "Tic-tac-toe" });
272
277
  }
273
278
 
274
279
  // src/components/subway-runner/index.tsx
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beta-gamer/react",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "React SDK for Beta Gamer GaaS — composable game components",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",