react-chess-replay-trainer 0.0.4 → 0.0.5

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.
@@ -32,6 +32,8 @@ export interface ReplayTrainerState {
32
32
  correctMoveSquare: string | null;
33
33
  /** FEN shown on the board (includes a pending correct-move ply). */
34
34
  displayFen: string;
35
+ /** UCI of the move that produced the current board position. */
36
+ lastMoveUci: string | null;
35
37
  canPrev: boolean;
36
38
  canNext: boolean;
37
39
  goFirst: () => void;
package/dist/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
3
- import { useCorrectMoveFeedback, createExpectedMoveDropHandler, fenAfterUci, ThemeProvider, ChessboardDnDProvider, HighlightChessboard, PlyNavigation, AnalysisErrorBoundary, AnalysisBoard } from 'react-chess-core';
3
+ import { useCorrectMoveFeedback, lastMoveUciAtPly, createExpectedMoveDropHandler, fenAfterUci, ThemeProvider, ChessboardDnDProvider, HighlightChessboard, PlyNavigation, AnalysisErrorBoundary, AnalysisBoard } from 'react-chess-core';
4
4
  export { AnalysisBoard, AnalysisBoardCore, AnalysisErrorBoundary, DEFAULT_ANALYSIS_LAYOUT, DefaultPlyNavigation, PlyNavigation, MISS_MOVE_ANIMATION_MS as REPLAY_MISS_MOVE_ANIMATION_MS, MISS_REFUTATION_MAX_WAIT_MS as REPLAY_MISS_REFUTATION_MAX_WAIT_MS, MISS_REFUTATION_PAUSE_MS as REPLAY_MISS_REFUTATION_PAUSE_MS, MISS_WRONG_PAUSE_MS as REPLAY_MISS_WRONG_PAUSE_MS, REFUTATION_EVAL_GAP_CP as REPLAY_REFUTATION_EVAL_GAP_CP, REFUTATION_EVAL_GAP_PAWNS as REPLAY_REFUTATION_EVAL_GAP_PAWNS, defaultRenderPlyNavigation, fenAfterUci, getMissDisplay as getReplayMissDisplay, refutationEvalGapCp, refutationFromEvaluation, refutationEngineOptions as replayRefutationEngineOptions, uciFromDrop, useMissBoard as useReplayMissBoard, useMissSequence as useReplayMissSequence, useMissRefutation as useReplayRefutation } from 'react-chess-core';
5
5
  import { Chess } from 'chess.js';
6
6
 
@@ -136,6 +136,13 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
136
136
  const totalPly = movesUci.length;
137
137
  const fen = useMemo(() => fenAtPly(movesUci, plyIndex), [movesUci, plyIndex]);
138
138
  const displayFen = feedbackFen !== null && feedbackFen !== void 0 ? feedbackFen : fen;
139
+ const lastMoveUci = useMemo(() => {
140
+ var _a;
141
+ if (feedbackFen) {
142
+ return (_a = movesUci[plyIndex]) !== null && _a !== void 0 ? _a : null;
143
+ }
144
+ return lastMoveUciAtPly(movesUci, plyIndex);
145
+ }, [feedbackFen, movesUci, plyIndex]);
139
146
  const complete = plyIndex >= totalPly && totalPly > 0;
140
147
  const sideToMove$1 = sideToMove(fen);
141
148
  const isUserTurn = isTrainSideToMove(trainColor, sideToMove$1);
@@ -309,6 +316,7 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
309
316
  expectedUci,
310
317
  correctMoveSquare,
311
318
  displayFen,
319
+ lastMoveUci,
312
320
  canPrev: plyIndex > 0,
313
321
  canNext: plyIndex < totalPly,
314
322
  goFirst,
@@ -464,7 +472,7 @@ const ReplayTrainer = ({ gameId, fetchGame, startFen, onMiss, onComplete, onExit
464
472
  if (state.trainColor === 'black')
465
473
  return piece[0] === 'b';
466
474
  return piece[0] === state.sideToMove;
467
- }, onPieceDrop: (source, target, piece) => state.handleDrop(source, target, piece), customArrows: customArrows, promotionDialogVariant: "modal", areArrowsAllowed: false, customBoardStyle: customBoardStyle }) }), jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4 }, children: [jsx(PlyNavigation, { plyIndex: state.plyIndex, totalPly: state.totalPly, canPrev: state.canPrev, canNext: state.canNext, onGoFirst: state.goFirst, onGoPrev: state.goPrev, onGoNext: state.goNext, onGoLast: state.goLast, onGoTo: state.goTo, theme: theme, showScrubber: showPlyScrubber, renderPlyNavigation: renderPlyNavigation }), jsx("button", { type: "button", onClick: state.toggleAutoplay, disabled: !state.autoplayActive && !state.canNext, style: buttonStyle(colors, state.autoplayActive ? 'ghost' : 'primary'), "aria-label": state.autoplayActive ? 'Stop autoplay' : 'Autoplay game', children: state.autoplayActive ? 'Stop' : 'Play' })] }), jsxs("div", { style: statusLineStyle(colors), children: ["Half move ", Math.min(state.plyIndex + (state.complete ? 0 : 1), state.totalPly), " of", ' ', state.totalPly, training && !state.complete && (jsxs(Fragment, { children: [` · ${TRAIN_COLOR_LABEL[state.trainColor]}`, state.trainColor === 'both'
475
+ }, onPieceDrop: (source, target, piece) => state.handleDrop(source, target, piece), customArrows: customArrows, lastMoveUci: state.lastMoveUci, promotionDialogVariant: "modal", areArrowsAllowed: false, customBoardStyle: customBoardStyle }) }), jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4 }, children: [jsx(PlyNavigation, { plyIndex: state.plyIndex, totalPly: state.totalPly, canPrev: state.canPrev, canNext: state.canNext, onGoFirst: state.goFirst, onGoPrev: state.goPrev, onGoNext: state.goNext, onGoLast: state.goLast, onGoTo: state.goTo, theme: theme, showScrubber: showPlyScrubber, renderPlyNavigation: renderPlyNavigation }), jsx("button", { type: "button", onClick: state.toggleAutoplay, disabled: !state.autoplayActive && !state.canNext, style: buttonStyle(colors, state.autoplayActive ? 'ghost' : 'primary'), "aria-label": state.autoplayActive ? 'Stop autoplay' : 'Autoplay game', children: state.autoplayActive ? 'Stop' : 'Play' })] }), jsxs("div", { style: statusLineStyle(colors), children: ["Half move ", Math.min(state.plyIndex + (state.complete ? 0 : 1), state.totalPly), " of", ' ', state.totalPly, training && !state.complete && (jsxs(Fragment, { children: [` · ${TRAIN_COLOR_LABEL[state.trainColor]}`, state.trainColor === 'both'
468
476
  ? ` · ${state.sideToMove === 'b' ? 'Black' : 'White'} to move`
469
477
  : state.isUserTurn
470
478
  ? ' · Your move'
package/dist/index.js CHANGED
@@ -137,6 +137,13 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
137
137
  const totalPly = movesUci.length;
138
138
  const fen = react.useMemo(() => fenAtPly(movesUci, plyIndex), [movesUci, plyIndex]);
139
139
  const displayFen = feedbackFen !== null && feedbackFen !== void 0 ? feedbackFen : fen;
140
+ const lastMoveUci = react.useMemo(() => {
141
+ var _a;
142
+ if (feedbackFen) {
143
+ return (_a = movesUci[plyIndex]) !== null && _a !== void 0 ? _a : null;
144
+ }
145
+ return reactChessCore.lastMoveUciAtPly(movesUci, plyIndex);
146
+ }, [feedbackFen, movesUci, plyIndex]);
140
147
  const complete = plyIndex >= totalPly && totalPly > 0;
141
148
  const sideToMove$1 = sideToMove(fen);
142
149
  const isUserTurn = isTrainSideToMove(trainColor, sideToMove$1);
@@ -310,6 +317,7 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
310
317
  expectedUci,
311
318
  correctMoveSquare,
312
319
  displayFen,
320
+ lastMoveUci,
313
321
  canPrev: plyIndex > 0,
314
322
  canNext: plyIndex < totalPly,
315
323
  goFirst,
@@ -465,7 +473,7 @@ const ReplayTrainer = ({ gameId, fetchGame, startFen, onMiss, onComplete, onExit
465
473
  if (state.trainColor === 'black')
466
474
  return piece[0] === 'b';
467
475
  return piece[0] === state.sideToMove;
468
- }, onPieceDrop: (source, target, piece) => state.handleDrop(source, target, piece), customArrows: customArrows, promotionDialogVariant: "modal", areArrowsAllowed: false, customBoardStyle: customBoardStyle }) }), jsxRuntime.jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4 }, children: [jsxRuntime.jsx(reactChessCore.PlyNavigation, { plyIndex: state.plyIndex, totalPly: state.totalPly, canPrev: state.canPrev, canNext: state.canNext, onGoFirst: state.goFirst, onGoPrev: state.goPrev, onGoNext: state.goNext, onGoLast: state.goLast, onGoTo: state.goTo, theme: theme, showScrubber: showPlyScrubber, renderPlyNavigation: renderPlyNavigation }), jsxRuntime.jsx("button", { type: "button", onClick: state.toggleAutoplay, disabled: !state.autoplayActive && !state.canNext, style: buttonStyle(colors, state.autoplayActive ? 'ghost' : 'primary'), "aria-label": state.autoplayActive ? 'Stop autoplay' : 'Autoplay game', children: state.autoplayActive ? 'Stop' : 'Play' })] }), jsxRuntime.jsxs("div", { style: statusLineStyle(colors), children: ["Half move ", Math.min(state.plyIndex + (state.complete ? 0 : 1), state.totalPly), " of", ' ', state.totalPly, training && !state.complete && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [` · ${TRAIN_COLOR_LABEL[state.trainColor]}`, state.trainColor === 'both'
476
+ }, onPieceDrop: (source, target, piece) => state.handleDrop(source, target, piece), customArrows: customArrows, lastMoveUci: state.lastMoveUci, promotionDialogVariant: "modal", areArrowsAllowed: false, customBoardStyle: customBoardStyle }) }), jsxRuntime.jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 4 }, children: [jsxRuntime.jsx(reactChessCore.PlyNavigation, { plyIndex: state.plyIndex, totalPly: state.totalPly, canPrev: state.canPrev, canNext: state.canNext, onGoFirst: state.goFirst, onGoPrev: state.goPrev, onGoNext: state.goNext, onGoLast: state.goLast, onGoTo: state.goTo, theme: theme, showScrubber: showPlyScrubber, renderPlyNavigation: renderPlyNavigation }), jsxRuntime.jsx("button", { type: "button", onClick: state.toggleAutoplay, disabled: !state.autoplayActive && !state.canNext, style: buttonStyle(colors, state.autoplayActive ? 'ghost' : 'primary'), "aria-label": state.autoplayActive ? 'Stop autoplay' : 'Autoplay game', children: state.autoplayActive ? 'Stop' : 'Play' })] }), jsxRuntime.jsxs("div", { style: statusLineStyle(colors), children: ["Half move ", Math.min(state.plyIndex + (state.complete ? 0 : 1), state.totalPly), " of", ' ', state.totalPly, training && !state.complete && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [` · ${TRAIN_COLOR_LABEL[state.trainColor]}`, state.trainColor === 'both'
469
477
  ? ` · ${state.sideToMove === 'b' ? 'Black' : 'White'} to move`
470
478
  : state.isUserTurn
471
479
  ? ' · Your move'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-chess-replay-trainer",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "React component for browsing a chess game and drilling its moves, reporting misses (uses react-chess-core for board and analysis)",
5
5
  "license": "MIT",
6
6
  "author": "Robert Blackwell",