@react-chess-tools/react-chess-game 0.5.2 → 1.0.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +399 -0
  3. package/dist/index.cjs +785 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +278 -0
  6. package/dist/index.d.ts +278 -0
  7. package/dist/{index.mjs → index.js} +339 -196
  8. package/dist/index.js.map +1 -0
  9. package/package.json +19 -9
  10. package/src/components/ChessGame/Theme.stories.tsx +242 -0
  11. package/src/components/ChessGame/ThemePresets.stories.tsx +144 -0
  12. package/src/components/ChessGame/parts/Board.tsx +215 -204
  13. package/src/components/ChessGame/parts/KeyboardControls.tsx +9 -0
  14. package/src/components/ChessGame/parts/Root.tsx +13 -1
  15. package/src/components/ChessGame/parts/Sounds.tsx +9 -0
  16. package/src/components/ChessGame/parts/__tests__/Board.test.tsx +122 -0
  17. package/src/components/ChessGame/parts/__tests__/KeyboardControls.test.tsx +34 -0
  18. package/src/components/ChessGame/parts/__tests__/Root.test.tsx +50 -0
  19. package/src/components/ChessGame/parts/__tests__/Sounds.test.tsx +22 -0
  20. package/src/docs/Theming.mdx +281 -0
  21. package/src/hooks/useChessGame.ts +23 -7
  22. package/src/index.ts +19 -0
  23. package/src/theme/__tests__/context.test.tsx +60 -0
  24. package/src/theme/__tests__/defaults.test.ts +61 -0
  25. package/src/theme/__tests__/utils.test.ts +106 -0
  26. package/src/theme/context.tsx +37 -0
  27. package/src/theme/defaults.ts +22 -0
  28. package/src/theme/index.ts +36 -0
  29. package/src/theme/presets.ts +41 -0
  30. package/src/theme/types.ts +56 -0
  31. package/src/theme/utils.ts +47 -0
  32. package/src/utils/__tests__/board.test.ts +118 -0
  33. package/src/utils/board.ts +18 -9
  34. package/src/utils/chess.ts +25 -5
  35. package/README.MD +0 -190
  36. package/coverage/clover.xml +0 -6
  37. package/coverage/coverage-final.json +0 -1
  38. package/coverage/lcov-report/base.css +0 -224
  39. package/coverage/lcov-report/block-navigation.js +0 -87
  40. package/coverage/lcov-report/favicon.png +0 -0
  41. package/coverage/lcov-report/index.html +0 -101
  42. package/coverage/lcov-report/prettify.css +0 -1
  43. package/coverage/lcov-report/prettify.js +0 -2
  44. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  45. package/coverage/lcov-report/sorter.js +0 -196
  46. package/coverage/lcov.info +0 -0
  47. package/dist/index.d.mts +0 -158
  48. package/dist/index.mjs.map +0 -1
