react-chess-explorer 0.0.5 → 0.0.6

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.
@@ -17,6 +17,8 @@ export declare function useGameReplayTraining({ gameId, startFen, fetchGame, }:
17
17
  feedback: GameReplayFeedback;
18
18
  lastExpectedSan: string | null;
19
19
  lastMoveUci: any;
20
+ correctMoveSquare: any;
21
+ incorrectMoveSquare: any;
20
22
  expectedSan: string | undefined;
21
23
  handlePieceDrop: (sourceSquare: string, targetSquare: string, piece: string) => boolean;
22
24
  revealMove: () => void;
package/dist/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Chess } from 'chess.js';
2
2
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
- import { ThemeProvider, HighlightChessboard, usePositionKeyboardNav, ChessboardDnDProvider, lastMoveUciAtPly } from 'react-chess-core';
3
+ import { ThemeProvider, HighlightChessboard, usePositionKeyboardNav, ChessboardDnDProvider, useCorrectMoveFeedback, useIncorrectMoveFeedback, lastMoveUciAtPly } from 'react-chess-core';
4
4
  import { useEffect, useState, useCallback, useRef, useMemo } from 'react';
5
5
 
6
6
  /** Standard start position — placeholder until game replay is implemented. */
@@ -1273,12 +1273,16 @@ function useGameReplayTraining({ gameId, startFen, fetchGame, }) {
1273
1273
  const [error, setError] = useState(null);
1274
1274
  const [feedback, setFeedback] = useState(null);
1275
1275
  const [lastExpectedSan, setLastExpectedSan] = useState(null);
1276
+ const { correctMoveSquare, showCorrectMove, clearCorrectMoveFeedback, isShowingCorrectMove, } = useCorrectMoveFeedback();
1277
+ const { incorrectMoveSquare, showIncorrectMove, clearIncorrectMoveFeedback, isShowingIncorrectMove, } = useIncorrectMoveFeedback();
1276
1278
  useEffect(() => {
1277
1279
  let cancelled = false;
1278
1280
  setLoading(true);
1279
1281
  setError(null);
1280
1282
  setFeedback(null);
1281
1283
  setLastExpectedSan(null);
1284
+ clearCorrectMoveFeedback();
1285
+ clearIncorrectMoveFeedback();
1282
1286
  (() => __awaiter(this, void 0, void 0, function* () {
1283
1287
  try {
1284
1288
  const loaded = yield fetchGame(gameId);
@@ -1305,7 +1309,7 @@ function useGameReplayTraining({ gameId, startFen, fetchGame, }) {
1305
1309
  return () => {
1306
1310
  cancelled = true;
1307
1311
  };
1308
- }, [gameId, startFen, fetchGame]);
1312
+ }, [gameId, startFen, fetchGame, clearCorrectMoveFeedback, clearIncorrectMoveFeedback]);
1309
1313
  const fen = useMemo(() => {
1310
1314
  if (!game)
1311
1315
  return startFen;
@@ -1316,21 +1320,40 @@ function useGameReplayTraining({ gameId, startFen, fetchGame, }) {
1316
1320
  const expectedSan = game === null || game === void 0 ? void 0 : game.movesSan[plyIndex];
1317
1321
  const lastMoveUci = useMemo(() => (game ? lastMoveUciAtPly(game.movesUci, plyIndex) : null), [game, plyIndex]);
1318
1322
  const handlePieceDrop = useCallback((sourceSquare, targetSquare, piece) => {
1319
- if (!game || complete || !expectedUci)
1323
+ if (!game ||
1324
+ complete ||
1325
+ !expectedUci ||
1326
+ isShowingCorrectMove ||
1327
+ isShowingIncorrectMove) {
1320
1328
  return false;
1329
+ }
1321
1330
  const uci = uciFromDrop(fen, sourceSquare, targetSquare, piece);
1322
1331
  if (!uci)
1323
1332
  return false;
1324
1333
  if (uci === expectedUci) {
1325
1334
  setFeedback("correct");
1326
- setPlyIndex((p) => p + 1);
1327
1335
  setLastExpectedSan(null);
1336
+ showCorrectMove(targetSquare, () => {
1337
+ setFeedback(null);
1338
+ setPlyIndex((p) => p + 1);
1339
+ });
1328
1340
  return true;
1329
1341
  }
1330
1342
  setFeedback("incorrect");
1331
1343
  setLastExpectedSan(expectedSan !== null && expectedSan !== void 0 ? expectedSan : null);
1344
+ showIncorrectMove(sourceSquare);
1332
1345
  return false;
1333
- }, [game, complete, expectedUci, expectedSan, fen]);
1346
+ }, [
1347
+ game,
1348
+ complete,
1349
+ expectedUci,
1350
+ expectedSan,
1351
+ fen,
1352
+ isShowingCorrectMove,
1353
+ isShowingIncorrectMove,
1354
+ showCorrectMove,
1355
+ showIncorrectMove,
1356
+ ]);
1334
1357
  const revealMove = useCallback(() => {
1335
1358
  if (!game || complete || !expectedSan)
1336
1359
  return;
@@ -1349,6 +1372,8 @@ function useGameReplayTraining({ gameId, startFen, fetchGame, }) {
1349
1372
  feedback,
1350
1373
  lastExpectedSan,
1351
1374
  lastMoveUci,
1375
+ correctMoveSquare,
1376
+ incorrectMoveSquare,
1352
1377
  expectedSan,
1353
1378
  handlePieceDrop,
1354
1379
  revealMove,
@@ -1369,7 +1394,7 @@ const defaultButtonStyle = {
1369
1394
  cursor: "pointer",
1370
1395
  };
1371
1396
  const GameReplayTrainer = ({ gameId, startFen, fetchGame, onExit, theme = "dark", boardWidth = DEFAULT_REFERENCE_LAYOUT.boardWidth, renderStatus, }) => {
1372
- const { game, fen, plyIndex, totalPlies, complete, loading, error, feedback, lastExpectedSan, lastMoveUci, handlePieceDrop, revealMove, } = useGameReplayTraining({ gameId, startFen, fetchGame });
1397
+ const { game, fen, plyIndex, totalPlies, complete, loading, error, feedback, lastExpectedSan, lastMoveUci, correctMoveSquare, incorrectMoveSquare, handlePieceDrop, revealMove, } = useGameReplayTraining({ gameId, startFen, fetchGame });
1373
1398
  const status = renderStatus === null || renderStatus === void 0 ? void 0 : renderStatus({
1374
1399
  loading,
1375
1400
  error,
@@ -1389,7 +1414,7 @@ const GameReplayTrainer = ({ gameId, startFen, fetchGame, onExit, theme = "dark"
1389
1414
  !error &&
1390
1415
  !complete &&
1391
1416
  feedback === "incorrect" &&
1392
- lastExpectedSan && (jsxs("span", { style: { color: "#ef6c00" }, children: ["Expected ", lastExpectedSan] })), !loading && !error && !complete && feedback === null && (jsxs("span", { children: ["Guess move ", plyIndex + 1, " of ", totalPlies] }))] })), jsx(ChessboardDnDProvider, { children: jsx(HighlightChessboard, { boardWidth: boardWidth, position: fen, checkSquare: "", hintSquare: null, incorrectMoveSquare: null, lastMoveUci: lastMoveUci, onPieceDrop: handlePieceDrop, promotionDialogVariant: "modal" }) }), !complete && !loading && !error && (jsx("button", { type: "button", style: defaultButtonStyle, onClick: revealMove, children: "Show move" }))] }) }));
1417
+ lastExpectedSan && (jsxs("span", { style: { color: "#ef6c00" }, children: ["Expected ", lastExpectedSan] })), !loading && !error && !complete && feedback === null && (jsxs("span", { children: ["Guess move ", plyIndex + 1, " of ", totalPlies] }))] })), jsx(ChessboardDnDProvider, { children: jsx(HighlightChessboard, { boardWidth: boardWidth, position: fen, checkSquare: "", hintSquare: null, incorrectMoveSquare: incorrectMoveSquare, correctMoveSquare: correctMoveSquare, lastMoveUci: lastMoveUci, arePiecesDraggable: !complete && !loading && !error && !correctMoveSquare && !incorrectMoveSquare, onPieceDrop: handlePieceDrop, promotionDialogVariant: "modal" }) }), !complete && !loading && !error && (jsx("button", { type: "button", style: defaultButtonStyle, onClick: revealMove, children: "Show move" }))] }) }));
1393
1418
  };
