@react-chess-tools/react-chess-puzzle 0.5.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.MD +1 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.mjs +6 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/hooks/useChessPuzzle.ts +7 -0
- package/src/hooks/useChessPuzzleContext.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @react-chess-tools/react-chess-puzzle
|
|
2
2
|
|
|
3
|
+
## 0.5.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f18ce4b: fix: improve error messages for context hook usage
|
|
8
|
+
- Updated dependencies [f18ce4b]
|
|
9
|
+
- @react-chess-tools/react-chess-game@0.4.2
|
|
10
|
+
|
|
3
11
|
## 0.5.1
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
package/README.MD
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -28,6 +28,7 @@ interface PuzzleBoardProps extends React__default.ComponentProps<typeof ChessGam
|
|
|
28
28
|
type ChessPuzzleContextType = {
|
|
29
29
|
status: Status;
|
|
30
30
|
changePuzzle: (puzzle: Puzzle) => void;
|
|
31
|
+
resetPuzzle: () => void;
|
|
31
32
|
puzzle: Puzzle;
|
|
32
33
|
hint: Hint;
|
|
33
34
|
nextMove?: string | null;
|
package/dist/index.mjs
CHANGED
|
@@ -212,10 +212,14 @@ var useChessPuzzle = (puzzle, onSolve, onFail) => {
|
|
|
212
212
|
const onHint = useCallback(() => {
|
|
213
213
|
dispatch({ type: "TOGGLE_HINT" });
|
|
214
214
|
}, []);
|
|
215
|
+
const resetPuzzle = useCallback(() => {
|
|
216
|
+
changePuzzle(puzzle);
|
|
217
|
+
}, [changePuzzle, puzzle]);
|
|
215
218
|
const puzzleContext = useMemo(
|
|
216
219
|
() => ({
|
|
217
220
|
status: state.status,
|
|
218
221
|
changePuzzle,
|
|
222
|
+
resetPuzzle,
|
|
219
223
|
puzzle,
|
|
220
224
|
hint: state.hint,
|
|
221
225
|
onHint,
|
|
@@ -228,6 +232,7 @@ var useChessPuzzle = (puzzle, onSolve, onFail) => {
|
|
|
228
232
|
[
|
|
229
233
|
state.status,
|
|
230
234
|
changePuzzle,
|
|
235
|
+
resetPuzzle,
|
|
231
236
|
puzzle,
|
|
232
237
|
state.hint,
|
|
233
238
|
onHint,
|
|
@@ -280,7 +285,7 @@ var useChessPuzzleContext = () => {
|
|
|
280
285
|
const context = React2.useContext(ChessPuzzleContext);
|
|
281
286
|
if (!context) {
|
|
282
287
|
throw new Error(
|
|
283
|
-
|
|
288
|
+
`useChessPuzzleContext must be used within a ChessPuzzle component. Make sure your component is wrapped with <ChessPuzzle.Root> or ensure the ChessPuzzle component is properly rendered in the component tree.`
|
|
284
289
|
);
|
|
285
290
|
}
|
|
286
291
|
return context;
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/ChessPuzzle/parts/Root.tsx","../src/utils/index.ts","../src/hooks/useChessPuzzle.ts","../src/hooks/reducer.ts","../src/hooks/useChessPuzzleContext.ts","../src/components/ChessPuzzle/parts/PuzzleBoard.tsx","../src/components/ChessPuzzle/parts/Reset.tsx","../src/components/ChessPuzzle/parts/Hint.tsx","../src/components/ChessPuzzle/index.ts"],"sourcesContent":["import React from \"react\";\nimport { Puzzle, getOrientation } from \"../../../utils\";\nimport {\n ChessPuzzleContextType,\n useChessPuzzle,\n} from \"../../../hooks/useChessPuzzle\";\nimport { ChessGame } from \"@react-chess-tools/react-chess-game\";\nimport { ChessPuzzleContext } from \"../../../hooks/useChessPuzzleContext\";\n\nexport interface RootProps {\n puzzle: Puzzle;\n onSolve?: (puzzleContext: ChessPuzzleContextType) => void;\n onFail?: (puzzleContext: ChessPuzzleContextType) => void;\n}\n\nconst PuzzleRoot: React.FC<React.PropsWithChildren<RootProps>> = ({\n puzzle,\n onSolve,\n onFail,\n children,\n}) => {\n const context = useChessPuzzle(puzzle, onSolve, onFail);\n\n return (\n <ChessPuzzleContext.Provider value={context}>\n {children}\n </ChessPuzzleContext.Provider>\n );\n};\n\nexport const Root: React.FC<React.PropsWithChildren<RootProps>> = ({\n puzzle,\n onSolve,\n onFail,\n children,\n}) => {\n return (\n <ChessGame.Root fen={puzzle.fen} orientation={getOrientation(puzzle)}>\n <PuzzleRoot puzzle={puzzle} onSolve={onSolve} onFail={onFail}>\n {children}\n </PuzzleRoot>\n </ChessGame.Root>\n );\n};\n","import { type Color, Chess, Move } from \"chess.js\";\nimport React, { CSSProperties, ReactElement, ReactNode } from \"react\";\nimport _ from \"lodash\";\n\nexport type Status = \"not-started\" | \"in-progress\" | \"solved\" | \"failed\";\n\nexport type Hint = \"none\" | \"piece\" | \"move\";\n\nexport type Puzzle = {\n fen: string;\n moves: string[];\n // if the first move of the puzzle has to be made by the cpu, as in chess.com puzzles\n makeFirstMove?: boolean;\n};\n\nconst FAIL_COLOR = \"rgba(201, 52, 48, 0.5)\";\nconst SUCCESS_COLOR = \"rgba(172, 206, 89, 0.5)\";\nconst HINT_COLOR = \"rgba(27, 172, 166, 0.5)\";\n\nexport const getOrientation = (puzzle: Puzzle): Color => {\n const fen = puzzle.fen;\n const game = new Chess(fen);\n if (puzzle.makeFirstMove) {\n game.move(puzzle.moves[0]);\n }\n return game.turn();\n};\n\ninterface ClickableElement extends ReactElement {\n props: {\n onClick?: () => void;\n };\n}\n\nexport const isClickableElement = (\n element: ReactNode,\n): element is ClickableElement => React.isValidElement(element);\n\nexport const getCustomSquareStyles = (\n status: Status,\n hint: Hint,\n isPlayerTurn: boolean,\n game: Chess,\n nextMove?: Move | null,\n) => {\n const customSquareStyles: Record<string, CSSProperties> = {};\n\n const lastMove = _.last(game.history({ verbose: true }));\n\n if (status === \"failed\" && lastMove) {\n customSquareStyles[lastMove.from] = {\n backgroundColor: FAIL_COLOR,\n };\n customSquareStyles[lastMove.to] = {\n backgroundColor: FAIL_COLOR,\n };\n }\n\n if (\n lastMove &&\n (status === \"solved\" || (status !== \"failed\" && !isPlayerTurn))\n ) {\n customSquareStyles[lastMove.from] = {\n backgroundColor: SUCCESS_COLOR,\n };\n customSquareStyles[lastMove.to] = {\n backgroundColor: SUCCESS_COLOR,\n };\n }\n\n if (hint === \"piece\") {\n if (nextMove) {\n customSquareStyles[nextMove.from] = {\n backgroundColor: HINT_COLOR,\n };\n }\n }\n\n if (hint === \"move\") {\n if (nextMove) {\n customSquareStyles[nextMove.from] = {\n backgroundColor: HINT_COLOR,\n };\n customSquareStyles[nextMove.to] = {\n backgroundColor: HINT_COLOR,\n };\n }\n }\n\n return customSquareStyles;\n};\n\nexport const stringToMove = (game: Chess, move: string | null | undefined) => {\n const copy = new Chess(game.fen());\n if (move === null || move === undefined) {\n return null;\n }\n try {\n return copy.move(move);\n } catch (e) {\n return null;\n }\n};\n","import { useEffect, useReducer, useCallback, useMemo } from \"react\";\nimport { initializePuzzle, reducer } from \"./reducer\";\nimport { getOrientation, type Puzzle, type Hint, type Status } from \"../utils\";\nimport { useChessGameContext } from \"@react-chess-tools/react-chess-game\";\n\nexport type ChessPuzzleContextType = {\n status: Status;\n changePuzzle: (puzzle: Puzzle) => void;\n puzzle: Puzzle;\n hint: Hint;\n nextMove?: string | null;\n isPlayerTurn: boolean;\n onHint: () => void;\n puzzleState: Status;\n movesPlayed: number;\n totalMoves: number;\n};\n\nexport const useChessPuzzle = (\n puzzle: Puzzle,\n onSolve?: (puzzleContext: ChessPuzzleContextType) => void,\n onFail?: (puzzleContext: ChessPuzzleContextType) => void,\n): ChessPuzzleContextType => {\n const gameContext = useChessGameContext();\n\n const [state, dispatch] = useReducer(reducer, { puzzle }, initializePuzzle);\n\n const {\n game,\n methods: { makeMove, setPosition },\n } = gameContext;\n\n const changePuzzle = useCallback(\n (puzzle: Puzzle) => {\n setPosition(puzzle.fen, getOrientation(puzzle));\n dispatch({ type: \"INITIALIZE\", payload: { puzzle } });\n },\n [setPosition],\n );\n\n useEffect(() => {\n changePuzzle(puzzle);\n }, [JSON.stringify(puzzle), changePuzzle]);\n\n useEffect(() => {\n if (gameContext && game.fen() === puzzle.fen && state.needCpuMove) {\n setTimeout(\n () =>\n dispatch({\n type: \"CPU_MOVE\",\n }),\n 0,\n );\n }\n }, [gameContext, state.needCpuMove]);\n\n useEffect(() => {\n if (state.cpuMove) {\n makeMove(state.cpuMove);\n }\n }, [state.cpuMove]);\n\n if (!gameContext) {\n throw new Error(\"useChessPuzzle must be used within a ChessGameContext\");\n }\n\n const onHint = useCallback(() => {\n dispatch({ type: \"TOGGLE_HINT\" });\n }, []);\n\n const puzzleContext: ChessPuzzleContextType = useMemo(\n () => ({\n status: state.status,\n changePuzzle,\n puzzle,\n hint: state.hint,\n onHint,\n nextMove: state.nextMove,\n isPlayerTurn: state.isPlayerTurn,\n puzzleState: state.status,\n movesPlayed: state.currentMoveIndex,\n totalMoves: puzzle.moves.length,\n }),\n [\n state.status,\n changePuzzle,\n puzzle,\n state.hint,\n onHint,\n state.nextMove,\n state.isPlayerTurn,\n state.currentMoveIndex,\n ],\n );\n\n useEffect(() => {\n if (game?.history()?.length <= 0 + (puzzle.makeFirstMove ? 1 : 0)) {\n return;\n }\n if (game.history().length % 2 === (puzzle.makeFirstMove ? 0 : 1)) {\n dispatch({\n type: \"PLAYER_MOVE\",\n payload: {\n move: gameContext?.game?.history({ verbose: true })?.pop() ?? null,\n puzzleContext,\n game: game,\n },\n });\n\n dispatch({\n type: \"CPU_MOVE\",\n });\n }\n }, [game?.history()?.length]);\n\n useEffect(() => {\n if (state.status === \"solved\" && !state.onSolveInvoked && onSolve) {\n onSolve(puzzleContext);\n dispatch({ type: \"MARK_SOLVE_INVOKED\" });\n }\n }, [state.status, state.onSolveInvoked]);\n\n useEffect(() => {\n if (state.status === \"failed\" && !state.onFailInvoked && onFail) {\n onFail(puzzleContext);\n dispatch({ type: \"MARK_FAIL_INVOKED\" });\n }\n }, [state.status, state.onFailInvoked]);\n\n return puzzleContext;\n};\n","import { Chess, Move } from \"chess.js\";\nimport { type Puzzle, type Hint, type Status } from \"../utils\";\nimport { ChessPuzzleContextType } from \"./useChessPuzzle\";\n\nexport type State = {\n puzzle: Puzzle;\n currentMoveIndex: number;\n status: Status;\n cpuMove?: string | null;\n nextMove?: string | null;\n hint: Hint;\n needCpuMove: boolean;\n isPlayerTurn: boolean;\n onSolveInvoked: boolean;\n onFailInvoked: boolean;\n};\n\nexport type Action =\n | {\n type: \"INITIALIZE\";\n payload: {\n puzzle: Puzzle;\n };\n }\n | {\n type: \"RESET\";\n }\n | { type: \"TOGGLE_HINT\" }\n | {\n type: \"CPU_MOVE\";\n }\n | {\n type: \"PLAYER_MOVE\";\n payload: {\n move?: Move | null;\n puzzleContext: ChessPuzzleContextType;\n game: Chess;\n };\n }\n | { type: \"MARK_SOLVE_INVOKED\" }\n | { type: \"MARK_FAIL_INVOKED\" };\n\nexport const initializePuzzle = ({ puzzle }: { puzzle: Puzzle }): State => {\n return {\n puzzle,\n currentMoveIndex: 0,\n status: \"not-started\",\n nextMove: puzzle.moves[0],\n hint: \"none\",\n cpuMove: null,\n needCpuMove: !!puzzle.makeFirstMove,\n isPlayerTurn: !puzzle.makeFirstMove,\n onSolveInvoked: false,\n onFailInvoked: false,\n };\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"INITIALIZE\":\n return {\n ...state,\n ...initializePuzzle(action.payload),\n };\n case \"RESET\":\n return {\n ...state,\n ...initializePuzzle({\n puzzle: state.puzzle,\n }),\n };\n case \"TOGGLE_HINT\":\n if (state.hint === \"none\") {\n return { ...state, hint: \"piece\" };\n }\n return { ...state, hint: \"move\" };\n case \"CPU_MOVE\":\n if (state.isPlayerTurn) {\n return state;\n }\n if ([\"solved\", \"failed\"].includes(state.status)) {\n return state;\n }\n\n return {\n ...state,\n currentMoveIndex: state.currentMoveIndex + 1,\n cpuMove: state.puzzle.moves[state.currentMoveIndex],\n nextMove:\n state.currentMoveIndex < state.puzzle.moves.length - 1\n ? state.puzzle.moves[state.currentMoveIndex + 1]\n : null,\n needCpuMove: false,\n isPlayerTurn: true,\n status: \"in-progress\",\n };\n\n case \"PLAYER_MOVE\": {\n const { move } = action.payload;\n\n const isMoveRight = [move?.san, move?.lan].includes(\n state?.nextMove || \"\",\n );\n const isPuzzleSolved =\n state.currentMoveIndex === state.puzzle.moves.length - 1;\n\n if (!isMoveRight) {\n return {\n ...state,\n status: \"failed\",\n nextMove: null,\n hint: \"none\",\n isPlayerTurn: false,\n onFailInvoked: false,\n };\n }\n\n if (isPuzzleSolved) {\n return {\n ...state,\n status: \"solved\",\n nextMove: null,\n hint: \"none\",\n isPlayerTurn: false,\n onSolveInvoked: false,\n };\n }\n\n return {\n ...state,\n hint: \"none\",\n currentMoveIndex: state.currentMoveIndex + 1,\n nextMove: state.puzzle.moves[state.currentMoveIndex + 1],\n status: \"in-progress\",\n needCpuMove: true,\n isPlayerTurn: false,\n };\n }\n\n case \"MARK_SOLVE_INVOKED\":\n return {\n ...state,\n onSolveInvoked: true,\n };\n\n case \"MARK_FAIL_INVOKED\":\n return {\n ...state,\n onFailInvoked: true,\n };\n\n default:\n return state;\n }\n};\n","import React from \"react\";\nimport { useChessPuzzle } from \"./useChessPuzzle\";\n\nexport const ChessPuzzleContext = React.createContext<ReturnType<\n typeof useChessPuzzle\n> | null>(null);\n\nexport const useChessPuzzleContext = () => {\n const context = React.useContext(ChessPuzzleContext);\n if (!context) {\n throw new Error(\n \"useChessGameContext must be used within a ChessGameProvider\",\n );\n }\n return context;\n};\n","import React from \"react\";\nimport {\n ChessGame,\n useChessGameContext,\n} from \"@react-chess-tools/react-chess-game\";\nimport { getCustomSquareStyles, stringToMove } from \"../../../utils\";\nimport { useChessPuzzleContext } from \"../../..\";\n\nexport interface PuzzleBoardProps\n extends React.ComponentProps<typeof ChessGame.Board> {}\nexport const PuzzleBoard: React.FC<PuzzleBoardProps> = ({ ...rest }) => {\n const puzzleContext = useChessPuzzleContext();\n const gameContext = useChessGameContext();\n\n if (!puzzleContext) {\n throw new Error(\"PuzzleContext not found\");\n }\n if (!gameContext) {\n throw new Error(\"ChessGameContext not found\");\n }\n\n const { game } = gameContext;\n const { status, hint, isPlayerTurn, nextMove } = puzzleContext;\n\n return (\n <ChessGame.Board\n customSquareStyles={getCustomSquareStyles(\n status,\n hint,\n isPlayerTurn,\n game,\n stringToMove(game, nextMove),\n )}\n {...rest}\n />\n );\n};\n","import React from \"react\";\nimport { isClickableElement, type Puzzle, type Status } from \"../../../utils\";\nimport { useChessPuzzleContext, type ChessPuzzleContextType } from \"../../..\";\n\nexport interface ResetProps {\n asChild?: boolean;\n puzzle?: Puzzle;\n onReset?: (puzzleContext: ChessPuzzleContextType) => void;\n showOn?: Status[];\n}\n\nconst defaultShowOn: Status[] = [\"failed\", \"solved\"];\n\nexport const Reset: React.FC<React.PropsWithChildren<ResetProps>> = ({\n children,\n asChild,\n puzzle,\n onReset,\n showOn = defaultShowOn,\n}) => {\n const puzzleContext = useChessPuzzleContext();\n if (!puzzleContext) {\n throw new Error(\"PuzzleContext not found\");\n }\n const { changePuzzle, status } = puzzleContext;\n const handleClick = () => {\n changePuzzle(puzzle || puzzleContext.puzzle);\n onReset?.(puzzleContext);\n };\n\n if (!showOn.includes(status)) {\n return null;\n }\n\n if (asChild) {\n const child = React.Children.only(children);\n if (isClickableElement(child)) {\n return React.cloneElement(child, {\n onClick: handleClick,\n });\n } else {\n throw new Error(\"Change child must be a clickable element\");\n }\n }\n\n return (\n <button type=\"button\" onClick={handleClick}>\n {children}\n </button>\n );\n};\n","import React from \"react\";\nimport { Status, isClickableElement } from \"../../../utils\";\nimport { useChessPuzzleContext } from \"../../..\";\n\nexport interface HintProps {\n asChild?: boolean;\n showOn?: Status[];\n}\n\nconst defaultShowOn: Status[] = [\"not-started\", \"in-progress\"];\n\nexport const Hint: React.FC<React.PropsWithChildren<HintProps>> = ({\n children,\n asChild,\n showOn = defaultShowOn,\n}) => {\n const puzzleContext = useChessPuzzleContext();\n if (!puzzleContext) {\n throw new Error(\"PuzzleContext not found\");\n }\n const { onHint, status } = puzzleContext;\n const handleClick = () => {\n onHint();\n };\n\n if (!showOn.includes(status)) {\n return null;\n }\n\n if (asChild) {\n const child = React.Children.only(children);\n if (isClickableElement(child)) {\n return React.cloneElement(child, {\n onClick: handleClick,\n });\n } else {\n throw new Error(\"Change child must be a clickable element\");\n }\n }\n\n return (\n <button type=\"button\" onClick={handleClick}>\n {children}\n </button>\n );\n};\n","import { Root } from \"./parts/Root\";\nimport { PuzzleBoard } from \"./parts/PuzzleBoard\";\nimport { Reset } from \"./parts/Reset\";\nimport { Hint } from \"./parts/Hint\";\n\nexport const ChessPuzzle = {\n Root,\n Board: PuzzleBoard,\n Reset,\n Hint,\n};\n"],"mappings":"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","names":["React","puzzle","_a","React","React","React","ChessGame","useChessGameContext","useChessGameContext","React","ChessGame","React","React","React","defaultShowOn","React"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/ChessPuzzle/parts/Root.tsx","../src/utils/index.ts","../src/hooks/useChessPuzzle.ts","../src/hooks/reducer.ts","../src/hooks/useChessPuzzleContext.ts","../src/components/ChessPuzzle/parts/PuzzleBoard.tsx","../src/components/ChessPuzzle/parts/Reset.tsx","../src/components/ChessPuzzle/parts/Hint.tsx","../src/components/ChessPuzzle/index.ts"],"sourcesContent":["import React from \"react\";\nimport { Puzzle, getOrientation } from \"../../../utils\";\nimport {\n ChessPuzzleContextType,\n useChessPuzzle,\n} from \"../../../hooks/useChessPuzzle\";\nimport { ChessGame } from \"@react-chess-tools/react-chess-game\";\nimport { ChessPuzzleContext } from \"../../../hooks/useChessPuzzleContext\";\n\nexport interface RootProps {\n puzzle: Puzzle;\n onSolve?: (puzzleContext: ChessPuzzleContextType) => void;\n onFail?: (puzzleContext: ChessPuzzleContextType) => void;\n}\n\nconst PuzzleRoot: React.FC<React.PropsWithChildren<RootProps>> = ({\n puzzle,\n onSolve,\n onFail,\n children,\n}) => {\n const context = useChessPuzzle(puzzle, onSolve, onFail);\n\n return (\n <ChessPuzzleContext.Provider value={context}>\n {children}\n </ChessPuzzleContext.Provider>\n );\n};\n\nexport const Root: React.FC<React.PropsWithChildren<RootProps>> = ({\n puzzle,\n onSolve,\n onFail,\n children,\n}) => {\n return (\n <ChessGame.Root fen={puzzle.fen} orientation={getOrientation(puzzle)}>\n <PuzzleRoot puzzle={puzzle} onSolve={onSolve} onFail={onFail}>\n {children}\n </PuzzleRoot>\n </ChessGame.Root>\n );\n};\n","import { type Color, Chess, Move } from \"chess.js\";\nimport React, { CSSProperties, ReactElement, ReactNode } from \"react\";\nimport _ from \"lodash\";\n\nexport type Status = \"not-started\" | \"in-progress\" | \"solved\" | \"failed\";\n\nexport type Hint = \"none\" | \"piece\" | \"move\";\n\nexport type Puzzle = {\n fen: string;\n moves: string[];\n // if the first move of the puzzle has to be made by the cpu, as in chess.com puzzles\n makeFirstMove?: boolean;\n};\n\nconst FAIL_COLOR = \"rgba(201, 52, 48, 0.5)\";\nconst SUCCESS_COLOR = \"rgba(172, 206, 89, 0.5)\";\nconst HINT_COLOR = \"rgba(27, 172, 166, 0.5)\";\n\nexport const getOrientation = (puzzle: Puzzle): Color => {\n const fen = puzzle.fen;\n const game = new Chess(fen);\n if (puzzle.makeFirstMove) {\n game.move(puzzle.moves[0]);\n }\n return game.turn();\n};\n\ninterface ClickableElement extends ReactElement {\n props: {\n onClick?: () => void;\n };\n}\n\nexport const isClickableElement = (\n element: ReactNode,\n): element is ClickableElement => React.isValidElement(element);\n\nexport const getCustomSquareStyles = (\n status: Status,\n hint: Hint,\n isPlayerTurn: boolean,\n game: Chess,\n nextMove?: Move | null,\n) => {\n const customSquareStyles: Record<string, CSSProperties> = {};\n\n const lastMove = _.last(game.history({ verbose: true }));\n\n if (status === \"failed\" && lastMove) {\n customSquareStyles[lastMove.from] = {\n backgroundColor: FAIL_COLOR,\n };\n customSquareStyles[lastMove.to] = {\n backgroundColor: FAIL_COLOR,\n };\n }\n\n if (\n lastMove &&\n (status === \"solved\" || (status !== \"failed\" && !isPlayerTurn))\n ) {\n customSquareStyles[lastMove.from] = {\n backgroundColor: SUCCESS_COLOR,\n };\n customSquareStyles[lastMove.to] = {\n backgroundColor: SUCCESS_COLOR,\n };\n }\n\n if (hint === \"piece\") {\n if (nextMove) {\n customSquareStyles[nextMove.from] = {\n backgroundColor: HINT_COLOR,\n };\n }\n }\n\n if (hint === \"move\") {\n if (nextMove) {\n customSquareStyles[nextMove.from] = {\n backgroundColor: HINT_COLOR,\n };\n customSquareStyles[nextMove.to] = {\n backgroundColor: HINT_COLOR,\n };\n }\n }\n\n return customSquareStyles;\n};\n\nexport const stringToMove = (game: Chess, move: string | null | undefined) => {\n const copy = new Chess(game.fen());\n if (move === null || move === undefined) {\n return null;\n }\n try {\n return copy.move(move);\n } catch (e) {\n return null;\n }\n};\n","import { useEffect, useReducer, useCallback, useMemo } from \"react\";\nimport { initializePuzzle, reducer } from \"./reducer\";\nimport { getOrientation, type Puzzle, type Hint, type Status } from \"../utils\";\nimport { useChessGameContext } from \"@react-chess-tools/react-chess-game\";\n\nexport type ChessPuzzleContextType = {\n status: Status;\n changePuzzle: (puzzle: Puzzle) => void;\n resetPuzzle: () => void;\n puzzle: Puzzle;\n hint: Hint;\n nextMove?: string | null;\n isPlayerTurn: boolean;\n onHint: () => void;\n puzzleState: Status;\n movesPlayed: number;\n totalMoves: number;\n};\n\nexport const useChessPuzzle = (\n puzzle: Puzzle,\n onSolve?: (puzzleContext: ChessPuzzleContextType) => void,\n onFail?: (puzzleContext: ChessPuzzleContextType) => void,\n): ChessPuzzleContextType => {\n const gameContext = useChessGameContext();\n\n const [state, dispatch] = useReducer(reducer, { puzzle }, initializePuzzle);\n\n const {\n game,\n methods: { makeMove, setPosition },\n } = gameContext;\n\n const changePuzzle = useCallback(\n (puzzle: Puzzle) => {\n setPosition(puzzle.fen, getOrientation(puzzle));\n dispatch({ type: \"INITIALIZE\", payload: { puzzle } });\n },\n [setPosition],\n );\n\n useEffect(() => {\n changePuzzle(puzzle);\n }, [JSON.stringify(puzzle), changePuzzle]);\n\n useEffect(() => {\n if (gameContext && game.fen() === puzzle.fen && state.needCpuMove) {\n setTimeout(\n () =>\n dispatch({\n type: \"CPU_MOVE\",\n }),\n 0,\n );\n }\n }, [gameContext, state.needCpuMove]);\n\n useEffect(() => {\n if (state.cpuMove) {\n makeMove(state.cpuMove);\n }\n }, [state.cpuMove]);\n\n if (!gameContext) {\n throw new Error(\"useChessPuzzle must be used within a ChessGameContext\");\n }\n\n const onHint = useCallback(() => {\n dispatch({ type: \"TOGGLE_HINT\" });\n }, []);\n\n const resetPuzzle = useCallback(() => {\n changePuzzle(puzzle);\n }, [changePuzzle, puzzle]);\n\n const puzzleContext: ChessPuzzleContextType = useMemo(\n () => ({\n status: state.status,\n changePuzzle,\n resetPuzzle,\n puzzle,\n hint: state.hint,\n onHint,\n nextMove: state.nextMove,\n isPlayerTurn: state.isPlayerTurn,\n puzzleState: state.status,\n movesPlayed: state.currentMoveIndex,\n totalMoves: puzzle.moves.length,\n }),\n [\n state.status,\n changePuzzle,\n resetPuzzle,\n puzzle,\n state.hint,\n onHint,\n state.nextMove,\n state.isPlayerTurn,\n state.currentMoveIndex,\n ],\n );\n\n useEffect(() => {\n if (game?.history()?.length <= 0 + (puzzle.makeFirstMove ? 1 : 0)) {\n return;\n }\n if (game.history().length % 2 === (puzzle.makeFirstMove ? 0 : 1)) {\n dispatch({\n type: \"PLAYER_MOVE\",\n payload: {\n move: gameContext?.game?.history({ verbose: true })?.pop() ?? null,\n puzzleContext,\n game: game,\n },\n });\n\n dispatch({\n type: \"CPU_MOVE\",\n });\n }\n }, [game?.history()?.length]);\n\n useEffect(() => {\n if (state.status === \"solved\" && !state.onSolveInvoked && onSolve) {\n onSolve(puzzleContext);\n dispatch({ type: \"MARK_SOLVE_INVOKED\" });\n }\n }, [state.status, state.onSolveInvoked]);\n\n useEffect(() => {\n if (state.status === \"failed\" && !state.onFailInvoked && onFail) {\n onFail(puzzleContext);\n dispatch({ type: \"MARK_FAIL_INVOKED\" });\n }\n }, [state.status, state.onFailInvoked]);\n\n return puzzleContext;\n};\n","import { Chess, Move } from \"chess.js\";\nimport { type Puzzle, type Hint, type Status } from \"../utils\";\nimport { ChessPuzzleContextType } from \"./useChessPuzzle\";\n\nexport type State = {\n puzzle: Puzzle;\n currentMoveIndex: number;\n status: Status;\n cpuMove?: string | null;\n nextMove?: string | null;\n hint: Hint;\n needCpuMove: boolean;\n isPlayerTurn: boolean;\n onSolveInvoked: boolean;\n onFailInvoked: boolean;\n};\n\nexport type Action =\n | {\n type: \"INITIALIZE\";\n payload: {\n puzzle: Puzzle;\n };\n }\n | {\n type: \"RESET\";\n }\n | { type: \"TOGGLE_HINT\" }\n | {\n type: \"CPU_MOVE\";\n }\n | {\n type: \"PLAYER_MOVE\";\n payload: {\n move?: Move | null;\n puzzleContext: ChessPuzzleContextType;\n game: Chess;\n };\n }\n | { type: \"MARK_SOLVE_INVOKED\" }\n | { type: \"MARK_FAIL_INVOKED\" };\n\nexport const initializePuzzle = ({ puzzle }: { puzzle: Puzzle }): State => {\n return {\n puzzle,\n currentMoveIndex: 0,\n status: \"not-started\",\n nextMove: puzzle.moves[0],\n hint: \"none\",\n cpuMove: null,\n needCpuMove: !!puzzle.makeFirstMove,\n isPlayerTurn: !puzzle.makeFirstMove,\n onSolveInvoked: false,\n onFailInvoked: false,\n };\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"INITIALIZE\":\n return {\n ...state,\n ...initializePuzzle(action.payload),\n };\n case \"RESET\":\n return {\n ...state,\n ...initializePuzzle({\n puzzle: state.puzzle,\n }),\n };\n case \"TOGGLE_HINT\":\n if (state.hint === \"none\") {\n return { ...state, hint: \"piece\" };\n }\n return { ...state, hint: \"move\" };\n case \"CPU_MOVE\":\n if (state.isPlayerTurn) {\n return state;\n }\n if ([\"solved\", \"failed\"].includes(state.status)) {\n return state;\n }\n\n return {\n ...state,\n currentMoveIndex: state.currentMoveIndex + 1,\n cpuMove: state.puzzle.moves[state.currentMoveIndex],\n nextMove:\n state.currentMoveIndex < state.puzzle.moves.length - 1\n ? state.puzzle.moves[state.currentMoveIndex + 1]\n : null,\n needCpuMove: false,\n isPlayerTurn: true,\n status: \"in-progress\",\n };\n\n case \"PLAYER_MOVE\": {\n const { move } = action.payload;\n\n const isMoveRight = [move?.san, move?.lan].includes(\n state?.nextMove || \"\",\n );\n const isPuzzleSolved =\n state.currentMoveIndex === state.puzzle.moves.length - 1;\n\n if (!isMoveRight) {\n return {\n ...state,\n status: \"failed\",\n nextMove: null,\n hint: \"none\",\n isPlayerTurn: false,\n onFailInvoked: false,\n };\n }\n\n if (isPuzzleSolved) {\n return {\n ...state,\n status: \"solved\",\n nextMove: null,\n hint: \"none\",\n isPlayerTurn: false,\n onSolveInvoked: false,\n };\n }\n\n return {\n ...state,\n hint: \"none\",\n currentMoveIndex: state.currentMoveIndex + 1,\n nextMove: state.puzzle.moves[state.currentMoveIndex + 1],\n status: \"in-progress\",\n needCpuMove: true,\n isPlayerTurn: false,\n };\n }\n\n case \"MARK_SOLVE_INVOKED\":\n return {\n ...state,\n onSolveInvoked: true,\n };\n\n case \"MARK_FAIL_INVOKED\":\n return {\n ...state,\n onFailInvoked: true,\n };\n\n default:\n return state;\n }\n};\n","import React from \"react\";\nimport { useChessPuzzle } from \"./useChessPuzzle\";\n\nexport const ChessPuzzleContext = React.createContext<ReturnType<\n typeof useChessPuzzle\n> | null>(null);\n\nexport const useChessPuzzleContext = () => {\n const context = React.useContext(ChessPuzzleContext);\n if (!context) {\n throw new Error(\n `useChessPuzzleContext must be used within a ChessPuzzle component. Make sure your component is wrapped with <ChessPuzzle.Root> or ensure the ChessPuzzle component is properly rendered in the component tree.`,\n );\n }\n return context;\n};\n","import React from \"react\";\nimport {\n ChessGame,\n useChessGameContext,\n} from \"@react-chess-tools/react-chess-game\";\nimport { getCustomSquareStyles, stringToMove } from \"../../../utils\";\nimport { useChessPuzzleContext } from \"../../..\";\n\nexport interface PuzzleBoardProps\n extends React.ComponentProps<typeof ChessGame.Board> {}\nexport const PuzzleBoard: React.FC<PuzzleBoardProps> = ({ ...rest }) => {\n const puzzleContext = useChessPuzzleContext();\n const gameContext = useChessGameContext();\n\n if (!puzzleContext) {\n throw new Error(\"PuzzleContext not found\");\n }\n if (!gameContext) {\n throw new Error(\"ChessGameContext not found\");\n }\n\n const { game } = gameContext;\n const { status, hint, isPlayerTurn, nextMove } = puzzleContext;\n\n return (\n <ChessGame.Board\n customSquareStyles={getCustomSquareStyles(\n status,\n hint,\n isPlayerTurn,\n game,\n stringToMove(game, nextMove),\n )}\n {...rest}\n />\n );\n};\n","import React from \"react\";\nimport { isClickableElement, type Puzzle, type Status } from \"../../../utils\";\nimport { useChessPuzzleContext, type ChessPuzzleContextType } from \"../../..\";\n\nexport interface ResetProps {\n asChild?: boolean;\n puzzle?: Puzzle;\n onReset?: (puzzleContext: ChessPuzzleContextType) => void;\n showOn?: Status[];\n}\n\nconst defaultShowOn: Status[] = [\"failed\", \"solved\"];\n\nexport const Reset: React.FC<React.PropsWithChildren<ResetProps>> = ({\n children,\n asChild,\n puzzle,\n onReset,\n showOn = defaultShowOn,\n}) => {\n const puzzleContext = useChessPuzzleContext();\n if (!puzzleContext) {\n throw new Error(\"PuzzleContext not found\");\n }\n const { changePuzzle, status } = puzzleContext;\n const handleClick = () => {\n changePuzzle(puzzle || puzzleContext.puzzle);\n onReset?.(puzzleContext);\n };\n\n if (!showOn.includes(status)) {\n return null;\n }\n\n if (asChild) {\n const child = React.Children.only(children);\n if (isClickableElement(child)) {\n return React.cloneElement(child, {\n onClick: handleClick,\n });\n } else {\n throw new Error(\"Change child must be a clickable element\");\n }\n }\n\n return (\n <button type=\"button\" onClick={handleClick}>\n {children}\n </button>\n );\n};\n","import React from \"react\";\nimport { Status, isClickableElement } from \"../../../utils\";\nimport { useChessPuzzleContext } from \"../../..\";\n\nexport interface HintProps {\n asChild?: boolean;\n showOn?: Status[];\n}\n\nconst defaultShowOn: Status[] = [\"not-started\", \"in-progress\"];\n\nexport const Hint: React.FC<React.PropsWithChildren<HintProps>> = ({\n children,\n asChild,\n showOn = defaultShowOn,\n}) => {\n const puzzleContext = useChessPuzzleContext();\n if (!puzzleContext) {\n throw new Error(\"PuzzleContext not found\");\n }\n const { onHint, status } = puzzleContext;\n const handleClick = () => {\n onHint();\n };\n\n if (!showOn.includes(status)) {\n return null;\n }\n\n if (asChild) {\n const child = React.Children.only(children);\n if (isClickableElement(child)) {\n return React.cloneElement(child, {\n onClick: handleClick,\n });\n } else {\n throw new Error(\"Change child must be a clickable element\");\n }\n }\n\n return (\n <button type=\"button\" onClick={handleClick}>\n {children}\n </button>\n );\n};\n","import { Root } from \"./parts/Root\";\nimport { PuzzleBoard } from \"./parts/PuzzleBoard\";\nimport { Reset } from \"./parts/Reset\";\nimport { Hint } from \"./parts/Hint\";\n\nexport const ChessPuzzle = {\n Root,\n Board: PuzzleBoard,\n Reset,\n Hint,\n};\n"],"mappings":"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","names":["React","puzzle","_a","React","React","React","ChessGame","useChessGameContext","useChessGameContext","React","ChessGame","React","React","React","defaultShowOn","React"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-chess-tools/react-chess-puzzle",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "A lightweight, customizable React component library for rendering and interacting with chess puzzles.",
|
|
5
5
|
"main": "dist/index.mjs",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"author": "Daniele Cammareri <daniele.cammareri@gmail.com>",
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@react-chess-tools/react-chess-game": "0.4.
|
|
35
|
+
"@react-chess-tools/react-chess-game": "0.4.2",
|
|
36
36
|
"chess.js": "^1.0.0-beta.8",
|
|
37
37
|
"lodash": "^4.17.21"
|
|
38
38
|
},
|
|
@@ -6,6 +6,7 @@ import { useChessGameContext } from "@react-chess-tools/react-chess-game";
|
|
|
6
6
|
export type ChessPuzzleContextType = {
|
|
7
7
|
status: Status;
|
|
8
8
|
changePuzzle: (puzzle: Puzzle) => void;
|
|
9
|
+
resetPuzzle: () => void;
|
|
9
10
|
puzzle: Puzzle;
|
|
10
11
|
hint: Hint;
|
|
11
12
|
nextMove?: string | null;
|
|
@@ -68,10 +69,15 @@ export const useChessPuzzle = (
|
|
|
68
69
|
dispatch({ type: "TOGGLE_HINT" });
|
|
69
70
|
}, []);
|
|
70
71
|
|
|
72
|
+
const resetPuzzle = useCallback(() => {
|
|
73
|
+
changePuzzle(puzzle);
|
|
74
|
+
}, [changePuzzle, puzzle]);
|
|
75
|
+
|
|
71
76
|
const puzzleContext: ChessPuzzleContextType = useMemo(
|
|
72
77
|
() => ({
|
|
73
78
|
status: state.status,
|
|
74
79
|
changePuzzle,
|
|
80
|
+
resetPuzzle,
|
|
75
81
|
puzzle,
|
|
76
82
|
hint: state.hint,
|
|
77
83
|
onHint,
|
|
@@ -84,6 +90,7 @@ export const useChessPuzzle = (
|
|
|
84
90
|
[
|
|
85
91
|
state.status,
|
|
86
92
|
changePuzzle,
|
|
93
|
+
resetPuzzle,
|
|
87
94
|
puzzle,
|
|
88
95
|
state.hint,
|
|
89
96
|
onHint,
|
|
@@ -9,7 +9,7 @@ export const useChessPuzzleContext = () => {
|
|
|
9
9
|
const context = React.useContext(ChessPuzzleContext);
|
|
10
10
|
if (!context) {
|
|
11
11
|
throw new Error(
|
|
12
|
-
|
|
12
|
+
`useChessPuzzleContext must be used within a ChessPuzzle component. Make sure your component is wrapped with <ChessPuzzle.Root> or ensure the ChessPuzzle component is properly rendered in the component tree.`,
|
|
13
13
|
);
|
|
14
14
|
}
|
|
15
15
|
return context;
|