react-chess-core 0.1.2 → 0.1.4
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/dist/features/analysis/core/AnalysisPosition.d.ts +1 -0
- package/dist/features/analysis/core/useAnalysisBoardModel.d.ts +1 -0
- package/dist/features/chessboard/CorrectMoveCheckBadge.d.ts +3 -0
- package/dist/features/chessboard/HighlightChessboard.d.ts +9 -1
- package/dist/features/chessboard/boardSquareHighlightColors.d.ts +3 -0
- package/dist/features/chessboard/createFeedbackSquareRenderer.d.ts +3 -0
- package/dist/features/chessboard/index.d.ts +2 -0
- package/dist/features/chessboard/lastMoveArrow.d.ts +8 -0
- package/dist/features/chessboard/useClickToMove.d.ts +28 -0
- package/dist/features/training/correctMoveFeedbackMs.d.ts +2 -0
- package/dist/features/training/index.d.ts +2 -0
- package/dist/features/training/miss/missDisplay.d.ts +1 -0
- package/dist/features/training/miss/useMissBoard.d.ts +1 -0
- package/dist/features/training/useCorrectMoveFeedback.d.ts +6 -0
- package/dist/index.esm.js +304 -17
- package/dist/index.js +310 -15
- package/dist/stories/Chessboard.stories.d.ts +2 -0
- package/package.json +1 -1
|
@@ -2,6 +2,14 @@ export interface HighlightChessboardProps {
|
|
|
2
2
|
checkSquare: string;
|
|
3
3
|
hintSquare: string | null;
|
|
4
4
|
incorrectMoveSquare: string | null;
|
|
5
|
+
/** Destination square of the last correct training move — shows a green check. */
|
|
6
|
+
correctMoveSquare?: string | null;
|
|
7
|
+
/** UCI of the move that led to the current position (shows a last-move arrow). */
|
|
8
|
+
lastMoveUci?: string | null;
|
|
9
|
+
/** Override the default last-move arrow color. */
|
|
10
|
+
lastMoveArrowColor?: string;
|
|
11
|
+
/** Enable click-to-move when `onPieceDrop` is provided. Defaults to true. */
|
|
12
|
+
clickToMove?: boolean;
|
|
5
13
|
[key: string]: any;
|
|
6
14
|
}
|
|
7
|
-
export declare const HighlightChessboard: ({ checkSquare, hintSquare, incorrectMoveSquare, customSquareStyles: extraSquareStyles, ...props }: HighlightChessboardProps) => import("react").JSX.Element;
|
|
15
|
+
export declare const HighlightChessboard: ({ checkSquare, hintSquare, incorrectMoveSquare, correctMoveSquare, lastMoveUci, lastMoveArrowColor, clickToMove, customSquareStyles: extraSquareStyles, customArrows, customBoardStyle, onPieceDrop, position, arePiecesDraggable, autoPromoteToQueen, isDraggablePiece, onPromotionCheck, onSquareClick, onPromotionPieceSelect, onPieceDragBegin, showPromotionDialog: showPromotionDialogProp, promotionToSquare: promotionToSquareProp, ...props }: HighlightChessboardProps) => import("react").JSX.Element;
|
|
@@ -6,4 +6,7 @@ export declare const boardSquareHighlightColors: {
|
|
|
6
6
|
readonly hint: "rgba(119, 177, 212, 0.75)";
|
|
7
7
|
/** Muted red — softer than the in-check highlight. */
|
|
8
8
|
readonly incorrect: "rgba(140, 38, 38, 0.82)";
|
|
9
|
+
readonly selected: "rgba(255, 255, 0, 0.45)";
|
|
10
|
+
readonly moveTarget: "radial-gradient(circle, rgba(0, 0, 0, 0.18) 22%, transparent 22%)";
|
|
11
|
+
readonly captureTarget: "radial-gradient(circle, rgba(0, 0, 0, 0.18) 72%, transparent 72%)";
|
|
9
12
|
};
|
|
@@ -2,4 +2,6 @@ export * from './boardThemes';
|
|
|
2
2
|
export * from './chessboardTheme';
|
|
3
3
|
export * from './ChessboardDnDProvider';
|
|
4
4
|
export * from './HighlightChessboard';
|
|
5
|
+
export * from './CorrectMoveCheckBadge';
|
|
5
6
|
export * from './boardSquareHighlightColors';
|
|
7
|
+
export * from './lastMoveArrow';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type ChessboardArrow = [string, string, string];
|
|
2
|
+
/** Subtle green arrow visible on light and dark boards (Lichess-style). */
|
|
3
|
+
export declare const DEFAULT_LAST_MOVE_ARROW_COLOR = "rgba(155, 199, 0, 0.85)";
|
|
4
|
+
export declare const uciToArrow: (uci: string, color?: string) => ChessboardArrow;
|
|
5
|
+
export declare const lastMoveArrowFromUci: (uci: string | null | undefined, color?: string) => ChessboardArrow[];
|
|
6
|
+
/** UCI of the move that produced the position at {@link plyIndex}. */
|
|
7
|
+
export declare const lastMoveUciAtPly: (movesUci: readonly string[], plyIndex: number) => string | null;
|
|
8
|
+
export declare const mergeCustomArrowsWithLastMove: (customArrows: ChessboardArrow[] | undefined, lastMoveUci: string | null | undefined, lastMoveArrowColor?: string) => ChessboardArrow[];
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Square } from 'chess.js';
|
|
2
|
+
import { type CSSProperties } from 'react';
|
|
3
|
+
type Piece = string;
|
|
4
|
+
export type ClickToMoveSquareStyles = Record<string, CSSProperties>;
|
|
5
|
+
export type UseClickToMoveOptions = {
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
position: string | undefined;
|
|
8
|
+
arePiecesDraggable?: boolean;
|
|
9
|
+
autoPromoteToQueen?: boolean;
|
|
10
|
+
isDraggablePiece?: (args: {
|
|
11
|
+
piece: Piece;
|
|
12
|
+
sourceSquare: Square;
|
|
13
|
+
}) => boolean;
|
|
14
|
+
onPromotionCheck?: (sourceSquare: Square, targetSquare: Square, piece: Piece) => boolean;
|
|
15
|
+
onPieceDrop?: (sourceSquare: Square, targetSquare: Square, piece: Piece) => boolean;
|
|
16
|
+
onSquareClick?: (square: Square, piece: Piece | undefined) => void;
|
|
17
|
+
onPromotionPieceSelect?: (piece?: Piece, promoteFromSquare?: Square, promoteToSquare?: Square) => boolean;
|
|
18
|
+
onPieceDragBegin?: (piece: Piece, sourceSquare: Square) => void;
|
|
19
|
+
};
|
|
20
|
+
export declare function useClickToMove({ enabled, position, arePiecesDraggable, autoPromoteToQueen, isDraggablePiece, onPromotionCheck, onPieceDrop, onSquareClick, onPromotionPieceSelect, onPieceDragBegin, }: UseClickToMoveOptions): {
|
|
21
|
+
clickSquareStyles: ClickToMoveSquareStyles;
|
|
22
|
+
handleSquareClick: (square: Square, piece: Piece | undefined) => void;
|
|
23
|
+
handlePromotionPieceSelect: (piece?: Piece, promoteFromSquare?: Square, promoteToSquare?: Square) => boolean;
|
|
24
|
+
handlePieceDragBegin: (piece: Piece, sourceSquare: Square) => void;
|
|
25
|
+
showPromotionDialog: boolean;
|
|
26
|
+
promotionToSquare: Square | null;
|
|
27
|
+
};
|
|
28
|
+
export {};
|
|
@@ -19,6 +19,7 @@ export declare function useMissBoard({ feedback, expectedUci, positionFen, answe
|
|
|
19
19
|
customArrows: [string, string, string][];
|
|
20
20
|
boardPosition: string;
|
|
21
21
|
boardAnimating: boolean;
|
|
22
|
+
lastMoveUci: string | null;
|
|
22
23
|
wrapDropHandler: (onDrop: (source: string, target: string, piece: string) => boolean, { enabled, dropFen, expectedMoveUci, }: {
|
|
23
24
|
enabled: boolean;
|
|
24
25
|
dropFen?: string;
|
package/dist/index.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { createContext, useContext,
|
|
2
|
+
import { createContext, useContext, useState, useCallback, useEffect, useMemo, useRef, useLayoutEffect, Component } from 'react';
|
|
3
3
|
import { ChessboardDnDProvider as ChessboardDnDProvider$1, Chessboard } from 'react-chessboard';
|
|
4
4
|
import { Chess } from 'chess.js';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
@@ -1741,8 +1741,225 @@ const boardSquareHighlightColors = {
|
|
|
1741
1741
|
hint: 'rgba(119, 177, 212, 0.75)',
|
|
1742
1742
|
/** Muted red — softer than the in-check highlight. */
|
|
1743
1743
|
incorrect: 'rgba(140, 38, 38, 0.82)',
|
|
1744
|
+
selected: 'rgba(255, 255, 0, 0.45)',
|
|
1745
|
+
moveTarget: 'radial-gradient(circle, rgba(0, 0, 0, 0.18) 22%, transparent 22%)',
|
|
1746
|
+
captureTarget: 'radial-gradient(circle, rgba(0, 0, 0, 0.18) 72%, transparent 72%)',
|
|
1744
1747
|
};
|
|
1745
1748
|
|
|
1749
|
+
const badgeStyle = {
|
|
1750
|
+
position: 'absolute',
|
|
1751
|
+
right: '6%',
|
|
1752
|
+
bottom: '6%',
|
|
1753
|
+
width: '26%',
|
|
1754
|
+
height: '26%',
|
|
1755
|
+
minWidth: 14,
|
|
1756
|
+
minHeight: 14,
|
|
1757
|
+
maxWidth: 26,
|
|
1758
|
+
maxHeight: 26,
|
|
1759
|
+
borderRadius: '50%',
|
|
1760
|
+
backgroundColor: '#2e7d32',
|
|
1761
|
+
display: 'flex',
|
|
1762
|
+
alignItems: 'center',
|
|
1763
|
+
justifyContent: 'center',
|
|
1764
|
+
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.35)',
|
|
1765
|
+
pointerEvents: 'none',
|
|
1766
|
+
};
|
|
1767
|
+
/** Green circle with a white check, anchored to the bottom-right of a square
|
|
1768
|
+
* square (over the piece). */
|
|
1769
|
+
const CorrectMoveCheckBadge = () => (jsx("span", { "aria-hidden": true, style: badgeStyle, children: jsx("svg", { viewBox: "0 0 12 12", width: "62%", height: "62%", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsx("path", { d: "M2.5 6.2 5 8.7 9.5 3.8", stroke: "#fff", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
|
|
1770
|
+
|
|
1771
|
+
const overlayStyle$1 = {
|
|
1772
|
+
position: 'absolute',
|
|
1773
|
+
inset: 0,
|
|
1774
|
+
pointerEvents: 'none',
|
|
1775
|
+
zIndex: 20,
|
|
1776
|
+
overflow: 'visible',
|
|
1777
|
+
};
|
|
1778
|
+
function createFeedbackSquareRenderer(correctMoveSquare) {
|
|
1779
|
+
return function FeedbackSquare({ children, style, square, ref }) {
|
|
1780
|
+
return (jsxs("div", { ref: ref, style: Object.assign(Object.assign({}, style), { position: 'relative', overflow: 'visible' }), children: [children, square === correctMoveSquare ? (jsx("div", { style: overlayStyle$1, children: jsx(CorrectMoveCheckBadge, {}) })) : null] }));
|
|
1781
|
+
};
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
/** Subtle green arrow visible on light and dark boards (Lichess-style). */
|
|
1785
|
+
const DEFAULT_LAST_MOVE_ARROW_COLOR = 'rgba(155, 199, 0, 0.85)';
|
|
1786
|
+
const uciToArrow = (uci, color = DEFAULT_LAST_MOVE_ARROW_COLOR) => [uci.slice(0, 2), uci.slice(2, 4), color];
|
|
1787
|
+
const lastMoveArrowFromUci = (uci, color = DEFAULT_LAST_MOVE_ARROW_COLOR) => {
|
|
1788
|
+
if (!uci || uci.length < 4) {
|
|
1789
|
+
return [];
|
|
1790
|
+
}
|
|
1791
|
+
return [uciToArrow(uci, color)];
|
|
1792
|
+
};
|
|
1793
|
+
/** UCI of the move that produced the position at {@link plyIndex}. */
|
|
1794
|
+
const lastMoveUciAtPly = (movesUci, plyIndex) => {
|
|
1795
|
+
var _a;
|
|
1796
|
+
if (plyIndex <= 0) {
|
|
1797
|
+
return null;
|
|
1798
|
+
}
|
|
1799
|
+
return (_a = movesUci[plyIndex - 1]) !== null && _a !== void 0 ? _a : null;
|
|
1800
|
+
};
|
|
1801
|
+
const mergeCustomArrowsWithLastMove = (customArrows, lastMoveUci, lastMoveArrowColor) => {
|
|
1802
|
+
const lastMove = lastMoveArrowFromUci(lastMoveUci, lastMoveArrowColor);
|
|
1803
|
+
if (!lastMove.length) {
|
|
1804
|
+
return customArrows !== null && customArrows !== void 0 ? customArrows : [];
|
|
1805
|
+
}
|
|
1806
|
+
return [...lastMove, ...(customArrows !== null && customArrows !== void 0 ? customArrows : [])];
|
|
1807
|
+
};
|
|
1808
|
+
|
|
1809
|
+
function defaultPromotionCheck(sourceSquare, targetSquare, piece) {
|
|
1810
|
+
return (((piece === 'wP' && sourceSquare[1] === '7' && targetSquare[1] === '8') ||
|
|
1811
|
+
(piece === 'bP' && sourceSquare[1] === '2' && targetSquare[1] === '1')) &&
|
|
1812
|
+
Math.abs(sourceSquare.charCodeAt(0) - targetSquare.charCodeAt(0)) <= 1);
|
|
1813
|
+
}
|
|
1814
|
+
function pieceAtSquare(fen, square) {
|
|
1815
|
+
const boardPiece = new Chess(fen).get(square);
|
|
1816
|
+
if (!boardPiece) {
|
|
1817
|
+
return null;
|
|
1818
|
+
}
|
|
1819
|
+
const color = boardPiece.color === 'w' ? 'w' : 'b';
|
|
1820
|
+
const type = boardPiece.type.toUpperCase();
|
|
1821
|
+
return `${color}${type}`;
|
|
1822
|
+
}
|
|
1823
|
+
function getMoveOptionStyles(fen, fromSquare) {
|
|
1824
|
+
const chess = new Chess(fen);
|
|
1825
|
+
const moves = chess.moves({ square: fromSquare, verbose: true });
|
|
1826
|
+
if (!moves.length) {
|
|
1827
|
+
return {
|
|
1828
|
+
[fromSquare]: { backgroundColor: boardSquareHighlightColors.selected },
|
|
1829
|
+
};
|
|
1830
|
+
}
|
|
1831
|
+
const styles = {
|
|
1832
|
+
[fromSquare]: { backgroundColor: boardSquareHighlightColors.selected },
|
|
1833
|
+
};
|
|
1834
|
+
for (const move of moves) {
|
|
1835
|
+
styles[move.to] = {
|
|
1836
|
+
background: chess.get(move.to)
|
|
1837
|
+
? boardSquareHighlightColors.captureTarget
|
|
1838
|
+
: boardSquareHighlightColors.moveTarget,
|
|
1839
|
+
borderRadius: '50%',
|
|
1840
|
+
};
|
|
1841
|
+
}
|
|
1842
|
+
return styles;
|
|
1843
|
+
}
|
|
1844
|
+
function useClickToMove({ enabled, position, arePiecesDraggable = true, autoPromoteToQueen = false, isDraggablePiece, onPromotionCheck = defaultPromotionCheck, onPieceDrop, onSquareClick, onPromotionPieceSelect, onPieceDragBegin, }) {
|
|
1845
|
+
var _a;
|
|
1846
|
+
const [moveFrom, setMoveFrom] = useState(null);
|
|
1847
|
+
const [pendingPromotion, setPendingPromotion] = useState(null);
|
|
1848
|
+
const fen = typeof position === 'string' ? position : undefined;
|
|
1849
|
+
const clearSelection = useCallback(() => {
|
|
1850
|
+
setMoveFrom(null);
|
|
1851
|
+
setPendingPromotion(null);
|
|
1852
|
+
}, []);
|
|
1853
|
+
useEffect(() => {
|
|
1854
|
+
clearSelection();
|
|
1855
|
+
}, [fen, clearSelection]);
|
|
1856
|
+
const clickSquareStyles = useMemo(() => {
|
|
1857
|
+
if (!enabled || !moveFrom || !fen) {
|
|
1858
|
+
return {};
|
|
1859
|
+
}
|
|
1860
|
+
return getMoveOptionStyles(fen, moveFrom);
|
|
1861
|
+
}, [enabled, fen, moveFrom]);
|
|
1862
|
+
const canSelectPiece = useCallback((square, piece) => {
|
|
1863
|
+
if (!piece || !arePiecesDraggable || !onPieceDrop) {
|
|
1864
|
+
return false;
|
|
1865
|
+
}
|
|
1866
|
+
if (isDraggablePiece) {
|
|
1867
|
+
return isDraggablePiece({ piece, sourceSquare: square });
|
|
1868
|
+
}
|
|
1869
|
+
return true;
|
|
1870
|
+
}, [arePiecesDraggable, isDraggablePiece, onPieceDrop]);
|
|
1871
|
+
const tryCompleteMove = useCallback((from, to, piece) => {
|
|
1872
|
+
if (!onPieceDrop) {
|
|
1873
|
+
return false;
|
|
1874
|
+
}
|
|
1875
|
+
if (onPromotionCheck(from, to, piece)) {
|
|
1876
|
+
if (autoPromoteToQueen) {
|
|
1877
|
+
const promotedPiece = piece[0] === 'w' ? 'wQ' : 'bQ';
|
|
1878
|
+
const accepted = onPieceDrop(from, to, promotedPiece);
|
|
1879
|
+
clearSelection();
|
|
1880
|
+
return accepted;
|
|
1881
|
+
}
|
|
1882
|
+
setPendingPromotion({ from, to, piece });
|
|
1883
|
+
setMoveFrom(null);
|
|
1884
|
+
return true;
|
|
1885
|
+
}
|
|
1886
|
+
const accepted = onPieceDrop(from, to, piece);
|
|
1887
|
+
clearSelection();
|
|
1888
|
+
return accepted;
|
|
1889
|
+
}, [autoPromoteToQueen, clearSelection, onPieceDrop, onPromotionCheck]);
|
|
1890
|
+
const handleSquareClick = useCallback((square, piece) => {
|
|
1891
|
+
onSquareClick === null || onSquareClick === void 0 ? void 0 : onSquareClick(square, piece);
|
|
1892
|
+
if (!enabled || !onPieceDrop || !arePiecesDraggable || !fen) {
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
1895
|
+
if (!moveFrom) {
|
|
1896
|
+
if (canSelectPiece(square, piece)) {
|
|
1897
|
+
setMoveFrom(square);
|
|
1898
|
+
}
|
|
1899
|
+
return;
|
|
1900
|
+
}
|
|
1901
|
+
if (square === moveFrom) {
|
|
1902
|
+
clearSelection();
|
|
1903
|
+
return;
|
|
1904
|
+
}
|
|
1905
|
+
const sourcePiece = pieceAtSquare(fen, moveFrom);
|
|
1906
|
+
if (!sourcePiece) {
|
|
1907
|
+
clearSelection();
|
|
1908
|
+
return;
|
|
1909
|
+
}
|
|
1910
|
+
const accepted = tryCompleteMove(moveFrom, square, sourcePiece);
|
|
1911
|
+
if (accepted) {
|
|
1912
|
+
return;
|
|
1913
|
+
}
|
|
1914
|
+
if (canSelectPiece(square, piece)) {
|
|
1915
|
+
setMoveFrom(square);
|
|
1916
|
+
return;
|
|
1917
|
+
}
|
|
1918
|
+
clearSelection();
|
|
1919
|
+
}, [
|
|
1920
|
+
arePiecesDraggable,
|
|
1921
|
+
canSelectPiece,
|
|
1922
|
+
clearSelection,
|
|
1923
|
+
enabled,
|
|
1924
|
+
fen,
|
|
1925
|
+
moveFrom,
|
|
1926
|
+
onPieceDrop,
|
|
1927
|
+
onSquareClick,
|
|
1928
|
+
tryCompleteMove,
|
|
1929
|
+
]);
|
|
1930
|
+
const handlePromotionPieceSelect = useCallback((piece, promoteFromSquare, promoteToSquare) => {
|
|
1931
|
+
if (pendingPromotion && piece) {
|
|
1932
|
+
const { from, to } = pendingPromotion;
|
|
1933
|
+
onPieceDrop === null || onPieceDrop === void 0 ? void 0 : onPieceDrop(from, to, piece);
|
|
1934
|
+
onPromotionPieceSelect === null || onPromotionPieceSelect === void 0 ? void 0 : onPromotionPieceSelect(piece, from, to);
|
|
1935
|
+
clearSelection();
|
|
1936
|
+
return false;
|
|
1937
|
+
}
|
|
1938
|
+
if (onPromotionPieceSelect) {
|
|
1939
|
+
return onPromotionPieceSelect(piece, promoteFromSquare, promoteToSquare);
|
|
1940
|
+
}
|
|
1941
|
+
return true;
|
|
1942
|
+
}, [clearSelection, onPieceDrop, onPromotionPieceSelect, pendingPromotion]);
|
|
1943
|
+
const handlePieceDragBegin = useCallback((piece, sourceSquare) => {
|
|
1944
|
+
clearSelection();
|
|
1945
|
+
onPieceDragBegin === null || onPieceDragBegin === void 0 ? void 0 : onPieceDragBegin(piece, sourceSquare);
|
|
1946
|
+
}, [clearSelection, onPieceDragBegin]);
|
|
1947
|
+
return {
|
|
1948
|
+
clickSquareStyles,
|
|
1949
|
+
handleSquareClick,
|
|
1950
|
+
handlePromotionPieceSelect,
|
|
1951
|
+
handlePieceDragBegin,
|
|
1952
|
+
showPromotionDialog: pendingPromotion !== null,
|
|
1953
|
+
promotionToSquare: (_a = pendingPromotion === null || pendingPromotion === void 0 ? void 0 : pendingPromotion.to) !== null && _a !== void 0 ? _a : null,
|
|
1954
|
+
};
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
/** Prevent mobile long-press text selection and iOS callout menus on the board. */
|
|
1958
|
+
const nonSelectableBoardStyle = {
|
|
1959
|
+
userSelect: 'none',
|
|
1960
|
+
WebkitUserSelect: 'none',
|
|
1961
|
+
WebkitTouchCallout: 'none',
|
|
1962
|
+
};
|
|
1746
1963
|
const getCheckHighlighting = (checkSquare) => {
|
|
1747
1964
|
const styles = {};
|
|
1748
1965
|
styles[checkSquare] = { backgroundColor: boardSquareHighlightColors.check };
|
|
@@ -1761,12 +1978,41 @@ const getFeedbackHighlighting = (hintSquare, incorrectMoveSquare) => {
|
|
|
1761
1978
|
return styles;
|
|
1762
1979
|
};
|
|
1763
1980
|
const HighlightChessboard = (_a) => {
|
|
1764
|
-
var { checkSquare, hintSquare, incorrectMoveSquare, customSquareStyles: extraSquareStyles } = _a, props = __rest(_a, ["checkSquare", "hintSquare", "incorrectMoveSquare", "customSquareStyles"]);
|
|
1981
|
+
var { checkSquare, hintSquare, incorrectMoveSquare, correctMoveSquare = null, lastMoveUci = null, lastMoveArrowColor, clickToMove, customSquareStyles: extraSquareStyles, customArrows, customBoardStyle, onPieceDrop, position, arePiecesDraggable, autoPromoteToQueen, isDraggablePiece, onPromotionCheck, onSquareClick, onPromotionPieceSelect, onPieceDragBegin, showPromotionDialog: showPromotionDialogProp, promotionToSquare: promotionToSquareProp } = _a, props = __rest(_a, ["checkSquare", "hintSquare", "incorrectMoveSquare", "correctMoveSquare", "lastMoveUci", "lastMoveArrowColor", "clickToMove", "customSquareStyles", "customArrows", "customBoardStyle", "onPieceDrop", "position", "arePiecesDraggable", "autoPromoteToQueen", "isDraggablePiece", "onPromotionCheck", "onSquareClick", "onPromotionPieceSelect", "onPieceDragBegin", "showPromotionDialog", "promotionToSquare"]);
|
|
1765
1982
|
const { customDarkSquareStyle, customLightSquareStyle } = useChessboardTheme();
|
|
1983
|
+
const clickToMoveEnabled = clickToMove !== false && typeof onPieceDrop === 'function';
|
|
1984
|
+
const { clickSquareStyles, handleSquareClick, handlePromotionPieceSelect, handlePieceDragBegin, showPromotionDialog: clickPromotionDialog, promotionToSquare: clickPromotionToSquare, } = useClickToMove({
|
|
1985
|
+
enabled: clickToMoveEnabled,
|
|
1986
|
+
position,
|
|
1987
|
+
arePiecesDraggable,
|
|
1988
|
+
autoPromoteToQueen,
|
|
1989
|
+
isDraggablePiece,
|
|
1990
|
+
onPromotionCheck,
|
|
1991
|
+
onPieceDrop,
|
|
1992
|
+
onSquareClick,
|
|
1993
|
+
onPromotionPieceSelect,
|
|
1994
|
+
onPieceDragBegin,
|
|
1995
|
+
});
|
|
1766
1996
|
const checkStyles = getCheckHighlighting(checkSquare);
|
|
1767
1997
|
const feedbackStyles = getFeedbackHighlighting(hintSquare, incorrectMoveSquare);
|
|
1768
|
-
const customSquareStyles = Object.assign(Object.assign(Object.assign({}, checkStyles), feedbackStyles), extraSquareStyles);
|
|
1769
|
-
|
|
1998
|
+
const customSquareStyles = Object.assign(Object.assign(Object.assign(Object.assign({}, clickSquareStyles), checkStyles), feedbackStyles), extraSquareStyles);
|
|
1999
|
+
const customSquare = useMemo(() => correctMoveSquare
|
|
2000
|
+
? createFeedbackSquareRenderer(correctMoveSquare)
|
|
2001
|
+
: undefined, [correctMoveSquare]);
|
|
2002
|
+
const mergedCustomArrows = useMemo(() => mergeCustomArrowsWithLastMove(customArrows, lastMoveUci, lastMoveArrowColor), [customArrows, lastMoveArrowColor, lastMoveUci]);
|
|
2003
|
+
const promotionControlProps = clickPromotionDialog
|
|
2004
|
+
? {
|
|
2005
|
+
showPromotionDialog: true,
|
|
2006
|
+
promotionToSquare: clickPromotionToSquare,
|
|
2007
|
+
}
|
|
2008
|
+
: showPromotionDialogProp !== undefined ||
|
|
2009
|
+
promotionToSquareProp !== undefined
|
|
2010
|
+
? {
|
|
2011
|
+
showPromotionDialog: showPromotionDialogProp,
|
|
2012
|
+
promotionToSquare: promotionToSquareProp,
|
|
2013
|
+
}
|
|
2014
|
+
: {};
|
|
2015
|
+
return (jsx(Chessboard, Object.assign({ customDarkSquareStyle: customDarkSquareStyle, customLightSquareStyle: customLightSquareStyle, customSquareStyles: customSquareStyles, customSquare: customSquare, customBoardStyle: Object.assign(Object.assign({}, nonSelectableBoardStyle), customBoardStyle), position: position, arePiecesDraggable: arePiecesDraggable, autoPromoteToQueen: autoPromoteToQueen, isDraggablePiece: isDraggablePiece, onPromotionCheck: onPromotionCheck, onPieceDrop: onPieceDrop, onSquareClick: clickToMoveEnabled ? handleSquareClick : onSquareClick, onPromotionPieceSelect: clickToMoveEnabled ? handlePromotionPieceSelect : onPromotionPieceSelect, onPieceDragBegin: clickToMoveEnabled ? handlePieceDragBegin : onPieceDragBegin, customArrows: mergedCustomArrows }, promotionControlProps, props)));
|
|
1770
2016
|
};
|
|
1771
2017
|
|
|
1772
2018
|
const emptyEngineEvaluation = () => ({
|
|
@@ -2694,9 +2940,7 @@ const PlyNavigation = ({ plyIndex, totalPly, canPrev, canNext, onGoFirst, onGoPr
|
|
|
2694
2940
|
/** Draggable analysis board (no surrounding layout chrome). */
|
|
2695
2941
|
const AnalysisChessboardView = ({ model }) => {
|
|
2696
2942
|
var _a;
|
|
2697
|
-
return (jsx(ChessboardDnDProvider, { children: jsx(HighlightChessboard, { checkSquare: (_a = model.checkSquare) !== null && _a !== void 0 ? _a : '', hintSquare: null, incorrectMoveSquare: null, position: model.fen, boardOrientation: model.boardOrientation, boardWidth: model.boardWidth, arePiecesDraggable: true, onPieceDrop: model.onPieceDrop, promotionDialogVariant: "modal",
|
|
2698
|
-
? getLastMoveSquareStyles(model.lastMove.from, model.lastMove.to, model.theme)
|
|
2699
|
-
: {} }) }));
|
|
2943
|
+
return (jsx(ChessboardDnDProvider, { children: jsx(HighlightChessboard, { checkSquare: (_a = model.checkSquare) !== null && _a !== void 0 ? _a : '', hintSquare: null, incorrectMoveSquare: null, position: model.fen, boardOrientation: model.boardOrientation, boardWidth: model.boardWidth, arePiecesDraggable: true, onPieceDrop: model.onPieceDrop, promotionDialogVariant: "modal", lastMoveUci: model.lastMoveUci }) }));
|
|
2700
2944
|
};
|
|
2701
2945
|
|
|
2702
2946
|
class AnalysisPosition {
|
|
@@ -2952,22 +3196,26 @@ class AnalysisPosition {
|
|
|
2952
3196
|
return true;
|
|
2953
3197
|
}
|
|
2954
3198
|
getLastMoveSquares() {
|
|
2955
|
-
const
|
|
2956
|
-
if (
|
|
3199
|
+
const uci = this.getLastMoveUci();
|
|
3200
|
+
if (!uci) {
|
|
2957
3201
|
return null;
|
|
2958
3202
|
}
|
|
2959
|
-
let uci;
|
|
2960
|
-
if (this.variation && this.variationCursor > 0) {
|
|
2961
|
-
uci = this.variation.moves[this.variationCursor - 1];
|
|
2962
|
-
}
|
|
2963
|
-
else {
|
|
2964
|
-
uci = this.solutionMoves[this.mainPly - 1];
|
|
2965
|
-
}
|
|
2966
3203
|
return {
|
|
2967
3204
|
from: uci.slice(0, 2),
|
|
2968
3205
|
to: uci.slice(2, 4),
|
|
2969
3206
|
};
|
|
2970
3207
|
}
|
|
3208
|
+
getLastMoveUci() {
|
|
3209
|
+
var _a;
|
|
3210
|
+
const navPly = this.getNavPly();
|
|
3211
|
+
if (navPly === 0) {
|
|
3212
|
+
return null;
|
|
3213
|
+
}
|
|
3214
|
+
if (this.variation && this.variationCursor > 0) {
|
|
3215
|
+
return this.variation.moves[this.variationCursor - 1];
|
|
3216
|
+
}
|
|
3217
|
+
return (_a = this.solutionMoves[this.mainPly - 1]) !== null && _a !== void 0 ? _a : null;
|
|
3218
|
+
}
|
|
2971
3219
|
fen() {
|
|
2972
3220
|
return this.chess.fen();
|
|
2973
3221
|
}
|
|
@@ -3012,6 +3260,7 @@ const useAnalysisBoardModel = ({ analysisContext, onClose, theme, boardWidth, en
|
|
|
3012
3260
|
engineEvaluation,
|
|
3013
3261
|
engineEnabled,
|
|
3014
3262
|
lastMove: analysisPosition.getLastMoveSquares(),
|
|
3263
|
+
lastMoveUci: analysisPosition.getLastMoveUci(),
|
|
3015
3264
|
checkSquare: analysisPosition.getCheckSquare(),
|
|
3016
3265
|
onSelectPly: (ply) => {
|
|
3017
3266
|
analysisPosition.goToNavPly(ply);
|
|
@@ -3502,6 +3751,37 @@ function useBoardRevision() {
|
|
|
3502
3751
|
return { revision, bumpRevision };
|
|
3503
3752
|
}
|
|
3504
3753
|
|
|
3754
|
+
/** Pause (ms) to show the correct-move check before advancing the line. */
|
|
3755
|
+
const CORRECT_MOVE_FEEDBACK_MS = 450;
|
|
3756
|
+
|
|
3757
|
+
function useCorrectMoveFeedback(delayMs = CORRECT_MOVE_FEEDBACK_MS) {
|
|
3758
|
+
const [correctMoveSquare, setCorrectMoveSquare] = useState(null);
|
|
3759
|
+
const timeoutRef = useRef(null);
|
|
3760
|
+
const clearCorrectMoveFeedback = useCallback(() => {
|
|
3761
|
+
if (timeoutRef.current !== null) {
|
|
3762
|
+
window.clearTimeout(timeoutRef.current);
|
|
3763
|
+
timeoutRef.current = null;
|
|
3764
|
+
}
|
|
3765
|
+
setCorrectMoveSquare(null);
|
|
3766
|
+
}, []);
|
|
3767
|
+
const showCorrectMove = useCallback((targetSquare, onComplete) => {
|
|
3768
|
+
clearCorrectMoveFeedback();
|
|
3769
|
+
setCorrectMoveSquare(targetSquare);
|
|
3770
|
+
timeoutRef.current = window.setTimeout(() => {
|
|
3771
|
+
timeoutRef.current = null;
|
|
3772
|
+
setCorrectMoveSquare(null);
|
|
3773
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
|
|
3774
|
+
}, delayMs);
|
|
3775
|
+
}, [clearCorrectMoveFeedback, delayMs]);
|
|
3776
|
+
useEffect(() => clearCorrectMoveFeedback, [clearCorrectMoveFeedback]);
|
|
3777
|
+
return {
|
|
3778
|
+
correctMoveSquare,
|
|
3779
|
+
showCorrectMove,
|
|
3780
|
+
clearCorrectMoveFeedback,
|
|
3781
|
+
isShowingCorrectMove: correctMoveSquare !== null,
|
|
3782
|
+
};
|
|
3783
|
+
}
|
|
3784
|
+
|
|
3505
3785
|
/** Minimum eval loss (pawns) from the wrong move before showing a refutation. */
|
|
3506
3786
|
const REFUTATION_EVAL_GAP_PAWNS = 0.5;
|
|
3507
3787
|
const REFUTATION_EVAL_GAP_CP = REFUTATION_EVAL_GAP_PAWNS * 100;
|
|
@@ -3595,6 +3875,7 @@ function getMissDisplay(sequence, expectedUci, refutationUci, answerArrowColor)
|
|
|
3595
3875
|
return {
|
|
3596
3876
|
fen: null,
|
|
3597
3877
|
arrows: [],
|
|
3878
|
+
lastMoveUci: null,
|
|
3598
3879
|
animating: false,
|
|
3599
3880
|
};
|
|
3600
3881
|
}
|
|
@@ -3605,6 +3886,7 @@ function getMissDisplay(sequence, expectedUci, refutationUci, answerArrowColor)
|
|
|
3605
3886
|
return {
|
|
3606
3887
|
fen: fenAfterWrong !== null && fenAfterWrong !== void 0 ? fenAfterWrong : setupFen,
|
|
3607
3888
|
arrows: [],
|
|
3889
|
+
lastMoveUci: attemptedUci,
|
|
3608
3890
|
animating: false,
|
|
3609
3891
|
};
|
|
3610
3892
|
case 'refutation': {
|
|
@@ -3614,6 +3896,7 @@ function getMissDisplay(sequence, expectedUci, refutationUci, answerArrowColor)
|
|
|
3614
3896
|
return {
|
|
3615
3897
|
fen: (_a = fenAfterRefutation !== null && fenAfterRefutation !== void 0 ? fenAfterRefutation : fenAfterWrong) !== null && _a !== void 0 ? _a : setupFen,
|
|
3616
3898
|
arrows: [],
|
|
3899
|
+
lastMoveUci: refutationUci,
|
|
3617
3900
|
animating: Boolean(fenAfterRefutation),
|
|
3618
3901
|
};
|
|
3619
3902
|
}
|
|
@@ -3621,18 +3904,21 @@ function getMissDisplay(sequence, expectedUci, refutationUci, answerArrowColor)
|
|
|
3621
3904
|
return {
|
|
3622
3905
|
fen: setupFen,
|
|
3623
3906
|
arrows: [],
|
|
3907
|
+
lastMoveUci: null,
|
|
3624
3908
|
animating: false,
|
|
3625
3909
|
};
|
|
3626
3910
|
case 'answer':
|
|
3627
3911
|
return {
|
|
3628
3912
|
fen: setupFen,
|
|
3629
3913
|
arrows: expectedMoveArrow(expectedUci, answerArrowColor),
|
|
3914
|
+
lastMoveUci: null,
|
|
3630
3915
|
animating: false,
|
|
3631
3916
|
};
|
|
3632
3917
|
default:
|
|
3633
3918
|
return {
|
|
3634
3919
|
fen: setupFen,
|
|
3635
3920
|
arrows: [],
|
|
3921
|
+
lastMoveUci: null,
|
|
3636
3922
|
animating: false,
|
|
3637
3923
|
};
|
|
3638
3924
|
}
|
|
@@ -3805,8 +4091,9 @@ function useMissBoard({ feedback, expectedUci, positionFen, answerArrowColor, au
|
|
|
3805
4091
|
customArrows,
|
|
3806
4092
|
boardPosition,
|
|
3807
4093
|
boardAnimating: missSequence.display.animating,
|
|
4094
|
+
lastMoveUci: missSequence.display.lastMoveUci,
|
|
3808
4095
|
wrapDropHandler,
|
|
3809
4096
|
};
|
|
3810
4097
|
}
|
|
3811
4098
|
|
|
3812
|
-
export { AnalysisBoard, AnalysisBoardCore, AnalysisBoardCoreView, AnalysisBoardLayout, AnalysisChessboardView, AnalysisEngineProvider, AnalysisErrorBoundary, AnalysisPosition, BOARD_THEMES, BOARD_THEME_IDS, ChessboardDnDProvider, ChessboardThemeContext, DEFAULT_ANALYSIS_LAYOUT, DEFAULT_BOARD_THEME, DEFAULT_STOCKFISH_SCRIPT_URL, DefaultAnalysisContainer, DefaultAnalysisSidebar, DefaultPlyNavigation, EngineEvaluationPanel, HighlightChessboard, MISS_MOVE_ANIMATION_MS, MISS_REFUTATION_MAX_WAIT_MS, MISS_REFUTATION_PAUSE_MS, MISS_WRONG_PAUSE_MS, PlyNavigation, REFUTATION_EVAL_GAP_CP, REFUTATION_EVAL_GAP_PAWNS, StockfishBrowserEngine, ThemeProvider, analysisBoardHighlightColors, analysisSidebarColors, applyUciMove, boardSquareHighlightColors, boardThemeFromLegacyUiTheme, createExpectedMoveDropHandler, createSidebarRowBandCounters, defaultRenderPlyNavigation, emptyEngineEvaluation, evaluateExpectedMoveDrop, fenAfterUci, formatEvaluation, formatPvPreview, getAnalysisModalStyles, getBoardThemeStyles, getCheckSquareFromChess, getLastMoveSquareStyles, getMissDisplay, getSidebarRowBackground, getStylesForTheme, isAnalyzableFen, isBoardThemeId, isEditableKeyboardTarget, lineEvalCpForGap, matchesExpectedUci, navButtonStyle, navRowStyle, normalizeEvalForWhite, normalizePvMoves, normalizeSubscriberOptions, parseUciInfoLine, parseUciMove, plyLabelStyle, palette as plyNavigationPalette, refutationEngineOptions, refutationEvalGapCp, refutationFromEvaluation, resolveStockfishScriptUrl, resolveStockfishWasmUrl, resolveStockfishWorkerUrl, scrubberInputStyle, splitWorkerLines, uciFromDrop, uciPvToSan, useAnalysisBoardModel, useAnalysisEngine, useAnalysisEngineContext, useBoardRevision, useChessboardTheme, useMissBoard, useMissRefutation, useMissSequence, usePositionKeyboardNav, useTheme };
|
|
4099
|
+
export { AnalysisBoard, AnalysisBoardCore, AnalysisBoardCoreView, AnalysisBoardLayout, AnalysisChessboardView, AnalysisEngineProvider, AnalysisErrorBoundary, AnalysisPosition, BOARD_THEMES, BOARD_THEME_IDS, CORRECT_MOVE_FEEDBACK_MS, ChessboardDnDProvider, ChessboardThemeContext, CorrectMoveCheckBadge, DEFAULT_ANALYSIS_LAYOUT, DEFAULT_BOARD_THEME, DEFAULT_LAST_MOVE_ARROW_COLOR, DEFAULT_STOCKFISH_SCRIPT_URL, DefaultAnalysisContainer, DefaultAnalysisSidebar, DefaultPlyNavigation, EngineEvaluationPanel, HighlightChessboard, MISS_MOVE_ANIMATION_MS, MISS_REFUTATION_MAX_WAIT_MS, MISS_REFUTATION_PAUSE_MS, MISS_WRONG_PAUSE_MS, PlyNavigation, REFUTATION_EVAL_GAP_CP, REFUTATION_EVAL_GAP_PAWNS, StockfishBrowserEngine, ThemeProvider, analysisBoardHighlightColors, analysisSidebarColors, applyUciMove, boardSquareHighlightColors, boardThemeFromLegacyUiTheme, createExpectedMoveDropHandler, createSidebarRowBandCounters, defaultRenderPlyNavigation, emptyEngineEvaluation, evaluateExpectedMoveDrop, fenAfterUci, formatEvaluation, formatPvPreview, getAnalysisModalStyles, getBoardThemeStyles, getCheckSquareFromChess, getLastMoveSquareStyles, getMissDisplay, getSidebarRowBackground, getStylesForTheme, isAnalyzableFen, isBoardThemeId, isEditableKeyboardTarget, lastMoveArrowFromUci, lastMoveUciAtPly, lineEvalCpForGap, matchesExpectedUci, mergeCustomArrowsWithLastMove, navButtonStyle, navRowStyle, normalizeEvalForWhite, normalizePvMoves, normalizeSubscriberOptions, parseUciInfoLine, parseUciMove, plyLabelStyle, palette as plyNavigationPalette, refutationEngineOptions, refutationEvalGapCp, refutationFromEvaluation, resolveStockfishScriptUrl, resolveStockfishWasmUrl, resolveStockfishWorkerUrl, scrubberInputStyle, splitWorkerLines, uciFromDrop, uciPvToSan, uciToArrow, useAnalysisBoardModel, useAnalysisEngine, useAnalysisEngineContext, useBoardRevision, useChessboardTheme, useCorrectMoveFeedback, useMissBoard, useMissRefutation, useMissSequence, usePositionKeyboardNav, useTheme };
|
package/dist/index.js
CHANGED
|
@@ -1743,8 +1743,225 @@ const boardSquareHighlightColors = {
|
|
|
1743
1743
|
hint: 'rgba(119, 177, 212, 0.75)',
|
|
1744
1744
|
/** Muted red — softer than the in-check highlight. */
|
|
1745
1745
|
incorrect: 'rgba(140, 38, 38, 0.82)',
|
|
1746
|
+
selected: 'rgba(255, 255, 0, 0.45)',
|
|
1747
|
+
moveTarget: 'radial-gradient(circle, rgba(0, 0, 0, 0.18) 22%, transparent 22%)',
|
|
1748
|
+
captureTarget: 'radial-gradient(circle, rgba(0, 0, 0, 0.18) 72%, transparent 72%)',
|
|
1746
1749
|
};
|
|
1747
1750
|
|
|
1751
|
+
const badgeStyle = {
|
|
1752
|
+
position: 'absolute',
|
|
1753
|
+
right: '6%',
|
|
1754
|
+
bottom: '6%',
|
|
1755
|
+
width: '26%',
|
|
1756
|
+
height: '26%',
|
|
1757
|
+
minWidth: 14,
|
|
1758
|
+
minHeight: 14,
|
|
1759
|
+
maxWidth: 26,
|
|
1760
|
+
maxHeight: 26,
|
|
1761
|
+
borderRadius: '50%',
|
|
1762
|
+
backgroundColor: '#2e7d32',
|
|
1763
|
+
display: 'flex',
|
|
1764
|
+
alignItems: 'center',
|
|
1765
|
+
justifyContent: 'center',
|
|
1766
|
+
boxShadow: '0 1px 3px rgba(0, 0, 0, 0.35)',
|
|
1767
|
+
pointerEvents: 'none',
|
|
1768
|
+
};
|
|
1769
|
+
/** Green circle with a white check, anchored to the bottom-right of a square
|
|
1770
|
+
* square (over the piece). */
|
|
1771
|
+
const CorrectMoveCheckBadge = () => (jsxRuntime.jsx("span", { "aria-hidden": true, style: badgeStyle, children: jsxRuntime.jsx("svg", { viewBox: "0 0 12 12", width: "62%", height: "62%", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsxRuntime.jsx("path", { d: "M2.5 6.2 5 8.7 9.5 3.8", stroke: "#fff", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
|
|
1772
|
+
|
|
1773
|
+
const overlayStyle$1 = {
|
|
1774
|
+
position: 'absolute',
|
|
1775
|
+
inset: 0,
|
|
1776
|
+
pointerEvents: 'none',
|
|
1777
|
+
zIndex: 20,
|
|
1778
|
+
overflow: 'visible',
|
|
1779
|
+
};
|
|
1780
|
+
function createFeedbackSquareRenderer(correctMoveSquare) {
|
|
1781
|
+
return function FeedbackSquare({ children, style, square, ref }) {
|
|
1782
|
+
return (jsxRuntime.jsxs("div", { ref: ref, style: Object.assign(Object.assign({}, style), { position: 'relative', overflow: 'visible' }), children: [children, square === correctMoveSquare ? (jsxRuntime.jsx("div", { style: overlayStyle$1, children: jsxRuntime.jsx(CorrectMoveCheckBadge, {}) })) : null] }));
|
|
1783
|
+
};
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
/** Subtle green arrow visible on light and dark boards (Lichess-style). */
|
|
1787
|
+
const DEFAULT_LAST_MOVE_ARROW_COLOR = 'rgba(155, 199, 0, 0.85)';
|
|
1788
|
+
const uciToArrow = (uci, color = DEFAULT_LAST_MOVE_ARROW_COLOR) => [uci.slice(0, 2), uci.slice(2, 4), color];
|
|
1789
|
+
const lastMoveArrowFromUci = (uci, color = DEFAULT_LAST_MOVE_ARROW_COLOR) => {
|
|
1790
|
+
if (!uci || uci.length < 4) {
|
|
1791
|
+
return [];
|
|
1792
|
+
}
|
|
1793
|
+
return [uciToArrow(uci, color)];
|
|
1794
|
+
};
|
|
1795
|
+
/** UCI of the move that produced the position at {@link plyIndex}. */
|
|
1796
|
+
const lastMoveUciAtPly = (movesUci, plyIndex) => {
|
|
1797
|
+
var _a;
|
|
1798
|
+
if (plyIndex <= 0) {
|
|
1799
|
+
return null;
|
|
1800
|
+
}
|
|
1801
|
+
return (_a = movesUci[plyIndex - 1]) !== null && _a !== void 0 ? _a : null;
|
|
1802
|
+
};
|
|
1803
|
+
const mergeCustomArrowsWithLastMove = (customArrows, lastMoveUci, lastMoveArrowColor) => {
|
|
1804
|
+
const lastMove = lastMoveArrowFromUci(lastMoveUci, lastMoveArrowColor);
|
|
1805
|
+
if (!lastMove.length) {
|
|
1806
|
+
return customArrows !== null && customArrows !== void 0 ? customArrows : [];
|
|
1807
|
+
}
|
|
1808
|
+
return [...lastMove, ...(customArrows !== null && customArrows !== void 0 ? customArrows : [])];
|
|
1809
|
+
};
|
|
1810
|
+
|
|
1811
|
+
function defaultPromotionCheck(sourceSquare, targetSquare, piece) {
|
|
1812
|
+
return (((piece === 'wP' && sourceSquare[1] === '7' && targetSquare[1] === '8') ||
|
|
1813
|
+
(piece === 'bP' && sourceSquare[1] === '2' && targetSquare[1] === '1')) &&
|
|
1814
|
+
Math.abs(sourceSquare.charCodeAt(0) - targetSquare.charCodeAt(0)) <= 1);
|
|
1815
|
+
}
|
|
1816
|
+
function pieceAtSquare(fen, square) {
|
|
1817
|
+
const boardPiece = new chess_js.Chess(fen).get(square);
|
|
1818
|
+
if (!boardPiece) {
|
|
1819
|
+
return null;
|
|
1820
|
+
}
|
|
1821
|
+
const color = boardPiece.color === 'w' ? 'w' : 'b';
|
|
1822
|
+
const type = boardPiece.type.toUpperCase();
|
|
1823
|
+
return `${color}${type}`;
|
|
1824
|
+
}
|
|
1825
|
+
function getMoveOptionStyles(fen, fromSquare) {
|
|
1826
|
+
const chess = new chess_js.Chess(fen);
|
|
1827
|
+
const moves = chess.moves({ square: fromSquare, verbose: true });
|
|
1828
|
+
if (!moves.length) {
|
|
1829
|
+
return {
|
|
1830
|
+
[fromSquare]: { backgroundColor: boardSquareHighlightColors.selected },
|
|
1831
|
+
};
|
|
1832
|
+
}
|
|
1833
|
+
const styles = {
|
|
1834
|
+
[fromSquare]: { backgroundColor: boardSquareHighlightColors.selected },
|
|
1835
|
+
};
|
|
1836
|
+
for (const move of moves) {
|
|
1837
|
+
styles[move.to] = {
|
|
1838
|
+
background: chess.get(move.to)
|
|
1839
|
+
? boardSquareHighlightColors.captureTarget
|
|
1840
|
+
: boardSquareHighlightColors.moveTarget,
|
|
1841
|
+
borderRadius: '50%',
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
return styles;
|
|
1845
|
+
}
|
|
1846
|
+
function useClickToMove({ enabled, position, arePiecesDraggable = true, autoPromoteToQueen = false, isDraggablePiece, onPromotionCheck = defaultPromotionCheck, onPieceDrop, onSquareClick, onPromotionPieceSelect, onPieceDragBegin, }) {
|
|
1847
|
+
var _a;
|
|
1848
|
+
const [moveFrom, setMoveFrom] = react.useState(null);
|
|
1849
|
+
const [pendingPromotion, setPendingPromotion] = react.useState(null);
|
|
1850
|
+
const fen = typeof position === 'string' ? position : undefined;
|
|
1851
|
+
const clearSelection = react.useCallback(() => {
|
|
1852
|
+
setMoveFrom(null);
|
|
1853
|
+
setPendingPromotion(null);
|
|
1854
|
+
}, []);
|
|
1855
|
+
react.useEffect(() => {
|
|
1856
|
+
clearSelection();
|
|
1857
|
+
}, [fen, clearSelection]);
|
|
1858
|
+
const clickSquareStyles = react.useMemo(() => {
|
|
1859
|
+
if (!enabled || !moveFrom || !fen) {
|
|
1860
|
+
return {};
|
|
1861
|
+
}
|
|
1862
|
+
return getMoveOptionStyles(fen, moveFrom);
|
|
1863
|
+
}, [enabled, fen, moveFrom]);
|
|
1864
|
+
const canSelectPiece = react.useCallback((square, piece) => {
|
|
1865
|
+
if (!piece || !arePiecesDraggable || !onPieceDrop) {
|
|
1866
|
+
return false;
|
|
1867
|
+
}
|
|
1868
|
+
if (isDraggablePiece) {
|
|
1869
|
+
return isDraggablePiece({ piece, sourceSquare: square });
|
|
1870
|
+
}
|
|
1871
|
+
return true;
|
|
1872
|
+
}, [arePiecesDraggable, isDraggablePiece, onPieceDrop]);
|
|
1873
|
+
const tryCompleteMove = react.useCallback((from, to, piece) => {
|
|
1874
|
+
if (!onPieceDrop) {
|
|
1875
|
+
return false;
|
|
1876
|
+
}
|
|
1877
|
+
if (onPromotionCheck(from, to, piece)) {
|
|
1878
|
+
if (autoPromoteToQueen) {
|
|
1879
|
+
const promotedPiece = piece[0] === 'w' ? 'wQ' : 'bQ';
|
|
1880
|
+
const accepted = onPieceDrop(from, to, promotedPiece);
|
|
1881
|
+
clearSelection();
|
|
1882
|
+
return accepted;
|
|
1883
|
+
}
|
|
1884
|
+
setPendingPromotion({ from, to, piece });
|
|
1885
|
+
setMoveFrom(null);
|
|
1886
|
+
return true;
|
|
1887
|
+
}
|
|
1888
|
+
const accepted = onPieceDrop(from, to, piece);
|
|
1889
|
+
clearSelection();
|
|
1890
|
+
return accepted;
|
|
1891
|
+
}, [autoPromoteToQueen, clearSelection, onPieceDrop, onPromotionCheck]);
|
|
1892
|
+
const handleSquareClick = react.useCallback((square, piece) => {
|
|
1893
|
+
onSquareClick === null || onSquareClick === void 0 ? void 0 : onSquareClick(square, piece);
|
|
1894
|
+
if (!enabled || !onPieceDrop || !arePiecesDraggable || !fen) {
|
|
1895
|
+
return;
|
|
1896
|
+
}
|
|
1897
|
+
if (!moveFrom) {
|
|
1898
|
+
if (canSelectPiece(square, piece)) {
|
|
1899
|
+
setMoveFrom(square);
|
|
1900
|
+
}
|
|
1901
|
+
return;
|
|
1902
|
+
}
|
|
1903
|
+
if (square === moveFrom) {
|
|
1904
|
+
clearSelection();
|
|
1905
|
+
return;
|
|
1906
|
+
}
|
|
1907
|
+
const sourcePiece = pieceAtSquare(fen, moveFrom);
|
|
1908
|
+
if (!sourcePiece) {
|
|
1909
|
+
clearSelection();
|
|
1910
|
+
return;
|
|
1911
|
+
}
|
|
1912
|
+
const accepted = tryCompleteMove(moveFrom, square, sourcePiece);
|
|
1913
|
+
if (accepted) {
|
|
1914
|
+
return;
|
|
1915
|
+
}
|
|
1916
|
+
if (canSelectPiece(square, piece)) {
|
|
1917
|
+
setMoveFrom(square);
|
|
1918
|
+
return;
|
|
1919
|
+
}
|
|
1920
|
+
clearSelection();
|
|
1921
|
+
}, [
|
|
1922
|
+
arePiecesDraggable,
|
|
1923
|
+
canSelectPiece,
|
|
1924
|
+
clearSelection,
|
|
1925
|
+
enabled,
|
|
1926
|
+
fen,
|
|
1927
|
+
moveFrom,
|
|
1928
|
+
onPieceDrop,
|
|
1929
|
+
onSquareClick,
|
|
1930
|
+
tryCompleteMove,
|
|
1931
|
+
]);
|
|
1932
|
+
const handlePromotionPieceSelect = react.useCallback((piece, promoteFromSquare, promoteToSquare) => {
|
|
1933
|
+
if (pendingPromotion && piece) {
|
|
1934
|
+
const { from, to } = pendingPromotion;
|
|
1935
|
+
onPieceDrop === null || onPieceDrop === void 0 ? void 0 : onPieceDrop(from, to, piece);
|
|
1936
|
+
onPromotionPieceSelect === null || onPromotionPieceSelect === void 0 ? void 0 : onPromotionPieceSelect(piece, from, to);
|
|
1937
|
+
clearSelection();
|
|
1938
|
+
return false;
|
|
1939
|
+
}
|
|
1940
|
+
if (onPromotionPieceSelect) {
|
|
1941
|
+
return onPromotionPieceSelect(piece, promoteFromSquare, promoteToSquare);
|
|
1942
|
+
}
|
|
1943
|
+
return true;
|
|
1944
|
+
}, [clearSelection, onPieceDrop, onPromotionPieceSelect, pendingPromotion]);
|
|
1945
|
+
const handlePieceDragBegin = react.useCallback((piece, sourceSquare) => {
|
|
1946
|
+
clearSelection();
|
|
1947
|
+
onPieceDragBegin === null || onPieceDragBegin === void 0 ? void 0 : onPieceDragBegin(piece, sourceSquare);
|
|
1948
|
+
}, [clearSelection, onPieceDragBegin]);
|
|
1949
|
+
return {
|
|
1950
|
+
clickSquareStyles,
|
|
1951
|
+
handleSquareClick,
|
|
1952
|
+
handlePromotionPieceSelect,
|
|
1953
|
+
handlePieceDragBegin,
|
|
1954
|
+
showPromotionDialog: pendingPromotion !== null,
|
|
1955
|
+
promotionToSquare: (_a = pendingPromotion === null || pendingPromotion === void 0 ? void 0 : pendingPromotion.to) !== null && _a !== void 0 ? _a : null,
|
|
1956
|
+
};
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
/** Prevent mobile long-press text selection and iOS callout menus on the board. */
|
|
1960
|
+
const nonSelectableBoardStyle = {
|
|
1961
|
+
userSelect: 'none',
|
|
1962
|
+
WebkitUserSelect: 'none',
|
|
1963
|
+
WebkitTouchCallout: 'none',
|
|
1964
|
+
};
|
|
1748
1965
|
const getCheckHighlighting = (checkSquare) => {
|
|
1749
1966
|
const styles = {};
|
|
1750
1967
|
styles[checkSquare] = { backgroundColor: boardSquareHighlightColors.check };
|
|
@@ -1763,12 +1980,41 @@ const getFeedbackHighlighting = (hintSquare, incorrectMoveSquare) => {
|
|
|
1763
1980
|
return styles;
|
|
1764
1981
|
};
|
|
1765
1982
|
const HighlightChessboard = (_a) => {
|
|
1766
|
-
var { checkSquare, hintSquare, incorrectMoveSquare, customSquareStyles: extraSquareStyles } = _a, props = __rest(_a, ["checkSquare", "hintSquare", "incorrectMoveSquare", "customSquareStyles"]);
|
|
1983
|
+
var { checkSquare, hintSquare, incorrectMoveSquare, correctMoveSquare = null, lastMoveUci = null, lastMoveArrowColor, clickToMove, customSquareStyles: extraSquareStyles, customArrows, customBoardStyle, onPieceDrop, position, arePiecesDraggable, autoPromoteToQueen, isDraggablePiece, onPromotionCheck, onSquareClick, onPromotionPieceSelect, onPieceDragBegin, showPromotionDialog: showPromotionDialogProp, promotionToSquare: promotionToSquareProp } = _a, props = __rest(_a, ["checkSquare", "hintSquare", "incorrectMoveSquare", "correctMoveSquare", "lastMoveUci", "lastMoveArrowColor", "clickToMove", "customSquareStyles", "customArrows", "customBoardStyle", "onPieceDrop", "position", "arePiecesDraggable", "autoPromoteToQueen", "isDraggablePiece", "onPromotionCheck", "onSquareClick", "onPromotionPieceSelect", "onPieceDragBegin", "showPromotionDialog", "promotionToSquare"]);
|
|
1767
1984
|
const { customDarkSquareStyle, customLightSquareStyle } = useChessboardTheme();
|
|
1985
|
+
const clickToMoveEnabled = clickToMove !== false && typeof onPieceDrop === 'function';
|
|
1986
|
+
const { clickSquareStyles, handleSquareClick, handlePromotionPieceSelect, handlePieceDragBegin, showPromotionDialog: clickPromotionDialog, promotionToSquare: clickPromotionToSquare, } = useClickToMove({
|
|
1987
|
+
enabled: clickToMoveEnabled,
|
|
1988
|
+
position,
|
|
1989
|
+
arePiecesDraggable,
|
|
1990
|
+
autoPromoteToQueen,
|
|
1991
|
+
isDraggablePiece,
|
|
1992
|
+
onPromotionCheck,
|
|
1993
|
+
onPieceDrop,
|
|
1994
|
+
onSquareClick,
|
|
1995
|
+
onPromotionPieceSelect,
|
|
1996
|
+
onPieceDragBegin,
|
|
1997
|
+
});
|
|
1768
1998
|
const checkStyles = getCheckHighlighting(checkSquare);
|
|
1769
1999
|
const feedbackStyles = getFeedbackHighlighting(hintSquare, incorrectMoveSquare);
|
|
1770
|
-
const customSquareStyles = Object.assign(Object.assign(Object.assign({}, checkStyles), feedbackStyles), extraSquareStyles);
|
|
1771
|
-
|
|
2000
|
+
const customSquareStyles = Object.assign(Object.assign(Object.assign(Object.assign({}, clickSquareStyles), checkStyles), feedbackStyles), extraSquareStyles);
|
|
2001
|
+
const customSquare = react.useMemo(() => correctMoveSquare
|
|
2002
|
+
? createFeedbackSquareRenderer(correctMoveSquare)
|
|
2003
|
+
: undefined, [correctMoveSquare]);
|
|
2004
|
+
const mergedCustomArrows = react.useMemo(() => mergeCustomArrowsWithLastMove(customArrows, lastMoveUci, lastMoveArrowColor), [customArrows, lastMoveArrowColor, lastMoveUci]);
|
|
2005
|
+
const promotionControlProps = clickPromotionDialog
|
|
2006
|
+
? {
|
|
2007
|
+
showPromotionDialog: true,
|
|
2008
|
+
promotionToSquare: clickPromotionToSquare,
|
|
2009
|
+
}
|
|
2010
|
+
: showPromotionDialogProp !== undefined ||
|
|
2011
|
+
promotionToSquareProp !== undefined
|
|
2012
|
+
? {
|
|
2013
|
+
showPromotionDialog: showPromotionDialogProp,
|
|
2014
|
+
promotionToSquare: promotionToSquareProp,
|
|
2015
|
+
}
|
|
2016
|
+
: {};
|
|
2017
|
+
return (jsxRuntime.jsx(reactChessboard.Chessboard, Object.assign({ customDarkSquareStyle: customDarkSquareStyle, customLightSquareStyle: customLightSquareStyle, customSquareStyles: customSquareStyles, customSquare: customSquare, customBoardStyle: Object.assign(Object.assign({}, nonSelectableBoardStyle), customBoardStyle), position: position, arePiecesDraggable: arePiecesDraggable, autoPromoteToQueen: autoPromoteToQueen, isDraggablePiece: isDraggablePiece, onPromotionCheck: onPromotionCheck, onPieceDrop: onPieceDrop, onSquareClick: clickToMoveEnabled ? handleSquareClick : onSquareClick, onPromotionPieceSelect: clickToMoveEnabled ? handlePromotionPieceSelect : onPromotionPieceSelect, onPieceDragBegin: clickToMoveEnabled ? handlePieceDragBegin : onPieceDragBegin, customArrows: mergedCustomArrows }, promotionControlProps, props)));
|
|
1772
2018
|
};
|
|
1773
2019
|
|
|
1774
2020
|
const emptyEngineEvaluation = () => ({
|
|
@@ -2696,9 +2942,7 @@ const PlyNavigation = ({ plyIndex, totalPly, canPrev, canNext, onGoFirst, onGoPr
|
|
|
2696
2942
|
/** Draggable analysis board (no surrounding layout chrome). */
|
|
2697
2943
|
const AnalysisChessboardView = ({ model }) => {
|
|
2698
2944
|
var _a;
|
|
2699
|
-
return (jsxRuntime.jsx(ChessboardDnDProvider, { children: jsxRuntime.jsx(HighlightChessboard, { checkSquare: (_a = model.checkSquare) !== null && _a !== void 0 ? _a : '', hintSquare: null, incorrectMoveSquare: null, position: model.fen, boardOrientation: model.boardOrientation, boardWidth: model.boardWidth, arePiecesDraggable: true, onPieceDrop: model.onPieceDrop, promotionDialogVariant: "modal",
|
|
2700
|
-
? getLastMoveSquareStyles(model.lastMove.from, model.lastMove.to, model.theme)
|
|
2701
|
-
: {} }) }));
|
|
2945
|
+
return (jsxRuntime.jsx(ChessboardDnDProvider, { children: jsxRuntime.jsx(HighlightChessboard, { checkSquare: (_a = model.checkSquare) !== null && _a !== void 0 ? _a : '', hintSquare: null, incorrectMoveSquare: null, position: model.fen, boardOrientation: model.boardOrientation, boardWidth: model.boardWidth, arePiecesDraggable: true, onPieceDrop: model.onPieceDrop, promotionDialogVariant: "modal", lastMoveUci: model.lastMoveUci }) }));
|
|
2702
2946
|
};
|
|
2703
2947
|
|
|
2704
2948
|
class AnalysisPosition {
|
|
@@ -2954,22 +3198,26 @@ class AnalysisPosition {
|
|
|
2954
3198
|
return true;
|
|
2955
3199
|
}
|
|
2956
3200
|
getLastMoveSquares() {
|
|
2957
|
-
const
|
|
2958
|
-
if (
|
|
3201
|
+
const uci = this.getLastMoveUci();
|
|
3202
|
+
if (!uci) {
|
|
2959
3203
|
return null;
|
|
2960
3204
|
}
|
|
2961
|
-
let uci;
|
|
2962
|
-
if (this.variation && this.variationCursor > 0) {
|
|
2963
|
-
uci = this.variation.moves[this.variationCursor - 1];
|
|
2964
|
-
}
|
|
2965
|
-
else {
|
|
2966
|
-
uci = this.solutionMoves[this.mainPly - 1];
|
|
2967
|
-
}
|
|
2968
3205
|
return {
|
|
2969
3206
|
from: uci.slice(0, 2),
|
|
2970
3207
|
to: uci.slice(2, 4),
|
|
2971
3208
|
};
|
|
2972
3209
|
}
|
|
3210
|
+
getLastMoveUci() {
|
|
3211
|
+
var _a;
|
|
3212
|
+
const navPly = this.getNavPly();
|
|
3213
|
+
if (navPly === 0) {
|
|
3214
|
+
return null;
|
|
3215
|
+
}
|
|
3216
|
+
if (this.variation && this.variationCursor > 0) {
|
|
3217
|
+
return this.variation.moves[this.variationCursor - 1];
|
|
3218
|
+
}
|
|
3219
|
+
return (_a = this.solutionMoves[this.mainPly - 1]) !== null && _a !== void 0 ? _a : null;
|
|
3220
|
+
}
|
|
2973
3221
|
fen() {
|
|
2974
3222
|
return this.chess.fen();
|
|
2975
3223
|
}
|
|
@@ -3014,6 +3262,7 @@ const useAnalysisBoardModel = ({ analysisContext, onClose, theme, boardWidth, en
|
|
|
3014
3262
|
engineEvaluation,
|
|
3015
3263
|
engineEnabled,
|
|
3016
3264
|
lastMove: analysisPosition.getLastMoveSquares(),
|
|
3265
|
+
lastMoveUci: analysisPosition.getLastMoveUci(),
|
|
3017
3266
|
checkSquare: analysisPosition.getCheckSquare(),
|
|
3018
3267
|
onSelectPly: (ply) => {
|
|
3019
3268
|
analysisPosition.goToNavPly(ply);
|
|
@@ -3504,6 +3753,37 @@ function useBoardRevision() {
|
|
|
3504
3753
|
return { revision, bumpRevision };
|
|
3505
3754
|
}
|
|
3506
3755
|
|
|
3756
|
+
/** Pause (ms) to show the correct-move check before advancing the line. */
|
|
3757
|
+
const CORRECT_MOVE_FEEDBACK_MS = 450;
|
|
3758
|
+
|
|
3759
|
+
function useCorrectMoveFeedback(delayMs = CORRECT_MOVE_FEEDBACK_MS) {
|
|
3760
|
+
const [correctMoveSquare, setCorrectMoveSquare] = react.useState(null);
|
|
3761
|
+
const timeoutRef = react.useRef(null);
|
|
3762
|
+
const clearCorrectMoveFeedback = react.useCallback(() => {
|
|
3763
|
+
if (timeoutRef.current !== null) {
|
|
3764
|
+
window.clearTimeout(timeoutRef.current);
|
|
3765
|
+
timeoutRef.current = null;
|
|
3766
|
+
}
|
|
3767
|
+
setCorrectMoveSquare(null);
|
|
3768
|
+
}, []);
|
|
3769
|
+
const showCorrectMove = react.useCallback((targetSquare, onComplete) => {
|
|
3770
|
+
clearCorrectMoveFeedback();
|
|
3771
|
+
setCorrectMoveSquare(targetSquare);
|
|
3772
|
+
timeoutRef.current = window.setTimeout(() => {
|
|
3773
|
+
timeoutRef.current = null;
|
|
3774
|
+
setCorrectMoveSquare(null);
|
|
3775
|
+
onComplete === null || onComplete === void 0 ? void 0 : onComplete();
|
|
3776
|
+
}, delayMs);
|
|
3777
|
+
}, [clearCorrectMoveFeedback, delayMs]);
|
|
3778
|
+
react.useEffect(() => clearCorrectMoveFeedback, [clearCorrectMoveFeedback]);
|
|
3779
|
+
return {
|
|
3780
|
+
correctMoveSquare,
|
|
3781
|
+
showCorrectMove,
|
|
3782
|
+
clearCorrectMoveFeedback,
|
|
3783
|
+
isShowingCorrectMove: correctMoveSquare !== null,
|
|
3784
|
+
};
|
|
3785
|
+
}
|
|
3786
|
+
|
|
3507
3787
|
/** Minimum eval loss (pawns) from the wrong move before showing a refutation. */
|
|
3508
3788
|
const REFUTATION_EVAL_GAP_PAWNS = 0.5;
|
|
3509
3789
|
const REFUTATION_EVAL_GAP_CP = REFUTATION_EVAL_GAP_PAWNS * 100;
|
|
@@ -3597,6 +3877,7 @@ function getMissDisplay(sequence, expectedUci, refutationUci, answerArrowColor)
|
|
|
3597
3877
|
return {
|
|
3598
3878
|
fen: null,
|
|
3599
3879
|
arrows: [],
|
|
3880
|
+
lastMoveUci: null,
|
|
3600
3881
|
animating: false,
|
|
3601
3882
|
};
|
|
3602
3883
|
}
|
|
@@ -3607,6 +3888,7 @@ function getMissDisplay(sequence, expectedUci, refutationUci, answerArrowColor)
|
|
|
3607
3888
|
return {
|
|
3608
3889
|
fen: fenAfterWrong !== null && fenAfterWrong !== void 0 ? fenAfterWrong : setupFen,
|
|
3609
3890
|
arrows: [],
|
|
3891
|
+
lastMoveUci: attemptedUci,
|
|
3610
3892
|
animating: false,
|
|
3611
3893
|
};
|
|
3612
3894
|
case 'refutation': {
|
|
@@ -3616,6 +3898,7 @@ function getMissDisplay(sequence, expectedUci, refutationUci, answerArrowColor)
|
|
|
3616
3898
|
return {
|
|
3617
3899
|
fen: (_a = fenAfterRefutation !== null && fenAfterRefutation !== void 0 ? fenAfterRefutation : fenAfterWrong) !== null && _a !== void 0 ? _a : setupFen,
|
|
3618
3900
|
arrows: [],
|
|
3901
|
+
lastMoveUci: refutationUci,
|
|
3619
3902
|
animating: Boolean(fenAfterRefutation),
|
|
3620
3903
|
};
|
|
3621
3904
|
}
|
|
@@ -3623,18 +3906,21 @@ function getMissDisplay(sequence, expectedUci, refutationUci, answerArrowColor)
|
|
|
3623
3906
|
return {
|
|
3624
3907
|
fen: setupFen,
|
|
3625
3908
|
arrows: [],
|
|
3909
|
+
lastMoveUci: null,
|
|
3626
3910
|
animating: false,
|
|
3627
3911
|
};
|
|
3628
3912
|
case 'answer':
|
|
3629
3913
|
return {
|
|
3630
3914
|
fen: setupFen,
|
|
3631
3915
|
arrows: expectedMoveArrow(expectedUci, answerArrowColor),
|
|
3916
|
+
lastMoveUci: null,
|
|
3632
3917
|
animating: false,
|
|
3633
3918
|
};
|
|
3634
3919
|
default:
|
|
3635
3920
|
return {
|
|
3636
3921
|
fen: setupFen,
|
|
3637
3922
|
arrows: [],
|
|
3923
|
+
lastMoveUci: null,
|
|
3638
3924
|
animating: false,
|
|
3639
3925
|
};
|
|
3640
3926
|
}
|
|
@@ -3807,6 +4093,7 @@ function useMissBoard({ feedback, expectedUci, positionFen, answerArrowColor, au
|
|
|
3807
4093
|
customArrows,
|
|
3808
4094
|
boardPosition,
|
|
3809
4095
|
boardAnimating: missSequence.display.animating,
|
|
4096
|
+
lastMoveUci: missSequence.display.lastMoveUci,
|
|
3810
4097
|
wrapDropHandler,
|
|
3811
4098
|
};
|
|
3812
4099
|
}
|
|
@@ -3821,10 +4108,13 @@ exports.AnalysisErrorBoundary = AnalysisErrorBoundary;
|
|
|
3821
4108
|
exports.AnalysisPosition = AnalysisPosition;
|
|
3822
4109
|
exports.BOARD_THEMES = BOARD_THEMES;
|
|
3823
4110
|
exports.BOARD_THEME_IDS = BOARD_THEME_IDS;
|
|
4111
|
+
exports.CORRECT_MOVE_FEEDBACK_MS = CORRECT_MOVE_FEEDBACK_MS;
|
|
3824
4112
|
exports.ChessboardDnDProvider = ChessboardDnDProvider;
|
|
3825
4113
|
exports.ChessboardThemeContext = ChessboardThemeContext;
|
|
4114
|
+
exports.CorrectMoveCheckBadge = CorrectMoveCheckBadge;
|
|
3826
4115
|
exports.DEFAULT_ANALYSIS_LAYOUT = DEFAULT_ANALYSIS_LAYOUT;
|
|
3827
4116
|
exports.DEFAULT_BOARD_THEME = DEFAULT_BOARD_THEME;
|
|
4117
|
+
exports.DEFAULT_LAST_MOVE_ARROW_COLOR = DEFAULT_LAST_MOVE_ARROW_COLOR;
|
|
3828
4118
|
exports.DEFAULT_STOCKFISH_SCRIPT_URL = DEFAULT_STOCKFISH_SCRIPT_URL;
|
|
3829
4119
|
exports.DefaultAnalysisContainer = DefaultAnalysisContainer;
|
|
3830
4120
|
exports.DefaultAnalysisSidebar = DefaultAnalysisSidebar;
|
|
@@ -3863,8 +4153,11 @@ exports.getStylesForTheme = getStylesForTheme;
|
|
|
3863
4153
|
exports.isAnalyzableFen = isAnalyzableFen;
|
|
3864
4154
|
exports.isBoardThemeId = isBoardThemeId;
|
|
3865
4155
|
exports.isEditableKeyboardTarget = isEditableKeyboardTarget;
|
|
4156
|
+
exports.lastMoveArrowFromUci = lastMoveArrowFromUci;
|
|
4157
|
+
exports.lastMoveUciAtPly = lastMoveUciAtPly;
|
|
3866
4158
|
exports.lineEvalCpForGap = lineEvalCpForGap;
|
|
3867
4159
|
exports.matchesExpectedUci = matchesExpectedUci;
|
|
4160
|
+
exports.mergeCustomArrowsWithLastMove = mergeCustomArrowsWithLastMove;
|
|
3868
4161
|
exports.navButtonStyle = navButtonStyle;
|
|
3869
4162
|
exports.navRowStyle = navRowStyle;
|
|
3870
4163
|
exports.normalizeEvalForWhite = normalizeEvalForWhite;
|
|
@@ -3884,11 +4177,13 @@ exports.scrubberInputStyle = scrubberInputStyle;
|
|
|
3884
4177
|
exports.splitWorkerLines = splitWorkerLines;
|
|
3885
4178
|
exports.uciFromDrop = uciFromDrop;
|
|
3886
4179
|
exports.uciPvToSan = uciPvToSan;
|
|
4180
|
+
exports.uciToArrow = uciToArrow;
|
|
3887
4181
|
exports.useAnalysisBoardModel = useAnalysisBoardModel;
|
|
3888
4182
|
exports.useAnalysisEngine = useAnalysisEngine;
|
|
3889
4183
|
exports.useAnalysisEngineContext = useAnalysisEngineContext;
|
|
3890
4184
|
exports.useBoardRevision = useBoardRevision;
|
|
3891
4185
|
exports.useChessboardTheme = useChessboardTheme;
|
|
4186
|
+
exports.useCorrectMoveFeedback = useCorrectMoveFeedback;
|
|
3892
4187
|
exports.useMissBoard = useMissBoard;
|
|
3893
4188
|
exports.useMissRefutation = useMissRefutation;
|
|
3894
4189
|
exports.useMissSequence = useMissSequence;
|