@react-chess-tools/react-chess-game 0.4.2 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.MD +58 -33
- package/dist/index.d.mts +9 -9
- package/dist/index.mjs +164 -44
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/components/ChessGame/parts/Board.tsx +160 -43
- package/src/hooks/useBoardSounds.ts +16 -7
- package/src/utils/__tests__/board.test.ts +256 -1
- package/src/utils/board.ts +49 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @react-chess-tools/react-chess-game
|
|
2
2
|
|
|
3
|
+
## 0.5.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f50ac0f: feat: improve chessboard options merging with deep merge utility
|
|
8
|
+
|
|
9
|
+
## 0.5.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- f58c1ac: chore: upgrade to react-chessboard v5
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- 95cf0c3: docs: update README documentation for react-chess-tools packages
|
|
18
|
+
- a877019: fix: handle sound playback errors gracefully
|
|
19
|
+
|
|
3
20
|
## 0.4.2
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/README.MD
CHANGED
|
@@ -18,7 +18,7 @@ This project is a React-based chess game that allows users to play chess online.
|
|
|
18
18
|
- Square highlighting
|
|
19
19
|
- Keyboard controls
|
|
20
20
|
|
|
21
|
-
It is
|
|
21
|
+
It is built using an approach similar to the one used in the `radix-ui`, where the `ChessGame` component is built using a `ChessGameContext` that you can use to customize and enhance the component game. It also provides a set of default components that you can use to build your next chess app.
|
|
22
22
|
|
|
23
23
|
## Preview
|
|
24
24
|
|
|
@@ -39,11 +39,11 @@ To use the `react-chess-game` package, you can import the `ChessGame` component
|
|
|
39
39
|
```tsx
|
|
40
40
|
import { ChessGame } from "@react-chess-tools/react-chess-game";
|
|
41
41
|
|
|
42
|
-
const App = () =>
|
|
42
|
+
const App = () => (
|
|
43
43
|
<ChessGame.Root>
|
|
44
44
|
<ChessGame.Board />
|
|
45
|
-
</ChessGame.Root
|
|
46
|
-
|
|
45
|
+
</ChessGame.Root>
|
|
46
|
+
);
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
## Documentation
|
|
@@ -58,23 +58,49 @@ The `ChessGame.Root` component is the root component of the `react-chess-game` p
|
|
|
58
58
|
|
|
59
59
|
The `ChessGame.Root` component accepts the following props:
|
|
60
60
|
|
|
61
|
-
| Name | Type | Default
|
|
62
|
-
| ----------- | ---------- |
|
|
63
|
-
| children | React.FC |
|
|
64
|
-
| fen | string |
|
|
65
|
-
| orientation | "w" \| "b" | "
|
|
61
|
+
| Name | Type | Default | Description |
|
|
62
|
+
| ----------- | ---------- | ------- | ----------------------------------------------- |
|
|
63
|
+
| children | React.FC | | The children of the `ChessGame.Root` component. |
|
|
64
|
+
| fen | string | | The initial FEN of the chess game. |
|
|
65
|
+
| orientation | "w" \| "b" | "w" | The orientation of the chess game. |
|
|
66
66
|
|
|
67
67
|
### ChessGame.Board
|
|
68
68
|
|
|
69
69
|
The `ChessGame.Board` component is the main component of the `react-chess-game` package. It is used to render the chess board and the pieces. It uses the `ChessGameContext` to get the `Chess` instance and the `orientation` of the game.
|
|
70
70
|
|
|
71
|
+
This version targets `react-chessboard` v5 and exposes a single `options` prop instead of spreading all board props.
|
|
72
|
+
|
|
71
73
|
#### Props
|
|
72
74
|
|
|
73
|
-
|
|
75
|
+
Accepts a single prop:
|
|
76
|
+
|
|
77
|
+
| Name | Type | Description |
|
|
78
|
+
| -------- | ------------------- | -------------------------------------------------------------------------------------------------- |
|
|
79
|
+
| options? | `ChessboardOptions` | Forwarded to `react-chessboard` v5 `Chessboard({ options })`. Your values merge with the defaults. |
|
|
80
|
+
|
|
81
|
+
Quick example (custom styles and event handlers):
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
<ChessGame.Root>
|
|
85
|
+
<ChessGame.Board
|
|
86
|
+
options={{
|
|
87
|
+
squareStyles: { e4: { boxShadow: "inset 0 0 0 2px #4f46e5" } },
|
|
88
|
+
onPieceDrop: ({ sourceSquare, targetSquare }) => {
|
|
89
|
+
// return boolean to accept/reject drop
|
|
90
|
+
return true;
|
|
91
|
+
},
|
|
92
|
+
showNotation: true,
|
|
93
|
+
animationDurationInMs: 300,
|
|
94
|
+
}}
|
|
95
|
+
/>
|
|
96
|
+
|
|
97
|
+
{/* Other parts like <ChessGame.Sounds /> or <ChessGame.KeyboardControls /> */}
|
|
98
|
+
</ChessGame.Root>
|
|
99
|
+
```
|
|
74
100
|
|
|
75
101
|
### ChessGame.Sounds
|
|
76
102
|
|
|
77
|
-
The `ChessGame.Sounds` component is used to provide the sounds for the chess game. By default, it uses
|
|
103
|
+
The `ChessGame.Sounds` component is used to provide the sounds for the chess game. By default, it uses built-in sounds, but you can provide your own sounds. Sounds must be provided as base 64 encoded strings.
|
|
78
104
|
|
|
79
105
|
#### Props
|
|
80
106
|
|
|
@@ -107,27 +133,31 @@ The `useChessGameContext` hook is used to get the `ChessGameContext` from the `C
|
|
|
107
133
|
|
|
108
134
|
The `useChessGameContext` hook returns the following values:
|
|
109
135
|
|
|
110
|
-
| Name
|
|
111
|
-
|
|
|
112
|
-
|
|
|
113
|
-
| orientation
|
|
114
|
-
|
|
|
115
|
-
|
|
|
136
|
+
| Name | Type | Description |
|
|
137
|
+
| ---------------- | ---------- | -------------------------------------------------------------------------------------- |
|
|
138
|
+
| game | Chess | The underlying `Chess.js` instance. |
|
|
139
|
+
| orientation | "w" \| "b" | The orientation of the chess game. |
|
|
140
|
+
| currentFen | string | The current FEN string representing the board position. |
|
|
141
|
+
| currentPosition | string | The current move in the game history. |
|
|
142
|
+
| currentMoveIndex | number | The index of the current move in the game history. |
|
|
143
|
+
| isLatestMove | boolean | Whether the current position is the latest move in the game. |
|
|
144
|
+
| methods | Methods | The methods you can use to interact with the chess game. |
|
|
145
|
+
| info | Info | The info of the chess game, calculated using the chess instance using chess.js methods |
|
|
116
146
|
|
|
117
147
|
#### Methods
|
|
118
148
|
|
|
119
|
-
The `
|
|
149
|
+
The `useChessGameContext` hook also exposes these methods:
|
|
120
150
|
|
|
121
|
-
| Name | Type
|
|
122
|
-
| ---------------- |
|
|
123
|
-
| makeMove | (move: string) =>
|
|
124
|
-
|
|
|
125
|
-
| flipBoard | () => void
|
|
126
|
-
| goToMove | (moveIndex: number) => void
|
|
127
|
-
| goToStart | () => void
|
|
128
|
-
| goToEnd | () => void
|
|
129
|
-
| goToPreviousMove | () => void
|
|
130
|
-
| goToNextMove | () => void
|
|
151
|
+
| Name | Type | Description |
|
|
152
|
+
| ---------------- | ------------------------------- | --------------------------------------------------------------- | -------------------------------------------------------------------- | --- | ------------------ | ------------------------------------------------------------------ |
|
|
153
|
+
| makeMove | `(move: string | { from: Square; to: Square; promotion?: "q" | "r" | "b" | "n" }) => boolean` | Attempts a move at the latest position; returns `true` if applied. |
|
|
154
|
+
| setPosition | `(fen: string, orientation: "w" | "b") => void` | Sets a new FEN and orientation, resets history navigation to latest. |
|
|
155
|
+
| flipBoard | `() => void` | Flips the board orientation. |
|
|
156
|
+
| goToMove | `(moveIndex: number) => void` | Jumps to a specific move index (`-1` is the starting position). |
|
|
157
|
+
| goToStart | `() => void` | Goes to the starting position. |
|
|
158
|
+
| goToEnd | `() => void` | Goes to the latest move. |
|
|
159
|
+
| goToPreviousMove | `() => void` | Goes to the previous move. |
|
|
160
|
+
| goToNextMove | `() => void` | Goes to the next move. |
|
|
131
161
|
|
|
132
162
|
#### Info
|
|
133
163
|
|
|
@@ -150,11 +180,6 @@ The `useChessGameContext` hook returns the following info:
|
|
|
150
180
|
| isDrawn | boolean | Whether the game is drawn |
|
|
151
181
|
| hasPlayerWon | boolean | Whether the player (the side specified in the `orientation` prop) has won |
|
|
152
182
|
| hasPlayerLost | boolean | Whether the player (the side specified in the `orientation` prop) has lost |
|
|
153
|
-
| currentFen | string | The current FEN string representing the board position |
|
|
154
|
-
| currentPosition | string | The current move in the game history |
|
|
155
|
-
| currentMoveIndex | number | The index of the current move in the game history |
|
|
156
|
-
| isLatestMove | boolean | Whether the current position is the latest move in the game |
|
|
157
|
-
| game | Chess | The underlying Chess.js instance |
|
|
158
183
|
|
|
159
184
|
## 📝 License
|
|
160
185
|
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import { Chessboard } from 'react-chessboard';
|
|
1
|
+
import { ChessboardOptions } from 'react-chessboard';
|
|
2
|
+
import * as react from 'react';
|
|
4
3
|
import * as chess_js from 'chess.js';
|
|
5
4
|
import { Color, Chess } from 'chess.js';
|
|
6
5
|
|
|
@@ -11,7 +10,8 @@ type SoundsProps = {
|
|
|
11
10
|
sounds?: Partial<Record<Sound, string>>;
|
|
12
11
|
};
|
|
13
12
|
|
|
14
|
-
interface ChessGameProps
|
|
13
|
+
interface ChessGameProps {
|
|
14
|
+
options?: ChessboardOptions;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
interface RootProps {
|
|
@@ -88,7 +88,7 @@ declare const useChessGameContext: () => {
|
|
|
88
88
|
from: string;
|
|
89
89
|
to: string;
|
|
90
90
|
promotion?: string | undefined;
|
|
91
|
-
}) => boolean;
|
|
91
|
+
} | null) => boolean;
|
|
92
92
|
setPosition: (fen: string, orientation: chess_js.Color) => void;
|
|
93
93
|
flipBoard: () => void;
|
|
94
94
|
goToMove: (moveIndex: number) => void;
|
|
@@ -107,10 +107,10 @@ type KeyboardControls = Record<string, (context: ChessGameContextType) => void>;
|
|
|
107
107
|
declare const KeyboardControls: React.FC<KeyboardControlsProps>;
|
|
108
108
|
|
|
109
109
|
declare const ChessGame: {
|
|
110
|
-
Root:
|
|
111
|
-
Board:
|
|
112
|
-
Sounds:
|
|
113
|
-
KeyboardControls:
|
|
110
|
+
Root: react.FC<react.PropsWithChildren<RootProps>>;
|
|
111
|
+
Board: react.FC<ChessGameProps>;
|
|
112
|
+
Sounds: react.FC<SoundsProps>;
|
|
113
|
+
KeyboardControls: react.FC<{
|
|
114
114
|
controls?: KeyboardControls | undefined;
|
|
115
115
|
}>;
|
|
116
116
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -224,9 +224,14 @@ var Root = ({
|
|
|
224
224
|
|
|
225
225
|
// src/components/ChessGame/parts/Board.tsx
|
|
226
226
|
import React4 from "react";
|
|
227
|
-
import {
|
|
227
|
+
import {
|
|
228
|
+
Chessboard,
|
|
229
|
+
defaultPieces,
|
|
230
|
+
chessColumnToColumnIndex
|
|
231
|
+
} from "react-chessboard";
|
|
228
232
|
|
|
229
233
|
// src/utils/board.ts
|
|
234
|
+
import { merge } from "lodash";
|
|
230
235
|
var LAST_MOVE_COLOR = "rgba(255, 255, 0, 0.5)";
|
|
231
236
|
var CHECK_COLOR = "rgba(255, 0, 0, 0.5)";
|
|
232
237
|
var getCustomSquareStyles = (game, info, activeSquare) => {
|
|
@@ -267,12 +272,28 @@ var getCustomSquareStyles = (game, info, activeSquare) => {
|
|
|
267
272
|
}
|
|
268
273
|
return customSquareStyles;
|
|
269
274
|
};
|
|
275
|
+
var deepMergeChessboardOptions = (baseOptions, customOptions) => {
|
|
276
|
+
if (!customOptions) {
|
|
277
|
+
return { ...baseOptions };
|
|
278
|
+
}
|
|
279
|
+
const result = merge({}, baseOptions, customOptions, {
|
|
280
|
+
customizer: (_objValue, srcValue) => {
|
|
281
|
+
if (typeof srcValue === "function") {
|
|
282
|
+
return srcValue;
|
|
283
|
+
}
|
|
284
|
+
if (Array.isArray(srcValue)) {
|
|
285
|
+
return srcValue;
|
|
286
|
+
}
|
|
287
|
+
return void 0;
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
delete result.customizer;
|
|
291
|
+
return result;
|
|
292
|
+
};
|
|
270
293
|
|
|
271
294
|
// src/components/ChessGame/parts/Board.tsx
|
|
272
|
-
var Board = ({
|
|
273
|
-
|
|
274
|
-
...rest
|
|
275
|
-
}) => {
|
|
295
|
+
var Board = ({ options = {} }) => {
|
|
296
|
+
var _a, _b, _c;
|
|
276
297
|
const gameContext = useChessGameContext();
|
|
277
298
|
if (!gameContext) {
|
|
278
299
|
throw new Error("ChessGameContext not found");
|
|
@@ -282,6 +303,7 @@ var Board = ({
|
|
|
282
303
|
currentFen,
|
|
283
304
|
orientation,
|
|
284
305
|
info,
|
|
306
|
+
isLatestMove,
|
|
285
307
|
methods: { makeMove }
|
|
286
308
|
} = gameContext;
|
|
287
309
|
const { turn, isGameOver } = info;
|
|
@@ -322,45 +344,138 @@ var Board = ({
|
|
|
322
344
|
});
|
|
323
345
|
};
|
|
324
346
|
const onPromotionPieceSelect = (piece) => {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
setPromotionMove(null);
|
|
328
|
-
return makeMove({
|
|
347
|
+
if ((promotionMove == null ? void 0 : promotionMove.from) && (promotionMove == null ? void 0 : promotionMove.to)) {
|
|
348
|
+
makeMove({
|
|
329
349
|
from: promotionMove.from,
|
|
330
350
|
to: promotionMove.to,
|
|
331
|
-
promotion:
|
|
351
|
+
promotion: piece.toLowerCase()
|
|
332
352
|
});
|
|
353
|
+
setPromotionMove(null);
|
|
333
354
|
}
|
|
334
|
-
return true;
|
|
335
355
|
};
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
356
|
+
const onSquareRightClick = () => {
|
|
357
|
+
setActiveSquare(null);
|
|
358
|
+
setPromotionMove(null);
|
|
359
|
+
};
|
|
360
|
+
const squareWidth = React4.useMemo(() => {
|
|
361
|
+
var _a2;
|
|
362
|
+
if (typeof document === "undefined") return 80;
|
|
363
|
+
const squareElement = document.querySelector(`[data-square]`);
|
|
364
|
+
return ((_a2 = squareElement == null ? void 0 : squareElement.getBoundingClientRect()) == null ? void 0 : _a2.width) ?? 80;
|
|
365
|
+
}, [promotionMove]);
|
|
366
|
+
const promotionSquareLeft = React4.useMemo(() => {
|
|
367
|
+
var _a2;
|
|
368
|
+
if (!(promotionMove == null ? void 0 : promotionMove.to)) return 0;
|
|
369
|
+
const column = ((_a2 = promotionMove.to.match(/^[a-h]/)) == null ? void 0 : _a2[0]) ?? "a";
|
|
370
|
+
return squareWidth * chessColumnToColumnIndex(
|
|
371
|
+
column,
|
|
372
|
+
8,
|
|
373
|
+
orientation === "b" ? "black" : "white"
|
|
374
|
+
);
|
|
375
|
+
}, [promotionMove, squareWidth, orientation]);
|
|
376
|
+
const baseOptions = {
|
|
377
|
+
squareStyles: getCustomSquareStyles(game, info, activeSquare),
|
|
378
|
+
boardOrientation: orientation === "b" ? "black" : "white",
|
|
379
|
+
position: currentFen,
|
|
380
|
+
showNotation: true,
|
|
381
|
+
showAnimations: isLatestMove,
|
|
382
|
+
canDragPiece: ({ piece }) => {
|
|
383
|
+
if (isGameOver) return false;
|
|
384
|
+
return piece.pieceType[0] === turn;
|
|
385
|
+
},
|
|
386
|
+
dropSquareStyle: {
|
|
387
|
+
backgroundColor: "rgba(255, 255, 0, 0.4)"
|
|
388
|
+
},
|
|
389
|
+
onPieceDrag: ({ piece, square }) => {
|
|
390
|
+
if (piece.pieceType[0] === turn) {
|
|
348
391
|
setActiveSquare(square);
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
onPieceDrop: ({ sourceSquare, targetSquare }) => {
|
|
395
|
+
setActiveSquare(null);
|
|
396
|
+
const moveData = {
|
|
354
397
|
from: sourceSquare,
|
|
355
|
-
to: targetSquare
|
|
356
|
-
|
|
357
|
-
})
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
398
|
+
to: targetSquare
|
|
399
|
+
};
|
|
400
|
+
if (requiresPromotion(game, { ...moveData, promotion: "q" })) {
|
|
401
|
+
setPromotionMove(moveData);
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
return makeMove(moveData);
|
|
405
|
+
},
|
|
406
|
+
onSquareClick: ({ square }) => {
|
|
407
|
+
if (square.match(/^[a-h][1-8]$/)) {
|
|
408
|
+
onSquareClick(square);
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
onSquareRightClick,
|
|
412
|
+
allowDrawingArrows: true,
|
|
413
|
+
animationDurationInMs: game.history().length === 0 ? 0 : 300
|
|
414
|
+
};
|
|
415
|
+
const mergedOptions = deepMergeChessboardOptions(baseOptions, options);
|
|
416
|
+
return /* @__PURE__ */ React4.createElement("div", { style: { position: "relative" } }, /* @__PURE__ */ React4.createElement(Chessboard, { options: mergedOptions }), promotionMove && /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(
|
|
417
|
+
"div",
|
|
418
|
+
{
|
|
419
|
+
onClick: () => setPromotionMove(null),
|
|
420
|
+
onContextMenu: (e) => {
|
|
421
|
+
e.preventDefault();
|
|
422
|
+
setPromotionMove(null);
|
|
423
|
+
},
|
|
424
|
+
style: {
|
|
425
|
+
position: "absolute",
|
|
426
|
+
top: 0,
|
|
427
|
+
left: 0,
|
|
428
|
+
right: 0,
|
|
429
|
+
bottom: 0,
|
|
430
|
+
backgroundColor: "rgba(0, 0, 0, 0.1)",
|
|
431
|
+
zIndex: 1e3
|
|
432
|
+
}
|
|
362
433
|
}
|
|
363
|
-
)
|
|
434
|
+
), /* @__PURE__ */ React4.createElement(
|
|
435
|
+
"div",
|
|
436
|
+
{
|
|
437
|
+
style: {
|
|
438
|
+
position: "absolute",
|
|
439
|
+
top: ((_b = (_a = promotionMove.to) == null ? void 0 : _a[1]) == null ? void 0 : _b.includes("8")) ? 0 : "auto",
|
|
440
|
+
bottom: ((_c = promotionMove.to) == null ? void 0 : _c[1].includes("1")) ? 0 : "auto",
|
|
441
|
+
left: promotionSquareLeft,
|
|
442
|
+
backgroundColor: "white",
|
|
443
|
+
width: squareWidth,
|
|
444
|
+
zIndex: 1001,
|
|
445
|
+
display: "flex",
|
|
446
|
+
flexDirection: "column",
|
|
447
|
+
boxShadow: "0 0 10px 0 rgba(0, 0, 0, 0.5)"
|
|
448
|
+
}
|
|
449
|
+
},
|
|
450
|
+
["q", "r", "n", "b"].map((piece) => /* @__PURE__ */ React4.createElement(
|
|
451
|
+
"button",
|
|
452
|
+
{
|
|
453
|
+
key: piece,
|
|
454
|
+
onClick: () => onPromotionPieceSelect(piece),
|
|
455
|
+
onContextMenu: (e) => {
|
|
456
|
+
e.preventDefault();
|
|
457
|
+
},
|
|
458
|
+
style: {
|
|
459
|
+
width: "100%",
|
|
460
|
+
aspectRatio: "1",
|
|
461
|
+
display: "flex",
|
|
462
|
+
alignItems: "center",
|
|
463
|
+
justifyContent: "center",
|
|
464
|
+
padding: 0,
|
|
465
|
+
border: "none",
|
|
466
|
+
cursor: "pointer",
|
|
467
|
+
backgroundColor: "white"
|
|
468
|
+
},
|
|
469
|
+
onMouseEnter: (e) => {
|
|
470
|
+
e.currentTarget.style.backgroundColor = "#f0f0f0";
|
|
471
|
+
},
|
|
472
|
+
onMouseLeave: (e) => {
|
|
473
|
+
e.currentTarget.style.backgroundColor = "white";
|
|
474
|
+
}
|
|
475
|
+
},
|
|
476
|
+
defaultPieces[`${turn}${piece.toUpperCase()}`]()
|
|
477
|
+
))
|
|
478
|
+
)));
|
|
364
479
|
};
|
|
365
480
|
|
|
366
481
|
// src/components/ChessGame/parts/Sounds.tsx
|
|
@@ -377,26 +492,31 @@ var defaultSounds = {
|
|
|
377
492
|
|
|
378
493
|
// src/hooks/useBoardSounds.ts
|
|
379
494
|
import { useEffect as useEffect2 } from "react";
|
|
495
|
+
var playSound = async (audioElement) => {
|
|
496
|
+
try {
|
|
497
|
+
await audioElement.play();
|
|
498
|
+
} catch (error) {
|
|
499
|
+
console.warn("Failed to play sound:", error.message);
|
|
500
|
+
}
|
|
501
|
+
};
|
|
380
502
|
var useBoardSounds = (sounds) => {
|
|
381
503
|
const {
|
|
382
504
|
info: { lastMove, isCheckmate }
|
|
383
505
|
} = useChessGameContext();
|
|
384
506
|
useEffect2(() => {
|
|
385
|
-
var _a, _b, _c;
|
|
386
507
|
if (Object.keys(sounds).length === 0) {
|
|
387
508
|
return;
|
|
388
509
|
}
|
|
389
|
-
if (isCheckmate) {
|
|
390
|
-
(
|
|
510
|
+
if (isCheckmate && sounds.gameOver) {
|
|
511
|
+
playSound(sounds.gameOver);
|
|
391
512
|
return;
|
|
392
513
|
}
|
|
393
|
-
if (lastMove == null ? void 0 : lastMove.captured) {
|
|
394
|
-
(
|
|
514
|
+
if ((lastMove == null ? void 0 : lastMove.captured) && sounds.capture) {
|
|
515
|
+
playSound(sounds.capture);
|
|
395
516
|
return;
|
|
396
517
|
}
|
|
397
|
-
if (lastMove) {
|
|
398
|
-
(
|
|
399
|
-
return;
|
|
518
|
+
if (lastMove && sounds.move) {
|
|
519
|
+
playSound(sounds.move);
|
|
400
520
|
}
|
|
401
521
|
}, [lastMove]);
|
|
402
522
|
};
|