react-chess-replay-trainer 0.0.3 → 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.
|
@@ -28,6 +28,12 @@ export interface ReplayTrainerState {
|
|
|
28
28
|
/** Revealed/expected move at the current ply (set after a miss or reveal). */
|
|
29
29
|
expectedSan: string | null;
|
|
30
30
|
expectedUci: string | null;
|
|
31
|
+
/** Destination square of the last correct guess (green check overlay). */
|
|
32
|
+
correctMoveSquare: string | null;
|
|
33
|
+
/** FEN shown on the board (includes a pending correct-move ply). */
|
|
34
|
+
displayFen: string;
|
|
35
|
+
/** UCI of the move that produced the current board position. */
|
|
36
|
+
lastMoveUci: string | null;
|
|
31
37
|
canPrev: boolean;
|
|
32
38
|
canNext: boolean;
|
|
33
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 { createExpectedMoveDropHandler, 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
|
|
|
@@ -78,6 +78,8 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
78
78
|
const [expectedSan, setExpectedSan] = useState(null);
|
|
79
79
|
const [autoplayActive, setAutoplayActive] = useState(false);
|
|
80
80
|
const [expectedUci, setExpectedUci] = useState(null);
|
|
81
|
+
const [feedbackFen, setFeedbackFen] = useState(null);
|
|
82
|
+
const { correctMoveSquare, showCorrectMove, clearCorrectMoveFeedback, isShowingCorrectMove, } = useCorrectMoveFeedback();
|
|
81
83
|
const fetchGameRef = useRef(fetchGame);
|
|
82
84
|
fetchGameRef.current = fetchGame;
|
|
83
85
|
const onMissRef = useRef(onMiss);
|
|
@@ -88,6 +90,8 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
88
90
|
const completedFiredRef = useRef(false);
|
|
89
91
|
const modeRef = useRef('browse');
|
|
90
92
|
const trainColorRef = useRef('both');
|
|
93
|
+
const showingCorrectMoveRef = useRef(false);
|
|
94
|
+
showingCorrectMoveRef.current = isShowingCorrectMove;
|
|
91
95
|
useEffect(() => {
|
|
92
96
|
let cancelled = false;
|
|
93
97
|
setLoading(true);
|
|
@@ -131,6 +135,14 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
131
135
|
const movesUci = useMemo(() => { var _a; return (_a = game === null || game === void 0 ? void 0 : game.movesUci) !== null && _a !== void 0 ? _a : []; }, [game]);
|
|
132
136
|
const totalPly = movesUci.length;
|
|
133
137
|
const fen = useMemo(() => fenAtPly(movesUci, plyIndex), [movesUci, plyIndex]);
|
|
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]);
|
|
134
146
|
const complete = plyIndex >= totalPly && totalPly > 0;
|
|
135
147
|
const sideToMove$1 = sideToMove(fen);
|
|
136
148
|
const isUserTurn = isTrainSideToMove(trainColor, sideToMove$1);
|
|
@@ -140,7 +152,9 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
140
152
|
setFeedback(null);
|
|
141
153
|
setExpectedSan(null);
|
|
142
154
|
setExpectedUci(null);
|
|
143
|
-
|
|
155
|
+
setFeedbackFen(null);
|
|
156
|
+
clearCorrectMoveFeedback();
|
|
157
|
+
}, [clearCorrectMoveFeedback]);
|
|
144
158
|
const stopAutoplay = useCallback(() => {
|
|
145
159
|
setAutoplayActive(false);
|
|
146
160
|
}, []);
|
|
@@ -220,12 +234,21 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
220
234
|
expectedUci: movesUci[plyIndex],
|
|
221
235
|
enabled: modeRef.current === 'train' &&
|
|
222
236
|
!complete &&
|
|
237
|
+
!showingCorrectMoveRef.current &&
|
|
223
238
|
isTrainSideToMove(trainColorRef.current, sideToMove$1),
|
|
224
|
-
onCorrect: () => {
|
|
239
|
+
onCorrect: (uci) => {
|
|
225
240
|
setFeedback('correct');
|
|
226
241
|
setExpectedSan(null);
|
|
227
242
|
setExpectedUci(null);
|
|
228
|
-
|
|
243
|
+
const nextFen = fenAfterUci(fen, uci);
|
|
244
|
+
if (nextFen) {
|
|
245
|
+
setFeedbackFen(nextFen);
|
|
246
|
+
}
|
|
247
|
+
showCorrectMove(uci.slice(2, 4), () => {
|
|
248
|
+
setFeedbackFen(null);
|
|
249
|
+
setFeedback(null);
|
|
250
|
+
setPlyIndex((p) => p + 1);
|
|
251
|
+
});
|
|
229
252
|
},
|
|
230
253
|
onIncorrect: () => {
|
|
231
254
|
var _a, _b;
|
|
@@ -238,7 +261,7 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
238
261
|
setExpectedUci(expectedUci);
|
|
239
262
|
recordMiss(plyIndex);
|
|
240
263
|
},
|
|
241
|
-
})(source, target, piece), [complete, movesUci, plyIndex,
|
|
264
|
+
})(source, target, piece), [complete, fen, movesUci, plyIndex, game, recordMiss, sideToMove$1, showCorrectMove]);
|
|
242
265
|
useEffect(() => {
|
|
243
266
|
var _a;
|
|
244
267
|
if (mode === 'train' && complete && !completedFiredRef.current) {
|
|
@@ -267,12 +290,15 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
267
290
|
if (mode !== 'train' || complete || trainColor === 'both' || isUserTurn) {
|
|
268
291
|
return;
|
|
269
292
|
}
|
|
293
|
+
if (isShowingCorrectMove) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
270
296
|
const id = setTimeout(() => {
|
|
271
297
|
setPlyIndex((p) => (p < totalPly ? p + 1 : p));
|
|
272
298
|
clearTransient();
|
|
273
299
|
}, OPPONENT_MOVE_DELAY_MS);
|
|
274
300
|
return () => clearTimeout(id);
|
|
275
|
-
}, [mode, complete, trainColor, isUserTurn, plyIndex, totalPly, clearTransient]);
|
|
301
|
+
}, [mode, complete, trainColor, isUserTurn, plyIndex, totalPly, clearTransient, isShowingCorrectMove]);
|
|
276
302
|
return {
|
|
277
303
|
game,
|
|
278
304
|
loading,
|
|
@@ -288,6 +314,9 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
288
314
|
feedback,
|
|
289
315
|
expectedSan,
|
|
290
316
|
expectedUci,
|
|
317
|
+
correctMoveSquare,
|
|
318
|
+
displayFen,
|
|
319
|
+
lastMoveUci,
|
|
291
320
|
canPrev: plyIndex > 0,
|
|
292
321
|
canNext: plyIndex < totalPly,
|
|
293
322
|
goFirst,
|
|
@@ -437,13 +466,13 @@ const ReplayTrainer = ({ gameId, fetchGame, startFen, onMiss, onComplete, onExit
|
|
|
437
466
|
]
|
|
438
467
|
: [];
|
|
439
468
|
const draggable = training && !state.complete;
|
|
440
|
-
return (jsxs(ThemeProvider, { theme: theme, boardTheme: boardTheme, children: [jsxs("div", { style: mainContainerStyle(boardWidth, colors), children: [jsxs("div", { style: headerStyle, children: [jsxs("span", { style: playerNameStyle, children: [((_b = game.white) !== null && _b !== void 0 ? _b : 'White'), " vs ", ((_c = game.black) !== null && _c !== void 0 ? _c : 'Black')] }), game.result && jsx("span", { style: subtleTextStyle(colors), children: game.result })] }), jsx(ChessboardDnDProvider, { children: jsx(HighlightChessboard, { boardWidth: boardWidth, checkSquare: "", hintSquare: null, incorrectMoveSquare: null, position: state.
|
|
469
|
+
return (jsxs(ThemeProvider, { theme: theme, boardTheme: boardTheme, children: [jsxs("div", { style: mainContainerStyle(boardWidth, colors), children: [jsxs("div", { style: headerStyle, children: [jsxs("span", { style: playerNameStyle, children: [((_b = game.white) !== null && _b !== void 0 ? _b : 'White'), " vs ", ((_c = game.black) !== null && _c !== void 0 ? _c : 'Black')] }), game.result && jsx("span", { style: subtleTextStyle(colors), children: game.result })] }), jsx(ChessboardDnDProvider, { children: jsx(HighlightChessboard, { boardWidth: boardWidth, checkSquare: "", hintSquare: null, incorrectMoveSquare: null, correctMoveSquare: state.correctMoveSquare, position: state.displayFen, boardOrientation: boardOrientation, arePiecesDraggable: draggable && !state.correctMoveSquare, isDraggablePiece: ({ piece }) => {
|
|
441
470
|
if (state.trainColor === 'white')
|
|
442
471
|
return piece[0] === 'w';
|
|
443
472
|
if (state.trainColor === 'black')
|
|
444
473
|
return piece[0] === 'b';
|
|
445
474
|
return piece[0] === state.sideToMove;
|
|
446
|
-
}, 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'
|
|
447
476
|
? ` · ${state.sideToMove === 'b' ? 'Black' : 'White'} to move`
|
|
448
477
|
: state.isUserTurn
|
|
449
478
|
? ' · Your move'
|
package/dist/index.js
CHANGED
|
@@ -79,6 +79,8 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
79
79
|
const [expectedSan, setExpectedSan] = react.useState(null);
|
|
80
80
|
const [autoplayActive, setAutoplayActive] = react.useState(false);
|
|
81
81
|
const [expectedUci, setExpectedUci] = react.useState(null);
|
|
82
|
+
const [feedbackFen, setFeedbackFen] = react.useState(null);
|
|
83
|
+
const { correctMoveSquare, showCorrectMove, clearCorrectMoveFeedback, isShowingCorrectMove, } = reactChessCore.useCorrectMoveFeedback();
|
|
82
84
|
const fetchGameRef = react.useRef(fetchGame);
|
|
83
85
|
fetchGameRef.current = fetchGame;
|
|
84
86
|
const onMissRef = react.useRef(onMiss);
|
|
@@ -89,6 +91,8 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
89
91
|
const completedFiredRef = react.useRef(false);
|
|
90
92
|
const modeRef = react.useRef('browse');
|
|
91
93
|
const trainColorRef = react.useRef('both');
|
|
94
|
+
const showingCorrectMoveRef = react.useRef(false);
|
|
95
|
+
showingCorrectMoveRef.current = isShowingCorrectMove;
|
|
92
96
|
react.useEffect(() => {
|
|
93
97
|
let cancelled = false;
|
|
94
98
|
setLoading(true);
|
|
@@ -132,6 +136,14 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
132
136
|
const movesUci = react.useMemo(() => { var _a; return (_a = game === null || game === void 0 ? void 0 : game.movesUci) !== null && _a !== void 0 ? _a : []; }, [game]);
|
|
133
137
|
const totalPly = movesUci.length;
|
|
134
138
|
const fen = react.useMemo(() => fenAtPly(movesUci, plyIndex), [movesUci, plyIndex]);
|
|
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]);
|
|
135
147
|
const complete = plyIndex >= totalPly && totalPly > 0;
|
|
136
148
|
const sideToMove$1 = sideToMove(fen);
|
|
137
149
|
const isUserTurn = isTrainSideToMove(trainColor, sideToMove$1);
|
|
@@ -141,7 +153,9 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
141
153
|
setFeedback(null);
|
|
142
154
|
setExpectedSan(null);
|
|
143
155
|
setExpectedUci(null);
|
|
144
|
-
|
|
156
|
+
setFeedbackFen(null);
|
|
157
|
+
clearCorrectMoveFeedback();
|
|
158
|
+
}, [clearCorrectMoveFeedback]);
|
|
145
159
|
const stopAutoplay = react.useCallback(() => {
|
|
146
160
|
setAutoplayActive(false);
|
|
147
161
|
}, []);
|
|
@@ -221,12 +235,21 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
221
235
|
expectedUci: movesUci[plyIndex],
|
|
222
236
|
enabled: modeRef.current === 'train' &&
|
|
223
237
|
!complete &&
|
|
238
|
+
!showingCorrectMoveRef.current &&
|
|
224
239
|
isTrainSideToMove(trainColorRef.current, sideToMove$1),
|
|
225
|
-
onCorrect: () => {
|
|
240
|
+
onCorrect: (uci) => {
|
|
226
241
|
setFeedback('correct');
|
|
227
242
|
setExpectedSan(null);
|
|
228
243
|
setExpectedUci(null);
|
|
229
|
-
|
|
244
|
+
const nextFen = reactChessCore.fenAfterUci(fen, uci);
|
|
245
|
+
if (nextFen) {
|
|
246
|
+
setFeedbackFen(nextFen);
|
|
247
|
+
}
|
|
248
|
+
showCorrectMove(uci.slice(2, 4), () => {
|
|
249
|
+
setFeedbackFen(null);
|
|
250
|
+
setFeedback(null);
|
|
251
|
+
setPlyIndex((p) => p + 1);
|
|
252
|
+
});
|
|
230
253
|
},
|
|
231
254
|
onIncorrect: () => {
|
|
232
255
|
var _a, _b;
|
|
@@ -239,7 +262,7 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
239
262
|
setExpectedUci(expectedUci);
|
|
240
263
|
recordMiss(plyIndex);
|
|
241
264
|
},
|
|
242
|
-
})(source, target, piece), [complete, movesUci, plyIndex,
|
|
265
|
+
})(source, target, piece), [complete, fen, movesUci, plyIndex, game, recordMiss, sideToMove$1, showCorrectMove]);
|
|
243
266
|
react.useEffect(() => {
|
|
244
267
|
var _a;
|
|
245
268
|
if (mode === 'train' && complete && !completedFiredRef.current) {
|
|
@@ -268,12 +291,15 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
268
291
|
if (mode !== 'train' || complete || trainColor === 'both' || isUserTurn) {
|
|
269
292
|
return;
|
|
270
293
|
}
|
|
294
|
+
if (isShowingCorrectMove) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
271
297
|
const id = setTimeout(() => {
|
|
272
298
|
setPlyIndex((p) => (p < totalPly ? p + 1 : p));
|
|
273
299
|
clearTransient();
|
|
274
300
|
}, OPPONENT_MOVE_DELAY_MS);
|
|
275
301
|
return () => clearTimeout(id);
|
|
276
|
-
}, [mode, complete, trainColor, isUserTurn, plyIndex, totalPly, clearTransient]);
|
|
302
|
+
}, [mode, complete, trainColor, isUserTurn, plyIndex, totalPly, clearTransient, isShowingCorrectMove]);
|
|
277
303
|
return {
|
|
278
304
|
game,
|
|
279
305
|
loading,
|
|
@@ -289,6 +315,9 @@ function useReplayTrainer({ gameId, startFen, fetchGame, onMiss, onComplete, })
|
|
|
289
315
|
feedback,
|
|
290
316
|
expectedSan,
|
|
291
317
|
expectedUci,
|
|
318
|
+
correctMoveSquare,
|
|
319
|
+
displayFen,
|
|
320
|
+
lastMoveUci,
|
|
292
321
|
canPrev: plyIndex > 0,
|
|
293
322
|
canNext: plyIndex < totalPly,
|
|
294
323
|
goFirst,
|
|
@@ -438,13 +467,13 @@ const ReplayTrainer = ({ gameId, fetchGame, startFen, onMiss, onComplete, onExit
|
|
|
438
467
|
]
|
|
439
468
|
: [];
|
|
440
469
|
const draggable = training && !state.complete;
|
|
441
|
-
return (jsxRuntime.jsxs(reactChessCore.ThemeProvider, { theme: theme, boardTheme: boardTheme, children: [jsxRuntime.jsxs("div", { style: mainContainerStyle(boardWidth, colors), children: [jsxRuntime.jsxs("div", { style: headerStyle, children: [jsxRuntime.jsxs("span", { style: playerNameStyle, children: [((_b = game.white) !== null && _b !== void 0 ? _b : 'White'), " vs ", ((_c = game.black) !== null && _c !== void 0 ? _c : 'Black')] }), game.result && jsxRuntime.jsx("span", { style: subtleTextStyle(colors), children: game.result })] }), jsxRuntime.jsx(reactChessCore.ChessboardDnDProvider, { children: jsxRuntime.jsx(reactChessCore.HighlightChessboard, { boardWidth: boardWidth, checkSquare: "", hintSquare: null, incorrectMoveSquare: null, position: state.
|
|
470
|
+
return (jsxRuntime.jsxs(reactChessCore.ThemeProvider, { theme: theme, boardTheme: boardTheme, children: [jsxRuntime.jsxs("div", { style: mainContainerStyle(boardWidth, colors), children: [jsxRuntime.jsxs("div", { style: headerStyle, children: [jsxRuntime.jsxs("span", { style: playerNameStyle, children: [((_b = game.white) !== null && _b !== void 0 ? _b : 'White'), " vs ", ((_c = game.black) !== null && _c !== void 0 ? _c : 'Black')] }), game.result && jsxRuntime.jsx("span", { style: subtleTextStyle(colors), children: game.result })] }), jsxRuntime.jsx(reactChessCore.ChessboardDnDProvider, { children: jsxRuntime.jsx(reactChessCore.HighlightChessboard, { boardWidth: boardWidth, checkSquare: "", hintSquare: null, incorrectMoveSquare: null, correctMoveSquare: state.correctMoveSquare, position: state.displayFen, boardOrientation: boardOrientation, arePiecesDraggable: draggable && !state.correctMoveSquare, isDraggablePiece: ({ piece }) => {
|
|
442
471
|
if (state.trainColor === 'white')
|
|
443
472
|
return piece[0] === 'w';
|
|
444
473
|
if (state.trainColor === 'black')
|
|
445
474
|
return piece[0] === 'b';
|
|
446
475
|
return piece[0] === state.sideToMove;
|
|
447
|
-
}, 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'
|
|
448
477
|
? ` · ${state.sideToMove === 'b' ? 'Black' : 'White'} to move`
|
|
449
478
|
: state.isUserTurn
|
|
450
479
|
? ' · Your move'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-chess-replay-trainer",
|
|
3
|
-
"version": "0.0.
|
|
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",
|