1394
1419
 
1395
1420
  const mockPosition = {
package/dist/index.js CHANGED
@@ -1275,12 +1275,16 @@ function useGameReplayTraining({ gameId, startFen, fetchGame, }) {
1275
1275
  const [error, setError] = react.useState(null);
1276
1276
  const [feedback, setFeedback] = react.useState(null);
1277
1277
  const [lastExpectedSan, setLastExpectedSan] = react.useState(null);
1278
+ const { correctMoveSquare, showCorrectMove, clearCorrectMoveFeedback, isShowingCorrectMove, } = reactChessCore.useCorrectMoveFeedback();
1279
+ const { incorrectMoveSquare, showIncorrectMove, clearIncorrectMoveFeedback, isShowingIncorrectMove, } = reactChessCore.useIncorrectMoveFeedback();
1278
1280
  react.useEffect(() => {
1279
1281
  let cancelled = false;
1280
1282
  setLoading(true);
1281
1283
  setError(null);
1282
1284
  setFeedback(null);
1283
1285
  setLastExpectedSan(null);
1286
+ clearCorrectMoveFeedback();
1287
+ clearIncorrectMoveFeedback();
1284
1288
  (() => __awaiter(this, void 0, void 0, function* () {
1285
1289
  try {
1286
1290
  const loaded = yield fetchGame(gameId);
@@ -1307,7 +1311,7 @@ function useGameReplayTraining({ gameId, startFen, fetchGame, }) {
1307
1311
  return () => {
1308
1312
  cancelled = true;
1309
1313
  };
1310
- }, [gameId, startFen, fetchGame]);
1314
+ }, [gameId, startFen, fetchGame, clearCorrectMoveFeedback, clearIncorrectMoveFeedback]);
1311
1315
  const fen = react.useMemo(() => {
1312
1316
  if (!game)
1313
1317
  return startFen;
@@ -1318,21 +1322,40 @@ function useGameReplayTraining({ gameId, startFen, fetchGame, }) {
1318
1322
  const expectedSan = game === null || game === void 0 ? void 0 : game.movesSan[plyIndex];
1319
1323
  const lastMoveUci = react.useMemo(() => (game ? reactChessCore.lastMoveUciAtPly(game.movesUci, plyIndex) : null), [game, plyIndex]);
1320
1324
  const handlePieceDrop = react.useCallback((sourceSquare, targetSquare, piece) => {
1321
- if (!game || complete || !expectedUci)
1325
+ if (!game ||
1326
+ complete ||
1327
+ !expectedUci ||
1328
+ isShowingCorrectMove ||
1329
+ isShowingIncorrectMove) {
1322
1330
  return false;
1331
+ }
1323
1332
  const uci = uciFromDrop(fen, sourceSquare, targetSquare, piece);
1324
1333
  if (!uci)
1325
1334
  return false;
1326
1335
  if (uci === expectedUci) {
1327
1336
  setFeedback("correct");
1328
- setPlyIndex((p) => p + 1);
1329
1337
  setLastExpectedSan(null);
1338
+ showCorrectMove(targetSquare, () => {
1339
+ setFeedback(null);
1340
+ setPlyIndex((p) => p + 1);
1341
+ });
1330
1342
  return true;
1331
1343
  }
1332
1344
  setFeedback("incorrect");
1333
1345
  setLastExpectedSan(expectedSan !== null && expectedSan !== void 0 ? expectedSan : null);
1346
+ showIncorrectMove(sourceSquare);
1334
1347
  return false;
1335
- }, [game, complete, expectedUci, expectedSan, fen]);
1348
+ }, [
1349
+ game,
1350
+ complete,
1351
+ expectedUci,
1352
+ expectedSan,
1353
+ fen,
1354
+ isShowingCorrectMove,
1355
+ isShowingIncorrectMove,
1356
+ showCorrectMove,
1357
+ showIncorrectMove,
1358
+ ]);
1336
1359
  const revealMove = react.useCallback(() => {
1337
1360
  if (!game || complete || !expectedSan)
1338
1361
  return;
@@ -1351,6 +1374,8 @@ function useGameReplayTraining({ gameId, startFen, fetchGame, }) {
1351
1374
  feedback,
1352
1375
  lastExpectedSan,
1353
1376
  lastMoveUci,
1377
+ correctMoveSquare,
1378
+ incorrectMoveSquare,
1354
1379
  expectedSan,
1355
1380
  handlePieceDrop,
1356
1381
  revealMove,
@@ -1371,7 +1396,7 @@ const defaultButtonStyle = {
1371
1396
  cursor: "pointer",
1372
1397
  };
1373
1398
  const GameReplayTrainer = ({ gameId, startFen, fetchGame, onExit, theme = "dark", boardWidth = DEFAULT_REFERENCE_LAYOUT.boardWidth, renderStatus, }) => {
1374
- const { game, fen, plyIndex, totalPlies, complete, loading, error, feedback, lastExpectedSan, lastMoveUci, handlePieceDrop, revealMove, } = useGameReplayTraining({ gameId, startFen, fetchGame });
1399
+ const { game, fen, plyIndex, totalPlies, complete, loading, error, feedback, lastExpectedSan, lastMoveUci, correctMoveSquare, incorrectMoveSquare, handlePieceDrop, revealMove, } = useGameReplayTraining({ gameId, startFen, fetchGame });
1375
1400
  const status = renderStatus === null || renderStatus === void 0 ? void 0 : renderStatus({
1376
1401
  loading,
1377
1402
  error,
@@ -1391,7 +1416,7 @@ const GameReplayTrainer = ({ gameId, startFen, fetchGame, onExit, theme = "dark"
1391
1416
  !error &&
1392
1417
  !complete &&
1393
1418
  feedback === "incorrect" &&
1394
- lastExpectedSan && (jsxRuntime.jsxs("span", { style: { color: "#ef6c00" }, children: ["Expected ", lastExpectedSan] })), !loading && !error && !complete && feedback === null && (jsxRuntime.jsxs("span", { children: ["Guess move ", plyIndex + 1, " of ", totalPlies] }))] })), jsxRuntime.jsx(reactChessCore.ChessboardDnDProvider, { children: jsxRuntime.jsx(reactChessCore.HighlightChessboard, { boardWidth: boardWidth, position: fen, checkSquare: "", hintSquare: null, incorrectMoveSquare: null, lastMoveUci: lastMoveUci, onPieceDrop: handlePieceDrop, promotionDialogVariant: "modal" }) }), !complete && !loading && !error && (jsxRuntime.jsx("button", { type: "button", style: defaultButtonStyle, onClick: revealMove, children: "Show move" }))] }) }));
1419
+ lastExpectedSan && (jsxRuntime.jsxs("span", { style: { color: "#ef6c00" }, children: ["Expected ", lastExpectedSan] })), !loading && !error && !complete && feedback === null && (jsxRuntime.jsxs("span", { children: ["Guess move ", plyIndex + 1, " of ", totalPlies] }))] })), jsxRuntime.jsx(reactChessCore.ChessboardDnDProvider, { children: jsxRuntime.jsx(reactChessCore.HighlightChessboard, { boardWidth: boardWidth, position: fen, checkSquare: "", hintSquare: null, incorrectMoveSquare: incorrectMoveSquare, correctMoveSquare: correctMoveSquare, lastMoveUci: lastMoveUci, arePiecesDraggable: !complete && !loading && !error && !correctMoveSquare && !incorrectMoveSquare, onPieceDrop: handlePieceDrop, promotionDialogVariant: "modal" }) }), !complete && !loading && !error && (jsxRuntime.jsx("button", { type: "button", style: defaultButtonStyle, onClick: revealMove, children: "Show move" }))] }) }));
1395
1420
  };
1396
1421
 
1397
1422
  const mockPosition = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-chess-explorer",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "React components for browsing and replaying chess games (depends on react-chess-core only)",
5
5
  "license": "MIT",
6
6
  "author": "Robert Blackwell",