package/dist/index.cjs ADDED
@@ -0,0 +1,785 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ ChessGame: () => ChessGame,
34
+ ChessGameThemeContext: () => ChessGameThemeContext,
35
+ chessComTheme: () => chessComTheme,
36
+ deepMergeChessboardOptions: () => deepMergeChessboardOptions,
37
+ defaultGameTheme: () => defaultGameTheme,
38
+ lichessTheme: () => lichessTheme,
39
+ mergeTheme: () => mergeTheme,
40
+ mergeThemeWith: () => mergeThemeWith,
41
+ themes: () => themes,
42
+ useChessGame: () => useChessGame,
43
+ useChessGameContext: () => useChessGameContext,
44
+ useChessGameTheme: () => useChessGameTheme
45
+ });
46
+ module.exports = __toCommonJS(index_exports);
47
+
48
+ // src/components/ChessGame/parts/Root.tsx
49
+ var import_react4 = __toESM(require("react"), 1);
50
+
51
+ // src/hooks/useChessGame.ts
52
+ var import_react = __toESM(require("react"), 1);
53
+ var import_chess2 = require("chess.js");
54
+
55
+ // src/utils/chess.ts
56
+ var import_chess = require("chess.js");
57
+ var import_lodash = __toESM(require("lodash"), 1);
58
+ var cloneGame = (game) => {
59
+ try {
60
+ const copy = new import_chess.Chess();
61
+ const pgn = game == null ? void 0 : game.pgn();
62
+ if (pgn) {
63
+ copy.loadPgn(pgn);
64
+ }
65
+ return copy;
66
+ } catch (e) {
67
+ console.error("Failed to clone game:", e);
68
+ return new import_chess.Chess();
69
+ }
70
+ };
71
+ var getGameInfo = (game, orientation) => {
72
+ const turn = game.turn();
73
+ const isPlayerTurn = turn === orientation;
74
+ const isOpponentTurn = !isPlayerTurn;
75
+ const moveNumber = game.history().length;
76
+ const lastMove = import_lodash.default.last(game.history({ verbose: true }));
77
+ const isCheck = game.isCheck();
78
+ const isCheckmate = game.isCheckmate();
79
+ const isDraw = game.isDraw();
80
+ const isStalemate = game.isStalemate();
81
+ const isThreefoldRepetition = game.isThreefoldRepetition();
82
+ const isInsufficientMaterial = game.isInsufficientMaterial();
83
+ const isGameOver = game.isGameOver();
84
+ const hasPlayerWon = isOpponentTurn && isGameOver && !isDraw;
85
+ const hasPlayerLost = isPlayerTurn && isGameOver && !isDraw;
86
+ const isDrawn = game.isDraw();
87
+ return {
88
+ turn,
89
+ isPlayerTurn,
90
+ isOpponentTurn,
91
+ moveNumber,
92
+ lastMove,
93
+ isCheck,
94
+ isCheckmate,
95
+ isDraw,
96
+ isStalemate,
97
+ isThreefoldRepetition,
98
+ isInsufficientMaterial,
99
+ isGameOver,
100
+ isDrawn,
101
+ hasPlayerWon,
102
+ hasPlayerLost
103
+ };
104
+ };
105
+ var isLegalMove = (game, move) => {
106
+ try {
107
+ const copy = cloneGame(game);
108
+ copy.move(move);
109
+ return true;
110
+ } catch (e) {
111
+ return false;
112
+ }
113
+ };
114
+ var requiresPromotion = (game, move) => {
115
+ if (!game) {
116
+ throw new Error("Game is required");
117
+ }
118
+ try {
119
+ const copy = cloneGame(game);
120
+ const result = copy.move(move);
121
+ return result.flags.indexOf("p") !== -1;
122
+ } catch (e) {
123
+ if (e instanceof Error && e.message.includes("Invalid move")) {
124
+ return false;
125
+ }
126
+ throw e;
127
+ }
128
+ };
129
+ var getDestinationSquares = (game, square) => {
130
+ const moves = game.moves({ square, verbose: true });
131
+ return moves.map((move) => move.to);
132
+ };
133
+ var getCurrentFen = (fen, game, currentMoveIndex) => {
134
+ const tempGame = new import_chess.Chess();
135
+ if (currentMoveIndex === -1) {
136
+ if (fen) {
137
+ try {
138
+ tempGame.load(fen);
139
+ } catch (e) {
140
+ console.error("Failed to load FEN in getCurrentFen:", fen, e);
141
+ }
142
+ }
143
+ } else {
144
+ const moves = game.history().slice(0, currentMoveIndex + 1);
145
+ if (fen) {
146
+ try {
147
+ tempGame.load(fen);
148
+ } catch (e) {
149
+ console.error("Failed to load FEN in getCurrentFen:", fen, e);
150
+ }
151
+ }
152
+ moves.forEach((move) => tempGame.move(move));
153
+ }
154
+ return tempGame.fen();
155
+ };
156
+
157
+ // src/hooks/useChessGame.ts
158
+ var useChessGame = ({
159
+ fen,
160
+ orientation: initialOrientation
161
+ } = {}) => {
162
+ const [game, setGame] = import_react.default.useState(() => {
163
+ try {
164
+ return new import_chess2.Chess(fen);
165
+ } catch (e) {
166
+ console.error("Invalid FEN:", fen, e);
167
+ return new import_chess2.Chess();
168
+ }
169
+ });
170
+ (0, import_react.useEffect)(() => {
171
+ try {
172
+ setGame(new import_chess2.Chess(fen));
173
+ } catch (e) {
174
+ console.error("Invalid FEN:", fen, e);
175
+ setGame(new import_chess2.Chess());
176
+ }
177
+ }, [fen]);
178
+ const [orientation, setOrientation] = import_react.default.useState(
179
+ initialOrientation ?? "w"
180
+ );
181
+ const [currentMoveIndex, setCurrentMoveIndex] = import_react.default.useState(-1);
182
+ const history = import_react.default.useMemo(() => game.history(), [game]);
183
+ const isLatestMove = import_react.default.useMemo(
184
+ () => currentMoveIndex === history.length - 1 || currentMoveIndex === -1,
185
+ [currentMoveIndex, history.length]
186
+ );
187
+ const info = import_react.default.useMemo(
188
+ () => getGameInfo(game, orientation),
189
+ [game, orientation]
190
+ );
191
+ const currentFen = import_react.default.useMemo(
192
+ () => getCurrentFen(fen, game, currentMoveIndex),
193
+ [game, currentMoveIndex]
194
+ );
195
+ const currentPosition = import_react.default.useMemo(
196
+ () => game.history()[currentMoveIndex],
197
+ [game, currentMoveIndex]
198
+ );
199
+ const setPosition = import_react.default.useCallback((fen2, orientation2) => {
200
+ try {
201
+ const newGame = new import_chess2.Chess();
202
+ newGame.load(fen2);
203
+ setOrientation(orientation2);
204
+ setGame(newGame);
205
+ setCurrentMoveIndex(-1);
206
+ } catch (e) {
207
+ console.error("Failed to load FEN:", fen2, e);
208
+ }
209
+ }, []);
210
+ const makeMove = import_react.default.useCallback(
211
+ (move) => {
212
+ if (!isLatestMove) {
213
+ return false;
214
+ }
215
+ try {
216
+ const copy = cloneGame(game);
217
+ copy.move(move);
218
+ setGame(copy);
219
+ setCurrentMoveIndex(copy.history().length - 1);
220
+ return true;
221
+ } catch (e) {
222
+ return false;
223
+ }
224
+ },
225
+ [isLatestMove, game]
226
+ );
227
+ const flipBoard = import_react.default.useCallback(() => {
228
+ setOrientation((orientation2) => orientation2 === "w" ? "b" : "w");
229
+ }, []);
230
+ const goToMove = import_react.default.useCallback(
231
+ (moveIndex) => {
232
+ if (moveIndex < -1 || moveIndex >= history.length) return;
233
+ setCurrentMoveIndex(moveIndex);
234
+ },
235
+ [history.length]
236
+ );
237
+ const goToStart = import_react.default.useCallback(() => goToMove(-1), []);
238
+ const goToEnd = import_react.default.useCallback(
239
+ () => goToMove(history.length - 1),
240
+ [history.length]
241
+ );
242
+ const goToPreviousMove = import_react.default.useCallback(
243
+ () => goToMove(currentMoveIndex - 1),
244
+ [currentMoveIndex]
245
+ );
246
+ const goToNextMove = import_react.default.useCallback(
247
+ () => goToMove(currentMoveIndex + 1),
248
+ [currentMoveIndex]
249
+ );
250
+ const methods = import_react.default.useMemo(
251
+ () => ({
252
+ makeMove,
253
+ setPosition,
254
+ flipBoard,
255
+ goToMove,
256
+ goToStart,
257
+ goToEnd,
258
+ goToPreviousMove,
259
+ goToNextMove
260
+ }),
261
+ [
262
+ makeMove,
263
+ setPosition,
264
+ flipBoard,
265
+ goToMove,
266
+ goToStart,
267
+ goToEnd,
268
+ goToPreviousMove,
269
+ goToNextMove
270
+ ]
271
+ );
272
+ return {
273
+ game,
274
+ currentFen,
275
+ currentPosition,
276
+ orientation,
277
+ currentMoveIndex,
278
+ isLatestMove,
279
+ info,
280
+ methods
281
+ };
282
+ };
283
+
284
+ // src/hooks/useChessGameContext.ts
285
+ var import_react2 = __toESM(require("react"), 1);
286
+ var ChessGameContext = import_react2.default.createContext(null);
287
+ var useChessGameContext = () => {
288
+ const context = import_react2.default.useContext(ChessGameContext);
289
+ if (!context) {
290
+ throw new Error(
291
+ `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.`
292
+ );
293
+ }
294
+ return context;
295
+ };
296
+
297
+ // src/theme/context.tsx
298
+ var import_react3 = __toESM(require("react"), 1);
299
+
300
+ // src/theme/defaults.ts
301
+ var defaultGameTheme = {
302
+ board: {
303
+ lightSquare: { backgroundColor: "#f0d9b5" },
304
+ darkSquare: { backgroundColor: "#b58863" }
305
+ },
306
+ state: {
307
+ lastMove: "rgba(255, 255, 0, 0.5)",
308
+ check: "rgba(255, 0, 0, 0.5)",
309
+ activeSquare: "rgba(255, 255, 0, 0.5)",
310
+ dropSquare: { backgroundColor: "rgba(255, 255, 0, 0.4)" }
311
+ },
312
+ indicators: {
313
+ move: "rgba(0, 0, 0, 0.1)",
314
+ capture: "rgba(1, 0, 0, 0.1)"
315
+ }
316
+ };
317
+
318
+ // src/theme/context.tsx
319
+ var ChessGameThemeContext = (0, import_react3.createContext)(defaultGameTheme);
320
+ var useChessGameTheme = () => {
321
+ return (0, import_react3.useContext)(ChessGameThemeContext);
322
+ };
323
+ var ThemeProvider = ({
324
+ theme,
325
+ children
326
+ }) => {
327
+ return /* @__PURE__ */ import_react3.default.createElement(ChessGameThemeContext.Provider, { value: theme }, children);
328
+ };
329
+
330
+ // src/theme/utils.ts
331
+ var import_lodash2 = require("lodash");
332
+ var mergeTheme = (partialTheme) => {
333
+ if (!partialTheme) {
334
+ return { ...defaultGameTheme };
335
+ }
336
+ return (0, import_lodash2.merge)({}, defaultGameTheme, partialTheme);
337
+ };
338
+ var mergeThemeWith = (baseTheme, partialTheme) => {
339
+ if (!partialTheme) {
340
+ return { ...baseTheme };
341
+ }
342
+ return (0, import_lodash2.merge)({}, baseTheme, partialTheme);
343
+ };
344
+
345
+ // src/components/ChessGame/parts/Root.tsx
346
+ var Root = ({
347
+ fen,
348
+ orientation,
349
+ theme,
350
+ children
351
+ }) => {
352
+ const context = useChessGame({ fen, orientation });
353
+ const mergedTheme = import_react4.default.useMemo(() => mergeTheme(theme), [theme]);
354
+ return /* @__PURE__ */ import_react4.default.createElement(ChessGameContext.Provider, { value: context }, /* @__PURE__ */ import_react4.default.createElement(ThemeProvider, { theme: mergedTheme }, children));
355
+ };
356
+ Root.displayName = "ChessGame.Root";
357
+
358
+ // src/components/ChessGame/parts/Board.tsx
359
+ var import_react5 = __toESM(require("react"), 1);
360
+ var import_react_chessboard = require("react-chessboard");
361
+
362
+ // src/utils/board.ts
363
+ var import_lodash3 = require("lodash");
364
+ var getCustomSquareStyles = (game, info, activeSquare, theme = defaultGameTheme) => {
365
+ const customSquareStyles = {};
366
+ const { lastMove, isCheck, turn } = info;
367
+ if (lastMove) {
368
+ customSquareStyles[lastMove.from] = {
369
+ backgroundColor: theme.state.lastMove
370
+ };
371
+ customSquareStyles[lastMove.to] = {
372
+ backgroundColor: theme.state.lastMove
373
+ };
374
+ }
375
+ if (activeSquare) {
376
+ customSquareStyles[activeSquare] = {
377
+ backgroundColor: theme.state.activeSquare
378
+ };
379
+ }
380
+ if (activeSquare) {
381
+ const destinationSquares = getDestinationSquares(game, activeSquare);
382
+ destinationSquares.forEach((square) => {
383
+ var _a;
384
+ customSquareStyles[square] = {
385
+ 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%)`
386
+ };
387
+ });
388
+ }
389
+ if (isCheck) {
390
+ game.board().forEach((row) => {
391
+ return row.forEach((square) => {
392
+ if ((square == null ? void 0 : square.type) === "k" && (square == null ? void 0 : square.color) === info.turn) {
393
+ customSquareStyles[square.square] = {
394
+ backgroundColor: theme.state.check
395
+ };
396
+ }
397
+ });
398
+ });
399
+ }
400
+ return customSquareStyles;
401
+ };
402
+ var deepMergeChessboardOptions = (baseOptions, customOptions) => {
403
+ if (!customOptions) {
404
+ return { ...baseOptions };
405
+ }
406
+ const result = (0, import_lodash3.merge)({}, baseOptions, customOptions, {
407
+ customizer: (_objValue, srcValue) => {
408
+ if (typeof srcValue === "function") {
409
+ return srcValue;
410
+ }
411
+ if (Array.isArray(srcValue)) {
412
+ return srcValue;
413
+ }
414
+ return void 0;
415
+ }
416
+ });
417
+ delete result.customizer;
418
+ return result;
419
+ };
420
+
421
+ // src/components/ChessGame/parts/Board.tsx
422
+ var Board = import_react5.default.forwardRef(
423
+ ({ options = {}, className, style: userStyle, ...rest }, ref) => {
424
+ var _a, _b, _c;
425
+ const gameContext = useChessGameContext();
426
+ const theme = useChessGameTheme();
427
+ if (!gameContext) {
428
+ throw new Error("ChessGameContext not found");
429
+ }
430
+ const {
431
+ game,
432
+ currentFen,
433
+ orientation,
434
+ info,
435
+ isLatestMove,
436
+ methods: { makeMove }
437
+ } = gameContext;
438
+ const { turn, isGameOver } = info;
439
+ const [activeSquare, setActiveSquare] = import_react5.default.useState(null);
440
+ const [promotionMove, setPromotionMove] = import_react5.default.useState(null);
441
+ const onSquareClick = (square) => {
442
+ if (isGameOver) {
443
+ return;
444
+ }
445
+ if (activeSquare === null) {
446
+ const squadreInfo = game.get(square);
447
+ if (squadreInfo && squadreInfo.color === turn) {
448
+ return setActiveSquare(square);
449
+ }
450
+ return;
451
+ }
452
+ if (!isLegalMove(game, {
453
+ from: activeSquare,
454
+ to: square,
455
+ promotion: "q"
456
+ })) {
457
+ return setActiveSquare(null);
458
+ }
459
+ if (requiresPromotion(game, {
460
+ from: activeSquare,
461
+ to: square,
462
+ promotion: "q"
463
+ })) {
464
+ return setPromotionMove({
465
+ from: activeSquare,
466
+ to: square
467
+ });
468
+ }
469
+ setActiveSquare(null);
470
+ makeMove({
471
+ from: activeSquare,
472
+ to: square
473
+ });
474
+ };
475
+ const onPromotionPieceSelect = (piece) => {
476
+ if ((promotionMove == null ? void 0 : promotionMove.from) && (promotionMove == null ? void 0 : promotionMove.to)) {
477
+ makeMove({
478
+ from: promotionMove.from,
479
+ to: promotionMove.to,
480
+ promotion: piece.toLowerCase()
481
+ });
482
+ setPromotionMove(null);
483
+ }
484
+ };
485
+ const onSquareRightClick = () => {
486
+ setActiveSquare(null);
487
+ setPromotionMove(null);
488
+ };
489
+ const squareWidth = import_react5.default.useMemo(() => {
490
+ var _a2;
491
+ if (typeof document === "undefined") return 80;
492
+ const squareElement = document.querySelector(`[data-square]`);
493
+ return ((_a2 = squareElement == null ? void 0 : squareElement.getBoundingClientRect()) == null ? void 0 : _a2.width) ?? 80;
494
+ }, [promotionMove]);
495
+ const promotionSquareLeft = import_react5.default.useMemo(() => {
496
+ var _a2;
497
+ if (!(promotionMove == null ? void 0 : promotionMove.to)) return 0;
498
+ const column = ((_a2 = promotionMove.to.match(/^[a-h]/)) == null ? void 0 : _a2[0]) ?? "a";
499
+ return squareWidth * (0, import_react_chessboard.chessColumnToColumnIndex)(
500
+ column,
501
+ 8,
502
+ orientation === "b" ? "black" : "white"
503
+ );
504
+ }, [promotionMove, squareWidth, orientation]);
505
+ const baseOptions = {
506
+ squareStyles: getCustomSquareStyles(game, info, activeSquare, theme),
507
+ boardOrientation: orientation === "b" ? "black" : "white",
508
+ position: currentFen,
509
+ showNotation: true,
510
+ showAnimations: isLatestMove,
511
+ lightSquareStyle: theme.board.lightSquare,
512
+ darkSquareStyle: theme.board.darkSquare,
513
+ canDragPiece: ({ piece }) => {
514
+ if (isGameOver) return false;
515
+ return piece.pieceType[0] === turn;
516
+ },
517
+ dropSquareStyle: theme.state.dropSquare,
518
+ onPieceDrag: ({ piece, square }) => {
519
+ if (piece.pieceType[0] === turn) {
520
+ setActiveSquare(square);
521
+ }
522
+ },
523
+ onPieceDrop: ({ sourceSquare, targetSquare }) => {
524
+ setActiveSquare(null);
525
+ const moveData = {
526
+ from: sourceSquare,
527
+ to: targetSquare
528
+ };
529
+ if (requiresPromotion(game, { ...moveData, promotion: "q" })) {
530
+ setPromotionMove(moveData);
531
+ return false;
532
+ }
533
+ return makeMove(moveData);
534
+ },
535
+ onSquareClick: ({ square }) => {
536
+ if (square.match(/^[a-h][1-8]$/)) {
537
+ onSquareClick(square);
538
+ }
539
+ },
540
+ onSquareRightClick,
541
+ allowDrawingArrows: true,
542
+ animationDurationInMs: game.history().length === 0 ? 0 : 300
543
+ };
544
+ const mergedOptions = deepMergeChessboardOptions(baseOptions, options);
545
+ const mergedStyle = {
546
+ ...userStyle,
547
+ position: "relative"
548
+ };
549
+ return /* @__PURE__ */ import_react5.default.createElement("div", { ref, className, style: mergedStyle, ...rest }, /* @__PURE__ */ import_react5.default.createElement(import_react_chessboard.Chessboard, { options: mergedOptions }), promotionMove && /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement(
550
+ "div",
551
+ {
552
+ onClick: () => setPromotionMove(null),
553
+ onContextMenu: (e) => {
554
+ e.preventDefault();
555
+ setPromotionMove(null);
556
+ },
557
+ style: {
558
+ position: "absolute",
559
+ top: 0,
560
+ left: 0,
561
+ right: 0,
562
+ bottom: 0,
563
+ backgroundColor: "rgba(0, 0, 0, 0.1)",
564
+ zIndex: 1e3
565
+ }
566
+ }
567
+ ), /* @__PURE__ */ import_react5.default.createElement(
568
+ "div",
569
+ {
570
+ style: {
571
+ position: "absolute",
572
+ top: ((_b = (_a = promotionMove.to) == null ? void 0 : _a[1]) == null ? void 0 : _b.includes("8")) ? 0 : "auto",
573
+ bottom: ((_c = promotionMove.to) == null ? void 0 : _c[1].includes("1")) ? 0 : "auto",
574
+ left: promotionSquareLeft,
575
+ backgroundColor: "white",
576
+ width: squareWidth,
577
+ zIndex: 1001,
578
+ display: "flex",
579
+ flexDirection: "column",
580
+ boxShadow: "0 0 10px 0 rgba(0, 0, 0, 0.5)"
581
+ }
582
+ },
583
+ ["q", "r", "n", "b"].map((piece) => /* @__PURE__ */ import_react5.default.createElement(
584
+ "button",
585
+ {
586
+ key: piece,
587
+ onClick: () => onPromotionPieceSelect(piece),
588
+ onContextMenu: (e) => {
589
+ e.preventDefault();
590
+ },
591
+ style: {
592
+ width: "100%",
593
+ aspectRatio: "1",
594
+ display: "flex",
595
+ alignItems: "center",
596
+ justifyContent: "center",
597
+ padding: 0,
598
+ border: "none",
599
+ cursor: "pointer",
600
+ backgroundColor: "white"
601
+ },
602
+ onMouseEnter: (e) => {
603
+ e.currentTarget.style.backgroundColor = "#f0f0f0";
604
+ },
605
+ onMouseLeave: (e) => {
606
+ e.currentTarget.style.backgroundColor = "white";
607
+ }
608
+ },
609
+ import_react_chessboard.defaultPieces[`${turn}${piece.toUpperCase()}`]()
610
+ ))
611
+ )));
612
+ }
613
+ );
614
+ Board.displayName = "ChessGame.Board";
615
+
616
+ // src/components/ChessGame/parts/Sounds.tsx
617
+ var import_react7 = require("react");
618
+
619
+ // src/assets/sounds.ts
620
+ var SILENCE = "Li4vU2lsZW5jZS5vZ2c=";
621
+ var defaultSounds = {
622
+ move: "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",
623
+ capture: "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",
624
+ check: SILENCE,
625
+ gameOver: "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"
626
+ };
627
+
628
+ // src/hooks/useBoardSounds.ts
629
+ var import_react6 = require("react");
630
+ var playSound = async (audioElement) => {
631
+ try {
632
+ await audioElement.play();
633
+ } catch (error) {
634
+ console.warn("Failed to play sound:", error.message);
635
+ }
636
+ };
637
+ var useBoardSounds = (sounds) => {
638
+ const {
639
+ info: { lastMove, isCheckmate }
640
+ } = useChessGameContext();
641
+ (0, import_react6.useEffect)(() => {
642
+ if (Object.keys(sounds).length === 0) {
643
+ return;
644
+ }
645
+ if (isCheckmate && sounds.gameOver) {
646
+ playSound(sounds.gameOver);
647
+ return;
648
+ }
649
+ if ((lastMove == null ? void 0 : lastMove.captured) && sounds.capture) {
650
+ playSound(sounds.capture);
651
+ return;
652
+ }
653
+ if (lastMove && sounds.move) {
654
+ playSound(sounds.move);
655
+ }
656
+ }, [lastMove]);
657
+ };
658
+
659
+ // src/components/ChessGame/parts/Sounds.tsx
660
+ var Sounds = ({ sounds }) => {
661
+ const customSoundsAudios = (0, import_react7.useMemo)(() => {
662
+ if (typeof window === "undefined" || typeof Audio === "undefined") {
663
+ return {};
664
+ }
665
+ return Object.entries({ ...defaultSounds, sounds }).reduce(
666
+ (acc, [name, base64]) => {
667
+ acc[name] = new Audio(`data:audio/wav;base64,${base64}`);
668
+ return acc;
669
+ },
670
+ {}
671
+ );
672
+ }, [sounds]);
673
+ useBoardSounds(customSoundsAudios);
674
+ return null;
675
+ };
676
+ Sounds.displayName = "ChessGame.Sounds";
677
+
678
+ // src/hooks/useKeyboardControls.ts
679
+ var import_react8 = require("react");
680
+ var useKeyboardControls = (controls) => {
681
+ const gameContext = useChessGameContext();
682
+ if (!gameContext) {
683
+ throw new Error("ChessGameContext not found");
684
+ }
685
+ const keyboardControls = { ...defaultKeyboardControls, ...controls };
686
+ (0, import_react8.useEffect)(() => {
687
+ const handleKeyDown = (event) => {
688
+ const handler = keyboardControls[event.key];
689
+ if (handler) {
690
+ event.preventDefault();
691
+ handler(gameContext);
692
+ }
693
+ };
694
+ window.addEventListener("keydown", handleKeyDown);
695
+ return () => {
696
+ window.removeEventListener("keydown", handleKeyDown);
697
+ };
698
+ }, [gameContext]);
699
+ return null;
700
+ };
701
+
702
+ // src/components/ChessGame/parts/KeyboardControls.tsx
703
+ var defaultKeyboardControls = {
704
+ ArrowLeft: (context) => context.methods.goToPreviousMove(),
705
+ ArrowRight: (context) => context.methods.goToNextMove(),
706
+ ArrowUp: (context) => context.methods.goToStart(),
707
+ ArrowDown: (context) => context.methods.goToEnd()
708
+ };
709
+ var KeyboardControls2 = ({
710
+ controls
711
+ }) => {
712
+ const gameContext = useChessGameContext();
713
+ if (!gameContext) {
714
+ throw new Error("ChessGameContext not found");
715
+ }
716
+ const keyboardControls = { ...defaultKeyboardControls, ...controls };
717
+ useKeyboardControls(keyboardControls);
718
+ return null;
719
+ };
720
+ KeyboardControls2.displayName = "ChessGame.KeyboardControls";
721
+
722
+ // src/components/ChessGame/index.ts
723
+ var ChessGame = {
724
+ Root,
725
+ Board,
726
+ Sounds,
727
+ KeyboardControls: KeyboardControls2
728
+ };
729
+
730
+ // src/theme/presets.ts
731
+ var lichessTheme = {
732
+ board: {
733
+ lightSquare: { backgroundColor: "#f0d9b5" },
734
+ darkSquare: { backgroundColor: "#b58863" }
735
+ },
736
+ state: {
737
+ lastMove: "rgba(155, 199, 0, 0.41)",
738
+ check: "rgba(255, 0, 0, 0.5)",
739
+ activeSquare: "rgba(20, 85, 30, 0.5)",
740
+ dropSquare: { backgroundColor: "rgba(20, 85, 30, 0.3)" }
741
+ },
742
+ indicators: {
743
+ move: "rgba(20, 85, 30, 0.3)",
744
+ capture: "rgba(20, 85, 30, 0.3)"
745
+ }
746
+ };
747
+ var chessComTheme = {
748
+ board: {
749
+ lightSquare: { backgroundColor: "#ebecd0" },
750
+ darkSquare: { backgroundColor: "#779556" }
751
+ },
752
+ state: {
753
+ lastMove: "rgba(255, 255, 0, 0.5)",
754
+ check: "rgba(255, 0, 0, 0.7)",
755
+ activeSquare: "rgba(255, 255, 0, 0.5)",
756
+ dropSquare: { backgroundColor: "rgba(255, 255, 0, 0.4)" }
757
+ },
758
+ indicators: {
759
+ move: "rgba(0, 0, 0, 0.1)",
760
+ capture: "rgba(0, 0, 0, 0.1)"
761
+ }
762
+ };
763
+
764
+ // src/theme/index.ts
765
+ var themes = {
766
+ default: defaultGameTheme,
767
+ lichess: lichessTheme,
768
+ chessCom: chessComTheme
769
+ };
770
+ // Annotate the CommonJS export names for ESM import in node:
771
+ 0 && (module.exports = {
772
+ ChessGame,
773
+ ChessGameThemeContext,
774
+ chessComTheme,
775
+ deepMergeChessboardOptions,
776
+ defaultGameTheme,
777
+ lichessTheme,
778
+ mergeTheme,
779
+ mergeThemeWith,
780
+ themes,
781
+ useChessGame,
782
+ useChessGameContext,
783
+ useChessGameTheme
784
+ });
785
+ //# sourceMappingURL=index.cjs.map