@react-chess-tools/react-chess-game 0.5.2 → 1.0.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/CHANGELOG.md +15 -0
- package/dist/index.cjs +775 -0
- package/dist/index.cjs.map +1 -0
- package/dist/{index.d.mts → index.d.cts} +118 -12
- package/dist/index.d.ts +264 -0
- package/dist/{index.mjs → index.js} +171 -38
- package/dist/index.js.map +1 -0
- package/package.json +18 -9
- package/src/components/ChessGame/Theme.stories.tsx +242 -0
- package/src/components/ChessGame/ThemePresets.stories.tsx +144 -0
- package/src/components/ChessGame/parts/Board.tsx +6 -4
- package/src/components/ChessGame/parts/Root.tsx +11 -1
- package/src/docs/Theming.mdx +281 -0
- package/src/hooks/useChessGame.ts +23 -7
- package/src/index.ts +19 -0
- package/src/theme/__tests__/context.test.tsx +75 -0
- package/src/theme/__tests__/defaults.test.ts +61 -0
- package/src/theme/__tests__/utils.test.ts +106 -0
- package/src/theme/context.tsx +37 -0
- package/src/theme/defaults.ts +22 -0
- package/src/theme/index.ts +36 -0
- package/src/theme/presets.ts +41 -0
- package/src/theme/types.ts +56 -0
- package/src/theme/utils.ts +47 -0
- package/src/utils/__tests__/board.test.ts +118 -0
- package/src/utils/board.ts +18 -9
- package/src/utils/chess.ts +25 -5
- package/coverage/clover.xml +0 -6
- package/coverage/coverage-final.json +0 -1
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -101
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov.info +0 -0
- package/dist/index.mjs.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/components/ChessGame/parts/Root.tsx
|
|
2
|
-
import
|
|
2
|
+
import React4 from "react";
|
|
3
3
|
|
|
4
4
|
// src/hooks/useChessGame.ts
|
|
5
5
|
import React, { useEffect } from "react";
|
|
@@ -9,9 +9,17 @@ import { Chess as Chess2 } from "chess.js";
|
|
|
9
9
|
import { Chess } from "chess.js";
|
|
10
10
|
import _ from "lodash";
|
|
11
11
|
var cloneGame = (game) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
try {
|
|
13
|
+
const copy = new Chess();
|
|
14
|
+
const pgn = game == null ? void 0 : game.pgn();
|
|
15
|
+
if (pgn) {
|
|
16
|
+
copy.loadPgn(pgn);
|
|
17
|
+
}
|
|
18
|
+
return copy;
|
|
19
|
+
} catch (e) {
|
|
20
|
+
console.error("Failed to clone game:", e);
|
|
21
|
+
return new Chess();
|
|
22
|
+
}
|
|
15
23
|
};
|
|
16
24
|
var getGameInfo = (game, orientation) => {
|
|
17
25
|
const turn = game.turn();
|
|
@@ -57,6 +65,9 @@ var isLegalMove = (game, move) => {
|
|
|
57
65
|
}
|
|
58
66
|
};
|
|
59
67
|
var requiresPromotion = (game, move) => {
|
|
68
|
+
if (!game) {
|
|
69
|
+
throw new Error("Game is required");
|
|
70
|
+
}
|
|
60
71
|
try {
|
|
61
72
|
const copy = cloneGame(game);
|
|
62
73
|
const result = copy.move(move);
|
|
@@ -76,12 +87,20 @@ var getCurrentFen = (fen, game, currentMoveIndex) => {
|
|
|
76
87
|
const tempGame = new Chess();
|
|
77
88
|
if (currentMoveIndex === -1) {
|
|
78
89
|
if (fen) {
|
|
79
|
-
|
|
90
|
+
try {
|
|
91
|
+
tempGame.load(fen);
|
|
92
|
+
} catch (e) {
|
|
93
|
+
console.error("Failed to load FEN in getCurrentFen:", fen, e);
|
|
94
|
+
}
|
|
80
95
|
}
|
|
81
96
|
} else {
|
|
82
97
|
const moves = game.history().slice(0, currentMoveIndex + 1);
|
|
83
98
|
if (fen) {
|
|
84
|
-
|
|
99
|
+
try {
|
|
100
|
+
tempGame.load(fen);
|
|
101
|
+
} catch (e) {
|
|
102
|
+
console.error("Failed to load FEN in getCurrentFen:", fen, e);
|
|
103
|
+
}
|
|
85
104
|
}
|
|
86
105
|
moves.forEach((move) => tempGame.move(move));
|
|
87
106
|
}
|
|
@@ -93,9 +112,21 @@ var useChessGame = ({
|
|
|
93
112
|
fen,
|
|
94
113
|
orientation: initialOrientation
|
|
95
114
|
} = {}) => {
|
|
96
|
-
const [game, setGame] = React.useState(
|
|
115
|
+
const [game, setGame] = React.useState(() => {
|
|
116
|
+
try {
|
|
117
|
+
return new Chess2(fen);
|
|
118
|
+
} catch (e) {
|
|
119
|
+
console.error("Invalid FEN:", fen, e);
|
|
120
|
+
return new Chess2();
|
|
121
|
+
}
|
|
122
|
+
});
|
|
97
123
|
useEffect(() => {
|
|
98
|
-
|
|
124
|
+
try {
|
|
125
|
+
setGame(new Chess2(fen));
|
|
126
|
+
} catch (e) {
|
|
127
|
+
console.error("Invalid FEN:", fen, e);
|
|
128
|
+
setGame(new Chess2());
|
|
129
|
+
}
|
|
99
130
|
}, [fen]);
|
|
100
131
|
const [orientation, setOrientation] = React.useState(
|
|
101
132
|
initialOrientation ?? "w"
|
|
@@ -119,11 +150,15 @@ var useChessGame = ({
|
|
|
119
150
|
[game, currentMoveIndex]
|
|
120
151
|
);
|
|
121
152
|
const setPosition = React.useCallback((fen2, orientation2) => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
153
|
+
try {
|
|
154
|
+
const newGame = new Chess2();
|
|
155
|
+
newGame.load(fen2);
|
|
156
|
+
setOrientation(orientation2);
|
|
157
|
+
setGame(newGame);
|
|
158
|
+
setCurrentMoveIndex(-1);
|
|
159
|
+
} catch (e) {
|
|
160
|
+
console.error("Failed to load FEN:", fen2, e);
|
|
161
|
+
}
|
|
127
162
|
}, []);
|
|
128
163
|
const makeMove = React.useCallback(
|
|
129
164
|
(move) => {
|
|
@@ -212,18 +247,68 @@ var useChessGameContext = () => {
|
|
|
212
247
|
return context;
|
|
213
248
|
};
|
|
214
249
|
|
|
250
|
+
// src/theme/context.tsx
|
|
251
|
+
import React3, { createContext, useContext } from "react";
|
|
252
|
+
|
|
253
|
+
// src/theme/defaults.ts
|
|
254
|
+
var defaultGameTheme = {
|
|
255
|
+
board: {
|
|
256
|
+
lightSquare: { backgroundColor: "#f0d9b5" },
|
|
257
|
+
darkSquare: { backgroundColor: "#b58863" }
|
|
258
|
+
},
|
|
259
|
+
state: {
|
|
260
|
+
lastMove: "rgba(255, 255, 0, 0.5)",
|
|
261
|
+
check: "rgba(255, 0, 0, 0.5)",
|
|
262
|
+
activeSquare: "rgba(255, 255, 0, 0.5)",
|
|
263
|
+
dropSquare: { backgroundColor: "rgba(255, 255, 0, 0.4)" }
|
|
264
|
+
},
|
|
265
|
+
indicators: {
|
|
266
|
+
move: "rgba(0, 0, 0, 0.1)",
|
|
267
|
+
capture: "rgba(1, 0, 0, 0.1)"
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
// src/theme/context.tsx
|
|
272
|
+
var ChessGameThemeContext = createContext(defaultGameTheme);
|
|
273
|
+
var useChessGameTheme = () => {
|
|
274
|
+
return useContext(ChessGameThemeContext);
|
|
275
|
+
};
|
|
276
|
+
var ThemeProvider = ({
|
|
277
|
+
theme,
|
|
278
|
+
children
|
|
279
|
+
}) => {
|
|
280
|
+
return /* @__PURE__ */ React3.createElement(ChessGameThemeContext.Provider, { value: theme }, children);
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
// src/theme/utils.ts
|
|
284
|
+
import { merge } from "lodash";
|
|
285
|
+
var mergeTheme = (partialTheme) => {
|
|
286
|
+
if (!partialTheme) {
|
|
287
|
+
return { ...defaultGameTheme };
|
|
288
|
+
}
|
|
289
|
+
return merge({}, defaultGameTheme, partialTheme);
|
|
290
|
+
};
|
|
291
|
+
var mergeThemeWith = (baseTheme, partialTheme) => {
|
|
292
|
+
if (!partialTheme) {
|
|
293
|
+
return { ...baseTheme };
|
|
294
|
+
}
|
|
295
|
+
return merge({}, baseTheme, partialTheme);
|
|
296
|
+
};
|
|
297
|
+
|
|
215
298
|
// src/components/ChessGame/parts/Root.tsx
|
|
216
299
|
var Root = ({
|
|
217
300
|
fen,
|
|
218
301
|
orientation,
|
|
302
|
+
theme,
|
|
219
303
|
children
|
|
220
304
|
}) => {
|
|
221
305
|
const context = useChessGame({ fen, orientation });
|
|
222
|
-
|
|
306
|
+
const mergedTheme = React4.useMemo(() => mergeTheme(theme), [theme]);
|
|
307
|
+
return /* @__PURE__ */ React4.createElement(ChessGameContext.Provider, { value: context }, /* @__PURE__ */ React4.createElement(ThemeProvider, { theme: mergedTheme }, children));
|
|
223
308
|
};
|
|
224
309
|
|
|
225
310
|
// src/components/ChessGame/parts/Board.tsx
|
|
226
|
-
import
|
|
311
|
+
import React5 from "react";
|
|
227
312
|
import {
|
|
228
313
|
Chessboard,
|
|
229
314
|
defaultPieces,
|
|
@@ -231,23 +316,21 @@ import {
|
|
|
231
316
|
} from "react-chessboard";
|
|
232
317
|
|
|
233
318
|
// src/utils/board.ts
|
|
234
|
-
import { merge } from "lodash";
|
|
235
|
-
var
|
|
236
|
-
var CHECK_COLOR = "rgba(255, 0, 0, 0.5)";
|
|
237
|
-
var getCustomSquareStyles = (game, info, activeSquare) => {
|
|
319
|
+
import { merge as merge2 } from "lodash";
|
|
320
|
+
var getCustomSquareStyles = (game, info, activeSquare, theme = defaultGameTheme) => {
|
|
238
321
|
const customSquareStyles = {};
|
|
239
322
|
const { lastMove, isCheck, turn } = info;
|
|
240
323
|
if (lastMove) {
|
|
241
324
|
customSquareStyles[lastMove.from] = {
|
|
242
|
-
backgroundColor:
|
|
325
|
+
backgroundColor: theme.state.lastMove
|
|
243
326
|
};
|
|
244
327
|
customSquareStyles[lastMove.to] = {
|
|
245
|
-
backgroundColor:
|
|
328
|
+
backgroundColor: theme.state.lastMove
|
|
246
329
|
};
|
|
247
330
|
}
|
|
248
331
|
if (activeSquare) {
|
|
249
332
|
customSquareStyles[activeSquare] = {
|
|
250
|
-
backgroundColor:
|
|
333
|
+
backgroundColor: theme.state.activeSquare
|
|
251
334
|
};
|
|
252
335
|
}
|
|
253
336
|
if (activeSquare) {
|
|
@@ -255,7 +338,7 @@ var getCustomSquareStyles = (game, info, activeSquare) => {
|
|
|
255
338
|
destinationSquares.forEach((square) => {
|
|
256
339
|
var _a;
|
|
257
340
|
customSquareStyles[square] = {
|
|
258
|
-
background: game.get(square) && ((_a = game.get(square)) == null ? void 0 : _a.color) !== turn ?
|
|
341
|
+
background: game.get(square) && ((_a = game.get(square)) == null ? void 0 : _a.color) !== turn ? `radial-gradient(circle, ${theme.indicators.capture} 85%, transparent 85%)` : `radial-gradient(circle, ${theme.indicators.move} 25%, transparent 25%)`
|
|
259
342
|
};
|
|
260
343
|
});
|
|
261
344
|
}
|
|
@@ -264,7 +347,7 @@ var getCustomSquareStyles = (game, info, activeSquare) => {
|
|
|
264
347
|
return row.forEach((square) => {
|
|
265
348
|
if ((square == null ? void 0 : square.type) === "k" && (square == null ? void 0 : square.color) === info.turn) {
|
|
266
349
|
customSquareStyles[square.square] = {
|
|
267
|
-
backgroundColor:
|
|
350
|
+
backgroundColor: theme.state.check
|
|
268
351
|
};
|
|
269
352
|
}
|
|
270
353
|
});
|
|
@@ -276,7 +359,7 @@ var deepMergeChessboardOptions = (baseOptions, customOptions) => {
|
|
|
276
359
|
if (!customOptions) {
|
|
277
360
|
return { ...baseOptions };
|
|
278
361
|
}
|
|
279
|
-
const result =
|
|
362
|
+
const result = merge2({}, baseOptions, customOptions, {
|
|
280
363
|
customizer: (_objValue, srcValue) => {
|
|
281
364
|
if (typeof srcValue === "function") {
|
|
282
365
|
return srcValue;
|
|
@@ -295,6 +378,7 @@ var deepMergeChessboardOptions = (baseOptions, customOptions) => {
|
|
|
295
378
|
var Board = ({ options = {} }) => {
|
|
296
379
|
var _a, _b, _c;
|
|
297
380
|
const gameContext = useChessGameContext();
|
|
381
|
+
const theme = useChessGameTheme();
|
|
298
382
|
if (!gameContext) {
|
|
299
383
|
throw new Error("ChessGameContext not found");
|
|
300
384
|
}
|
|
@@ -307,8 +391,8 @@ var Board = ({ options = {} }) => {
|
|
|
307
391
|
methods: { makeMove }
|
|
308
392
|
} = gameContext;
|
|
309
393
|
const { turn, isGameOver } = info;
|
|
310
|
-
const [activeSquare, setActiveSquare] =
|
|
311
|
-
const [promotionMove, setPromotionMove] =
|
|
394
|
+
const [activeSquare, setActiveSquare] = React5.useState(null);
|
|
395
|
+
const [promotionMove, setPromotionMove] = React5.useState(null);
|
|
312
396
|
const onSquareClick = (square) => {
|
|
313
397
|
if (isGameOver) {
|
|
314
398
|
return;
|
|
@@ -357,13 +441,13 @@ var Board = ({ options = {} }) => {
|
|
|
357
441
|
setActiveSquare(null);
|
|
358
442
|
setPromotionMove(null);
|
|
359
443
|
};
|
|
360
|
-
const squareWidth =
|
|
444
|
+
const squareWidth = React5.useMemo(() => {
|
|
361
445
|
var _a2;
|
|
362
446
|
if (typeof document === "undefined") return 80;
|
|
363
447
|
const squareElement = document.querySelector(`[data-square]`);
|
|
364
448
|
return ((_a2 = squareElement == null ? void 0 : squareElement.getBoundingClientRect()) == null ? void 0 : _a2.width) ?? 80;
|
|
365
449
|
}, [promotionMove]);
|
|
366
|
-
const promotionSquareLeft =
|
|
450
|
+
const promotionSquareLeft = React5.useMemo(() => {
|
|
367
451
|
var _a2;
|
|
368
452
|
if (!(promotionMove == null ? void 0 : promotionMove.to)) return 0;
|
|
369
453
|
const column = ((_a2 = promotionMove.to.match(/^[a-h]/)) == null ? void 0 : _a2[0]) ?? "a";
|
|
@@ -374,18 +458,18 @@ var Board = ({ options = {} }) => {
|
|
|
374
458
|
);
|
|
375
459
|
}, [promotionMove, squareWidth, orientation]);
|
|
376
460
|
const baseOptions = {
|
|
377
|
-
squareStyles: getCustomSquareStyles(game, info, activeSquare),
|
|
461
|
+
squareStyles: getCustomSquareStyles(game, info, activeSquare, theme),
|
|
378
462
|
boardOrientation: orientation === "b" ? "black" : "white",
|
|
379
463
|
position: currentFen,
|
|
380
464
|
showNotation: true,
|
|
381
465
|
showAnimations: isLatestMove,
|
|
466
|
+
lightSquareStyle: theme.board.lightSquare,
|
|
467
|
+
darkSquareStyle: theme.board.darkSquare,
|
|
382
468
|
canDragPiece: ({ piece }) => {
|
|
383
469
|
if (isGameOver) return false;
|
|
384
470
|
return piece.pieceType[0] === turn;
|
|
385
471
|
},
|
|
386
|
-
dropSquareStyle:
|
|
387
|
-
backgroundColor: "rgba(255, 255, 0, 0.4)"
|
|
388
|
-
},
|
|
472
|
+
dropSquareStyle: theme.state.dropSquare,
|
|
389
473
|
onPieceDrag: ({ piece, square }) => {
|
|
390
474
|
if (piece.pieceType[0] === turn) {
|
|
391
475
|
setActiveSquare(square);
|
|
@@ -413,7 +497,7 @@ var Board = ({ options = {} }) => {
|
|
|
413
497
|
animationDurationInMs: game.history().length === 0 ? 0 : 300
|
|
414
498
|
};
|
|
415
499
|
const mergedOptions = deepMergeChessboardOptions(baseOptions, options);
|
|
416
|
-
return /* @__PURE__ */
|
|
500
|
+
return /* @__PURE__ */ React5.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React5.createElement(Chessboard, { options: mergedOptions }), promotionMove && /* @__PURE__ */ React5.createElement(React5.Fragment, null, /* @__PURE__ */ React5.createElement(
|
|
417
501
|
"div",
|
|
418
502
|
{
|
|
419
503
|
onClick: () => setPromotionMove(null),
|
|
@@ -431,7 +515,7 @@ var Board = ({ options = {} }) => {
|
|
|
431
515
|
zIndex: 1e3
|
|
432
516
|
}
|
|
433
517
|
}
|
|
434
|
-
), /* @__PURE__ */
|
|
518
|
+
), /* @__PURE__ */ React5.createElement(
|
|
435
519
|
"div",
|
|
436
520
|
{
|
|
437
521
|
style: {
|
|
@@ -447,7 +531,7 @@ var Board = ({ options = {} }) => {
|
|
|
447
531
|
boxShadow: "0 0 10px 0 rgba(0, 0, 0, 0.5)"
|
|
448
532
|
}
|
|
449
533
|
},
|
|
450
|
-
["q", "r", "n", "b"].map((piece) => /* @__PURE__ */
|
|
534
|
+
["q", "r", "n", "b"].map((piece) => /* @__PURE__ */ React5.createElement(
|
|
451
535
|
"button",
|
|
452
536
|
{
|
|
453
537
|
key: piece,
|
|
@@ -589,10 +673,59 @@ var ChessGame = {
|
|
|
589
673
|
Sounds,
|
|
590
674
|
KeyboardControls: KeyboardControls2
|
|
591
675
|
};
|
|
676
|
+
|
|
677
|
+
// src/theme/presets.ts
|
|
678
|
+
var lichessTheme = {
|
|
679
|
+
board: {
|
|
680
|
+
lightSquare: { backgroundColor: "#f0d9b5" },
|
|
681
|
+
darkSquare: { backgroundColor: "#b58863" }
|
|
682
|
+
},
|
|
683
|
+
state: {
|
|
684
|
+
lastMove: "rgba(155, 199, 0, 0.41)",
|
|
685
|
+
check: "rgba(255, 0, 0, 0.5)",
|
|
686
|
+
activeSquare: "rgba(20, 85, 30, 0.5)",
|
|
687
|
+
dropSquare: { backgroundColor: "rgba(20, 85, 30, 0.3)" }
|
|
688
|
+
},
|
|
689
|
+
indicators: {
|
|
690
|
+
move: "rgba(20, 85, 30, 0.3)",
|
|
691
|
+
capture: "rgba(20, 85, 30, 0.3)"
|
|
692
|
+
}
|
|
693
|
+
};
|
|
694
|
+
var chessComTheme = {
|
|
695
|
+
board: {
|
|
696
|
+
lightSquare: { backgroundColor: "#ebecd0" },
|
|
697
|
+
darkSquare: { backgroundColor: "#779556" }
|
|
698
|
+
},
|
|
699
|
+
state: {
|
|
700
|
+
lastMove: "rgba(255, 255, 0, 0.5)",
|
|
701
|
+
check: "rgba(255, 0, 0, 0.7)",
|
|
702
|
+
activeSquare: "rgba(255, 255, 0, 0.5)",
|
|
703
|
+
dropSquare: { backgroundColor: "rgba(255, 255, 0, 0.4)" }
|
|
704
|
+
},
|
|
705
|
+
indicators: {
|
|
706
|
+
move: "rgba(0, 0, 0, 0.1)",
|
|
707
|
+
capture: "rgba(0, 0, 0, 0.1)"
|
|
708
|
+
}
|
|
709
|
+
};
|
|
710
|
+
|
|
711
|
+
// src/theme/index.ts
|
|
712
|
+
var themes = {
|
|
713
|
+
default: defaultGameTheme,
|
|
714
|
+
lichess: lichessTheme,
|
|
715
|
+
chessCom: chessComTheme
|
|
716
|
+
};
|
|
592
717
|
export {
|
|
593
718
|
ChessGame,
|
|
719
|
+
ChessGameThemeContext,
|
|
720
|
+
chessComTheme,
|
|
594
721
|
deepMergeChessboardOptions,
|
|
722
|
+
defaultGameTheme,
|
|
723
|
+
lichessTheme,
|
|
724
|
+
mergeTheme,
|
|
725
|
+
mergeThemeWith,
|
|
726
|
+
themes,
|
|
595
727
|
useChessGame,
|
|
596
|
-
useChessGameContext
|
|
728
|
+
useChessGameContext,
|
|
729
|
+
useChessGameTheme
|
|
597
730
|
};
|
|
598
|
-
//# sourceMappingURL=index.
|
|
731
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ChessGame/parts/Root.tsx","../src/hooks/useChessGame.ts","../src/utils/chess.ts","../src/hooks/useChessGameContext.ts","../src/theme/context.tsx","../src/theme/defaults.ts","../src/theme/utils.ts","../src/components/ChessGame/parts/Board.tsx","../src/utils/board.ts","../src/components/ChessGame/parts/Sounds.tsx","../src/assets/sounds.ts","../src/hooks/useBoardSounds.ts","../src/hooks/useKeyboardControls.ts","../src/components/ChessGame/parts/KeyboardControls.tsx","../src/components/ChessGame/index.ts","../src/theme/presets.ts","../src/theme/index.ts"],"sourcesContent":["import React from \"react\";\nimport { Color } from \"chess.js\";\nimport { useChessGame } from \"../../../hooks/useChessGame\";\nimport { ChessGameContext } from \"../../../hooks/useChessGameContext\";\nimport { ThemeProvider } from \"../../../theme/context\";\nimport { mergeTheme } from \"../../../theme/utils\";\nimport type { PartialChessGameTheme } from \"../../../theme/types\";\n\nexport interface RootProps {\n fen?: string;\n orientation?: Color;\n /** Optional theme configuration. Supports partial themes - only override the colors you need. */\n theme?: PartialChessGameTheme;\n}\n\nexport const Root: React.FC<React.PropsWithChildren<RootProps>> = ({\n fen,\n orientation,\n theme,\n children,\n}) => {\n const context = useChessGame({ fen, orientation });\n\n // Merge partial theme with defaults\n const mergedTheme = React.useMemo(() => mergeTheme(theme), [theme]);\n\n return (\n <ChessGameContext.Provider value={context}>\n <ThemeProvider theme={mergedTheme}>{children}</ThemeProvider>\n </ChessGameContext.Provider>\n );\n};\n","import React, { useEffect } from \"react\";\nimport { Chess, Color } from \"chess.js\";\nimport { cloneGame, getCurrentFen, getGameInfo } from \"../utils/chess\";\n\nexport type useChessGameProps = {\n fen?: string;\n orientation?: Color;\n};\n\nexport const useChessGame = ({\n fen,\n orientation: initialOrientation,\n}: useChessGameProps = {}) => {\n const [game, setGame] = React.useState(() => {\n try {\n return new Chess(fen);\n } catch (e) {\n console.error(\"Invalid FEN:\", fen, e);\n return new Chess(); // Return empty board\n }\n });\n\n useEffect(() => {\n try {\n setGame(new Chess(fen));\n } catch (e) {\n console.error(\"Invalid FEN:\", fen, e);\n setGame(new Chess());\n }\n }, [fen]);\n\n const [orientation, setOrientation] = React.useState<Color>(\n initialOrientation ?? \"w\",\n );\n const [currentMoveIndex, setCurrentMoveIndex] = React.useState(-1);\n\n const history = React.useMemo(() => game.history(), [game]);\n const isLatestMove = React.useMemo(\n () => currentMoveIndex === history.length - 1 || currentMoveIndex === -1,\n [currentMoveIndex, history.length],\n );\n\n const info = React.useMemo(\n () => getGameInfo(game, orientation),\n [game, orientation],\n );\n\n const currentFen = React.useMemo(\n () => getCurrentFen(fen, game, currentMoveIndex),\n [game, currentMoveIndex],\n );\n\n const currentPosition = React.useMemo(\n () => game.history()[currentMoveIndex],\n [game, currentMoveIndex],\n );\n\n const setPosition = React.useCallback((fen: string, orientation: Color) => {\n try {\n const newGame = new Chess();\n newGame.load(fen);\n setOrientation(orientation);\n setGame(newGame);\n setCurrentMoveIndex(-1);\n } catch (e) {\n console.error(\"Failed to load FEN:\", fen, e);\n }\n }, []);\n\n const makeMove = React.useCallback(\n (move: Parameters<Chess[\"move\"]>[0]): boolean => {\n // Only allow moves when we're at the latest position\n if (!isLatestMove) {\n return false;\n }\n\n try {\n const copy = cloneGame(game);\n copy.move(move);\n setGame(copy);\n setCurrentMoveIndex(copy.history().length - 1);\n return true;\n } catch (e) {\n return false;\n }\n },\n [isLatestMove, game],\n );\n\n const flipBoard = React.useCallback(() => {\n setOrientation((orientation) => (orientation === \"w\" ? \"b\" : \"w\"));\n }, []);\n\n const goToMove = React.useCallback(\n (moveIndex: number) => {\n if (moveIndex < -1 || moveIndex >= history.length) return;\n setCurrentMoveIndex(moveIndex);\n },\n [history.length],\n );\n\n const goToStart = React.useCallback(() => goToMove(-1), []);\n const goToEnd = React.useCallback(\n () => goToMove(history.length - 1),\n [history.length],\n );\n const goToPreviousMove = React.useCallback(\n () => goToMove(currentMoveIndex - 1),\n [currentMoveIndex],\n );\n const goToNextMove = React.useCallback(\n () => goToMove(currentMoveIndex + 1),\n [currentMoveIndex],\n );\n\n const methods = React.useMemo(\n () => ({\n makeMove,\n setPosition,\n flipBoard,\n goToMove,\n goToStart,\n goToEnd,\n goToPreviousMove,\n goToNextMove,\n }),\n [\n makeMove,\n setPosition,\n flipBoard,\n goToMove,\n goToStart,\n goToEnd,\n goToPreviousMove,\n goToNextMove,\n ],\n );\n\n return {\n game,\n currentFen,\n currentPosition,\n orientation,\n currentMoveIndex,\n isLatestMove,\n info,\n methods,\n };\n};\n","import { Chess, Color, Square } from \"chess.js\";\nimport _ from \"lodash\";\n\n/**\n * Creates a clone of the given Chess.js instance. This is needed to update the state\n * of react-chessboard component\n * @param game - The Chess.js instance to clone.\n * @returns A new Chess.js instance with the same state as the original.\n */\nexport const cloneGame = (game: Chess) => {\n try {\n const copy = new Chess();\n const pgn = game?.pgn();\n if (pgn) {\n copy.loadPgn(pgn);\n }\n return copy;\n } catch (e) {\n console.error(\"Failed to clone game:\", e);\n return new Chess();\n }\n};\n\n/**\n * Returns an object with information about the current state of the game. This can be determined\n * using chess.js instance, but this function is provided for convenience.\n * @param game - The Chess.js instance representing the game.\n * @returns An object with information about the current state of the game.\n */\n\nexport const getGameInfo = (game: Chess, orientation: Color) => {\n const turn = game.turn();\n const isPlayerTurn = turn === orientation;\n const isOpponentTurn = !isPlayerTurn;\n const moveNumber = game.history().length;\n const lastMove = _.last(game.history({ verbose: true }));\n const isCheck = game.isCheck();\n const isCheckmate = game.isCheckmate();\n const isDraw = game.isDraw();\n const isStalemate = game.isStalemate();\n const isThreefoldRepetition = game.isThreefoldRepetition();\n const isInsufficientMaterial = game.isInsufficientMaterial();\n const isGameOver = game.isGameOver();\n const hasPlayerWon = isOpponentTurn && isGameOver && !isDraw;\n const hasPlayerLost = isPlayerTurn && isGameOver && !isDraw;\n const isDrawn = game.isDraw();\n return {\n turn,\n isPlayerTurn,\n isOpponentTurn,\n moveNumber,\n lastMove,\n isCheck,\n isCheckmate,\n isDraw,\n isStalemate,\n isThreefoldRepetition,\n isInsufficientMaterial,\n isGameOver,\n isDrawn,\n hasPlayerWon,\n hasPlayerLost,\n };\n};\n\nexport type GameInfo = ReturnType<typeof getGameInfo>;\n\nexport const isLegalMove = (\n game: Chess,\n move: Parameters<Chess[\"move\"]>[0],\n) => {\n try {\n const copy = cloneGame(game);\n copy.move(move);\n return true;\n } catch (e) {\n return false;\n }\n};\n\nexport const requiresPromotion = (\n game: Chess,\n move: Parameters<Chess[\"move\"]>[0],\n) => {\n if (!game) {\n throw new Error(\"Game is required\");\n }\n\n try {\n const copy = cloneGame(game);\n const result = copy.move(move);\n\n return result.flags.indexOf(\"p\") !== -1;\n } catch (e) {\n if (e instanceof Error && e.message.includes(\"Invalid move\")) {\n return false;\n }\n throw e;\n }\n};\n\nexport const getDestinationSquares = (game: Chess, square: Square) => {\n const moves = game.moves({ square, verbose: true });\n return moves.map((move) => move.to);\n};\n\nexport const getCurrentFen = (\n fen: string | undefined,\n game: Chess,\n currentMoveIndex: number,\n) => {\n const tempGame = new Chess();\n if (currentMoveIndex === -1) {\n if (fen) {\n try {\n tempGame.load(fen);\n } catch (e) {\n console.error(\"Failed to load FEN in getCurrentFen:\", fen, e);\n }\n }\n } else {\n const moves = game.history().slice(0, currentMoveIndex + 1);\n\n if (fen) {\n try {\n tempGame.load(fen);\n } catch (e) {\n console.error(\"Failed to load FEN in getCurrentFen:\", fen, e);\n }\n }\n moves.forEach((move) => tempGame.move(move));\n }\n return tempGame.fen();\n};\n","import React from \"react\";\nimport { useChessGame } from \"./useChessGame\";\n\nexport const ChessGameContext = React.createContext<ReturnType<\n typeof useChessGame\n> | null>(null);\n\nexport const useChessGameContext = () => {\n const context = React.useContext(ChessGameContext);\n if (!context) {\n throw new Error(\n `useChessGameContext must be used within a ChessGame component. Make sure your component is wrapped with <ChessGame.Root> or ensure the ChessGame component is properly rendered in the component tree.`,\n );\n }\n return context;\n};\n\nexport type ChessGameContextType = ReturnType<typeof useChessGame>;\n","import React, { createContext, useContext } from \"react\";\nimport type { ChessGameTheme } from \"./types\";\nimport { defaultGameTheme } from \"./defaults\";\n\n/**\n * Context for ChessGame theme\n */\nexport const ChessGameThemeContext =\n createContext<ChessGameTheme>(defaultGameTheme);\n\n/**\n * Hook to access the current ChessGame theme.\n * Returns the default theme if no ThemeProvider is present.\n */\nexport const useChessGameTheme = (): ChessGameTheme => {\n return useContext(ChessGameThemeContext);\n};\n\nexport interface ThemeProviderProps {\n theme: ChessGameTheme;\n children: React.ReactNode;\n}\n\n/**\n * Internal provider component used by Root when a theme prop is provided.\n * This is not exported directly - users pass theme via Root's theme prop.\n */\nexport const ThemeProvider: React.FC<ThemeProviderProps> = ({\n theme,\n children,\n}) => {\n return (\n <ChessGameThemeContext.Provider value={theme}>\n {children}\n </ChessGameThemeContext.Provider>\n );\n};\n","import type { ChessGameTheme } from \"./types\";\n\n/**\n * Default theme for ChessGame component.\n * These values match the original hardcoded colors for backward compatibility.\n */\nexport const defaultGameTheme: ChessGameTheme = {\n board: {\n lightSquare: { backgroundColor: \"#f0d9b5\" },\n darkSquare: { backgroundColor: \"#b58863\" },\n },\n state: {\n lastMove: \"rgba(255, 255, 0, 0.5)\",\n check: \"rgba(255, 0, 0, 0.5)\",\n activeSquare: \"rgba(255, 255, 0, 0.5)\",\n dropSquare: { backgroundColor: \"rgba(255, 255, 0, 0.4)\" },\n },\n indicators: {\n move: \"rgba(0, 0, 0, 0.1)\",\n capture: \"rgba(1, 0, 0, 0.1)\",\n },\n};\n","import { merge } from \"lodash\";\nimport type { ChessGameTheme, PartialChessGameTheme } from \"./types\";\nimport { defaultGameTheme } from \"./defaults\";\n\n/**\n * Deep merges a partial theme with the default theme.\n * Allows users to override only specific theme properties while keeping defaults for the rest.\n *\n * @param partialTheme - Partial theme with only the properties to override\n * @returns Complete theme with overridden properties merged with defaults\n *\n * @example\n * ```typescript\n * const customTheme = mergeTheme({\n * state: { lastMove: \"rgba(100, 200, 100, 0.6)\" }\n * });\n * // Returns full theme with only lastMove color changed\n * ```\n */\nexport const mergeTheme = (\n partialTheme?: PartialChessGameTheme,\n): ChessGameTheme => {\n if (!partialTheme) {\n return { ...defaultGameTheme };\n }\n\n return merge({}, defaultGameTheme, partialTheme);\n};\n\n/**\n * Deep merges a partial theme with a base theme.\n * Useful when extending an existing theme.\n *\n * @param baseTheme - The base theme to extend\n * @param partialTheme - Partial theme with properties to override\n * @returns Complete theme with overridden properties\n */\nexport const mergeThemeWith = (\n baseTheme: ChessGameTheme,\n partialTheme?: PartialChessGameTheme,\n): ChessGameTheme => {\n if (!partialTheme) {\n return { ...baseTheme };\n }\n\n return merge({}, baseTheme, partialTheme);\n};\n","import React from \"react\";\nimport {\n Chessboard,\n ChessboardOptions,\n defaultPieces,\n chessColumnToColumnIndex,\n} from \"react-chessboard\";\nimport { Move, Square } from \"chess.js\";\nimport {\n getCustomSquareStyles,\n deepMergeChessboardOptions,\n} from \"../../../utils/board\";\nimport { isLegalMove, requiresPromotion } from \"../../../utils/chess\";\nimport { useChessGameContext } from \"../../../hooks/useChessGameContext\";\nimport { useChessGameTheme } from \"../../../theme/context\";\n\nexport interface ChessGameProps {\n options?: ChessboardOptions;\n}\n\nexport const Board: React.FC<ChessGameProps> = ({ options = {} }) => {\n const gameContext = useChessGameContext();\n const theme = useChessGameTheme();\n\n if (!gameContext) {\n throw new Error(\"ChessGameContext not found\");\n }\n\n const {\n game,\n currentFen,\n orientation,\n info,\n isLatestMove,\n methods: { makeMove },\n } = gameContext;\n\n const { turn, isGameOver } = info;\n\n const [activeSquare, setActiveSquare] = React.useState<Square | null>(null);\n\n const [promotionMove, setPromotionMove] =\n React.useState<Partial<Move> | null>(null);\n\n const onSquareClick = (square: Square) => {\n if (isGameOver) {\n return;\n }\n\n if (activeSquare === null) {\n const squadreInfo = game.get(square);\n if (squadreInfo && squadreInfo.color === turn) {\n return setActiveSquare(square);\n }\n return;\n }\n\n if (\n !isLegalMove(game, {\n from: activeSquare,\n to: square,\n promotion: \"q\",\n })\n ) {\n return setActiveSquare(null);\n }\n\n if (\n requiresPromotion(game, {\n from: activeSquare,\n to: square,\n promotion: \"q\",\n })\n ) {\n return setPromotionMove({\n from: activeSquare,\n to: square,\n });\n }\n\n setActiveSquare(null);\n makeMove({\n from: activeSquare,\n to: square,\n });\n };\n\n const onPromotionPieceSelect = (piece: string): void => {\n if (promotionMove?.from && promotionMove?.to) {\n makeMove({\n from: promotionMove.from,\n to: promotionMove.to,\n promotion: piece.toLowerCase(),\n });\n setPromotionMove(null);\n }\n };\n\n const onSquareRightClick = () => {\n setActiveSquare(null);\n setPromotionMove(null);\n };\n\n // Calculate square width for precise positioning\n const squareWidth = React.useMemo(() => {\n if (typeof document === \"undefined\") return 80;\n const squareElement = document.querySelector(`[data-square]`);\n return squareElement?.getBoundingClientRect()?.width ?? 80;\n }, [promotionMove]);\n\n // Calculate promotion square position\n const promotionSquareLeft = React.useMemo(() => {\n if (!promotionMove?.to) return 0;\n const column = promotionMove.to.match(/^[a-h]/)?.[0] ?? \"a\";\n return (\n squareWidth *\n chessColumnToColumnIndex(\n column,\n 8,\n orientation === \"b\" ? \"black\" : \"white\",\n )\n );\n }, [promotionMove, squareWidth, orientation]);\n\n const baseOptions: ChessboardOptions = {\n squareStyles: getCustomSquareStyles(game, info, activeSquare, theme),\n boardOrientation: orientation === \"b\" ? \"black\" : \"white\",\n position: currentFen,\n showNotation: true,\n showAnimations: isLatestMove,\n lightSquareStyle: theme.board.lightSquare,\n darkSquareStyle: theme.board.darkSquare,\n canDragPiece: ({ piece }) => {\n if (isGameOver) return false;\n return piece.pieceType[0] === turn;\n },\n dropSquareStyle: theme.state.dropSquare,\n onPieceDrag: ({ piece, square }) => {\n if (piece.pieceType[0] === turn) {\n setActiveSquare(square as Square);\n }\n },\n onPieceDrop: ({ sourceSquare, targetSquare }) => {\n setActiveSquare(null);\n const moveData = {\n from: sourceSquare as Square,\n to: targetSquare as Square,\n };\n\n // Check if promotion is needed\n if (requiresPromotion(game, { ...moveData, promotion: \"q\" })) {\n setPromotionMove(moveData);\n return false; // Prevent the move until promotion is selected\n }\n\n return makeMove(moveData);\n },\n onSquareClick: ({ square }) => {\n if (square.match(/^[a-h][1-8]$/)) {\n onSquareClick(square as Square);\n }\n },\n onSquareRightClick: onSquareRightClick,\n allowDrawingArrows: true,\n animationDurationInMs: game.history().length === 0 ? 0 : 300,\n };\n\n const mergedOptions = deepMergeChessboardOptions(baseOptions, options);\n\n return (\n <div style={{ position: \"relative\" }}>\n <Chessboard options={mergedOptions} />\n {promotionMove && (\n <>\n {/* Backdrop overlay - click to cancel */}\n <div\n onClick={() => setPromotionMove(null)}\n onContextMenu={(e) => {\n e.preventDefault();\n setPromotionMove(null);\n }}\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n backgroundColor: \"rgba(0, 0, 0, 0.1)\",\n zIndex: 1000,\n }}\n />\n {/* Promotion piece selection */}\n <div\n style={{\n position: \"absolute\",\n top: promotionMove.to?.[1]?.includes(\"8\") ? 0 : \"auto\",\n bottom: promotionMove.to?.[1].includes(\"1\") ? 0 : \"auto\",\n left: promotionSquareLeft,\n backgroundColor: \"white\",\n width: squareWidth,\n zIndex: 1001,\n display: \"flex\",\n flexDirection: \"column\",\n boxShadow: \"0 0 10px 0 rgba(0, 0, 0, 0.5)\",\n }}\n >\n {[\"q\", \"r\", \"n\", \"b\"].map((piece) => (\n <button\n key={piece}\n onClick={() => onPromotionPieceSelect(piece)}\n onContextMenu={(e) => {\n e.preventDefault();\n }}\n style={{\n width: \"100%\",\n aspectRatio: \"1\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: 0,\n border: \"none\",\n cursor: \"pointer\",\n backgroundColor: \"white\",\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = \"#f0f0f0\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = \"white\";\n }}\n >\n {defaultPieces[\n `${turn}${piece.toUpperCase()}` as keyof typeof defaultPieces\n ]()}\n </button>\n ))}\n </div>\n </>\n )}\n </div>\n );\n};\n","import { type Chess, type Square } from \"chess.js\";\nimport { type CSSProperties } from \"react\";\nimport { merge } from \"lodash\";\nimport type { ChessboardOptions } from \"react-chessboard\";\nimport { getDestinationSquares, type GameInfo } from \"./chess\";\nimport type { ChessGameTheme } from \"../theme/types\";\nimport { defaultGameTheme } from \"../theme/defaults\";\n\n/**\n * Generates custom square styles based on game state and theme.\n *\n * @param game - Chess.js game instance\n * @param info - Game info containing lastMove, isCheck, turn\n * @param activeSquare - Currently selected square (if any)\n * @param theme - Theme configuration (defaults to defaultGameTheme)\n * @returns Record of square names to CSS properties\n */\nexport const getCustomSquareStyles = (\n game: Chess,\n info: GameInfo,\n activeSquare: Square | null,\n theme: ChessGameTheme = defaultGameTheme,\n) => {\n const customSquareStyles: Record<string, CSSProperties> = {};\n\n const { lastMove, isCheck, turn } = info;\n\n if (lastMove) {\n customSquareStyles[lastMove.from] = {\n backgroundColor: theme.state.lastMove,\n };\n customSquareStyles[lastMove.to] = {\n backgroundColor: theme.state.lastMove,\n };\n }\n\n if (activeSquare) {\n customSquareStyles[activeSquare] = {\n backgroundColor: theme.state.activeSquare,\n };\n }\n\n if (activeSquare) {\n const destinationSquares = getDestinationSquares(game, activeSquare);\n destinationSquares.forEach((square) => {\n customSquareStyles[square] = {\n background:\n game.get(square) && game.get(square)?.color !== turn\n ? `radial-gradient(circle, ${theme.indicators.capture} 85%, transparent 85%)`\n : `radial-gradient(circle, ${theme.indicators.move} 25%, transparent 25%)`,\n };\n });\n }\n\n if (isCheck) {\n game.board().forEach((row) => {\n return row.forEach((square) => {\n if (square?.type === \"k\" && square?.color === info.turn) {\n customSquareStyles[square.square] = {\n backgroundColor: theme.state.check,\n };\n }\n });\n });\n }\n return customSquareStyles;\n};\n\n/**\n * Smart deep merge for ChessboardOptions that handles different property types appropriately:\n * - Functions: Overwrite (custom functions replace base functions)\n * - Objects: Deep merge (nested objects merge recursively)\n * - Primitives: Overwrite (custom values replace base values)\n *\n * This ensures that computed options (like squareStyles with move highlighting) are preserved\n * while allowing custom options to extend or override them intelligently.\n *\n * @param baseOptions - The computed base options (e.g., computed squareStyles, event handlers)\n * @param customOptions - Custom options provided by the user\n * @returns Intelligently merged ChessboardOptions\n */\nexport const deepMergeChessboardOptions = (\n baseOptions: ChessboardOptions,\n customOptions?: Partial<ChessboardOptions>,\n): ChessboardOptions => {\n if (!customOptions) {\n return { ...baseOptions }; // Return a new object even when no custom options\n }\n\n const result = merge({}, baseOptions, customOptions, {\n customizer: (_objValue: unknown, srcValue: unknown) => {\n // Functions should always overwrite (not merge)\n // This is important for event handlers like onSquareClick, onPieceDrop, etc.\n if (typeof srcValue === \"function\") {\n return srcValue;\n }\n\n // For arrays, we typically want to overwrite rather than merge\n // This avoids unexpected behavior with array concatenation\n if (Array.isArray(srcValue)) {\n return srcValue;\n }\n\n // Let lodash handle objects with default deep merge behavior\n // This will properly merge nested objects like squareStyles, dropSquareStyle, etc.\n return undefined; // Use default merge behavior\n },\n });\n\n // Clean up any unwanted properties that lodash might add\n delete (result as Record<string, unknown>).customizer;\n\n return result;\n};\n","import { useMemo } from \"react\";\nimport { defaultSounds, type Sound } from \"../../../assets/sounds\";\nimport { useBoardSounds } from \"../../../hooks/useBoardSounds\";\n\nexport type SoundsProps = {\n sounds?: Partial<Record<Sound, string>>;\n};\n\nexport const Sounds: React.FC<SoundsProps> = ({ sounds }) => {\n const customSoundsAudios = useMemo(() => {\n if (typeof window === \"undefined\" || typeof Audio === \"undefined\") {\n return {} as Record<Sound, HTMLAudioElement>;\n }\n\n return Object.entries({ ...defaultSounds, sounds }).reduce(\n (acc, [name, base64]) => {\n acc[name as Sound] = new Audio(`data:audio/wav;base64,${base64}`);\n return acc;\n },\n {} as Record<Sound, HTMLAudioElement>,\n );\n }, [sounds]);\n useBoardSounds(customSoundsAudios);\n return null;\n};\n","export type Sound = \"check\" | \"move\" | \"capture\" | \"gameOver\";\nexport type Sounds = Record<Sound, HTMLAudioElement>;\n\nconst SILENCE = \"Li4vU2lsZW5jZS5vZ2c=\";\n\nexport const defaultSounds: Record<Sound, string> = {\n move: \"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\",\n capture:\n \"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\",\n check: SILENCE,\n gameOver:\n \"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\",\n};\n","import { useEffect } from \"react\";\nimport { useChessGameContext } from \"./useChessGameContext\";\nimport { type Sound } from \"../assets/sounds\";\n\nconst playSound = async (audioElement: HTMLAudioElement) => {\n try {\n await audioElement.play();\n } catch (error) {\n console.warn(\"Failed to play sound:\", (error as Error).message);\n }\n};\n\nexport const useBoardSounds = (sounds: Record<Sound, HTMLAudioElement>) => {\n const {\n info: { lastMove, isCheckmate },\n } = useChessGameContext();\n\n useEffect(() => {\n if (Object.keys(sounds).length === 0) {\n return;\n }\n\n if (isCheckmate && sounds.gameOver) {\n playSound(sounds.gameOver);\n return;\n }\n\n if (lastMove?.captured && sounds.capture) {\n playSound(sounds.capture);\n return;\n }\n\n if (lastMove && sounds.move) {\n playSound(sounds.move);\n }\n }, [lastMove]);\n};\n","import { useEffect } from \"react\";\nimport {\n defaultKeyboardControls,\n KeyboardControls,\n} from \"../components/ChessGame/parts/KeyboardControls\";\nimport { useChessGameContext } from \"./useChessGameContext\";\n\nexport const useKeyboardControls = (controls?: KeyboardControls) => {\n const gameContext = useChessGameContext();\n if (!gameContext) {\n throw new Error(\"ChessGameContext not found\");\n }\n const keyboardControls = { ...defaultKeyboardControls, ...controls };\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n const handler = keyboardControls[event.key];\n if (handler) {\n event.preventDefault();\n handler(gameContext);\n }\n };\n window.addEventListener(\"keydown\", handleKeyDown);\n return () => {\n window.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [gameContext]);\n return null;\n};\n","import {\n ChessGameContextType,\n useChessGameContext,\n} from \"../../../hooks/useChessGameContext\";\nimport { useKeyboardControls } from \"../../../hooks/useKeyboardControls\";\n\nexport type KeyboardControls = Record<\n string,\n (context: ChessGameContextType) => void\n>;\n\nexport const defaultKeyboardControls: KeyboardControls = {\n ArrowLeft: (context) => context.methods.goToPreviousMove(),\n ArrowRight: (context) => context.methods.goToNextMove(),\n ArrowUp: (context) => context.methods.goToStart(),\n ArrowDown: (context) => context.methods.goToEnd(),\n};\n\ntype KeyboardControlsProps = {\n controls?: KeyboardControls;\n};\n\nexport const KeyboardControls: React.FC<KeyboardControlsProps> = ({\n controls,\n}) => {\n const gameContext = useChessGameContext();\n if (!gameContext) {\n throw new Error(\"ChessGameContext not found\");\n }\n const keyboardControls = { ...defaultKeyboardControls, ...controls };\n useKeyboardControls(keyboardControls);\n return null;\n};\n","import { Root } from \"./parts/Root\";\nimport { Board } from \"./parts/Board\";\nimport { Sounds } from \"./parts/Sounds\";\nimport { KeyboardControls } from \"./parts/KeyboardControls\";\n\nexport const ChessGame = {\n Root,\n Board,\n Sounds,\n KeyboardControls,\n};\n","import type { ChessGameTheme } from \"./types\";\n\n/**\n * Lichess-inspired theme with green highlights\n */\nexport const lichessTheme: ChessGameTheme = {\n board: {\n lightSquare: { backgroundColor: \"#f0d9b5\" },\n darkSquare: { backgroundColor: \"#b58863\" },\n },\n state: {\n lastMove: \"rgba(155, 199, 0, 0.41)\",\n check: \"rgba(255, 0, 0, 0.5)\",\n activeSquare: \"rgba(20, 85, 30, 0.5)\",\n dropSquare: { backgroundColor: \"rgba(20, 85, 30, 0.3)\" },\n },\n indicators: {\n move: \"rgba(20, 85, 30, 0.3)\",\n capture: \"rgba(20, 85, 30, 0.3)\",\n },\n};\n\n/**\n * Chess.com-inspired theme with green board and yellow highlights\n */\nexport const chessComTheme: ChessGameTheme = {\n board: {\n lightSquare: { backgroundColor: \"#ebecd0\" },\n darkSquare: { backgroundColor: \"#779556\" },\n },\n state: {\n lastMove: \"rgba(255, 255, 0, 0.5)\",\n check: \"rgba(255, 0, 0, 0.7)\",\n activeSquare: \"rgba(255, 255, 0, 0.5)\",\n dropSquare: { backgroundColor: \"rgba(255, 255, 0, 0.4)\" },\n },\n indicators: {\n move: \"rgba(0, 0, 0, 0.1)\",\n capture: \"rgba(0, 0, 0, 0.1)\",\n },\n};\n","// Types\nexport type {\n ChessGameTheme,\n BoardTheme,\n StateTheme,\n IndicatorTheme,\n PartialChessGameTheme,\n DeepPartial,\n} from \"./types\";\n\n// Default theme\nexport { defaultGameTheme } from \"./defaults\";\n\n// Preset themes\nexport { lichessTheme, chessComTheme } from \"./presets\";\n\n// All themes as a single object\nimport { defaultGameTheme } from \"./defaults\";\nimport { lichessTheme, chessComTheme } from \"./presets\";\n\nexport const themes = {\n default: defaultGameTheme,\n lichess: lichessTheme,\n chessCom: chessComTheme,\n} as const;\n\n// Utilities\nexport { mergeTheme, mergeThemeWith } from \"./utils\";\n\n// Context and hook\nexport {\n ChessGameThemeContext,\n useChessGameTheme,\n ThemeProvider,\n} from \"./context\";\nexport type { ThemeProviderProps } from \"./context\";\n"],"mappings":"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","names":["React","Chess","Chess","fen","orientation","React","React","React","React","React","merge","merge","React","_a","useEffect","useEffect","useEffect","useEffect","KeyboardControls","KeyboardControls"]}
|
package/package.json
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-chess-tools/react-chess-game",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "react-chess-game is a React component bridging chess.js with react-chessboard to offer a full-featured, ready-to-integrate chess board experience.",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"require": "./dist/index.cjs",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"main": "./dist/index.cjs",
|
|
15
|
+
"module": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
8
17
|
"scripts": {
|
|
9
18
|
"build": "tsup src/index.ts",
|
|
10
19
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -30,14 +39,14 @@
|
|
|
30
39
|
"author": "Daniele Cammareri <daniele.cammareri@gmail.com>",
|
|
31
40
|
"license": "MIT",
|
|
32
41
|
"dependencies": {
|
|
33
|
-
"chess.js": "^1.
|
|
42
|
+
"chess.js": "^1.4.0",
|
|
34
43
|
"lodash": "^4.17.21",
|
|
35
|
-
"react-chessboard": "^5.
|
|
44
|
+
"react-chessboard": "^5.8.6"
|
|
36
45
|
},
|
|
37
46
|
"devDependencies": {
|
|
38
|
-
"@types/lodash": "^4.17.
|
|
39
|
-
"react": "^19.
|
|
40
|
-
"react-dom": "^19.
|
|
47
|
+
"@types/lodash": "^4.17.21",
|
|
48
|
+
"react": "^19.2.3",
|
|
49
|
+
"react-dom": "^19.2.3"
|
|
41
50
|
},
|
|
42
51
|
"peerDependencies": {
|
|
43
52
|
"react": ">=16.14.0",
|