@react-chess-tools/react-chess-puzzle 0.6.2 → 1.0.1
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 +28 -0
- package/README.md +568 -0
- package/dist/index.cjs +513 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +128 -0
- package/dist/index.d.ts +128 -0
- package/dist/{index.mjs → index.js} +143 -92
- package/dist/index.js.map +1 -0
- package/package.json +19 -9
- package/src/components/ChessPuzzle/ThemePuzzle.stories.tsx +300 -0
- package/src/components/ChessPuzzle/parts/Hint.tsx +32 -23
- package/src/components/ChessPuzzle/parts/PuzzleBoard.tsx +33 -27
- package/src/components/ChessPuzzle/parts/Reset.tsx +56 -36
- package/src/components/ChessPuzzle/parts/Root.tsx +29 -5
- package/src/components/ChessPuzzle/parts/__tests__/Hint.test.tsx +158 -0
- package/src/components/ChessPuzzle/parts/__tests__/PuzzleBoard.test.tsx +140 -0
- package/src/components/ChessPuzzle/parts/__tests__/Reset.test.tsx +341 -0
- package/src/components/ChessPuzzle/parts/__tests__/Root.test.tsx +42 -0
- package/src/docs/Theming.mdx +255 -0
- package/src/index.ts +14 -0
- package/src/theme/__tests__/context.test.tsx +66 -0
- package/src/theme/__tests__/defaults.test.ts +48 -0
- package/src/theme/__tests__/utils.test.ts +76 -0
- package/src/theme/context.tsx +36 -0
- package/src/theme/defaults.ts +16 -0
- package/src/theme/index.ts +20 -0
- package/src/theme/types.ts +29 -0
- package/src/theme/utils.ts +28 -0
- package/src/utils/__tests__/index.test.ts +0 -17
- package/src/utils/index.ts +21 -21
- package/README.MD +0 -344
- package/dist/index.d.mts +0 -57
- package/dist/index.mjs.map +0 -1
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import { DeepPartial, ChessGameTheme, ChessGame } from '@react-chess-tools/react-chess-game';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Puzzle-specific state colors (RGBA color strings)
|
|
7
|
+
*/
|
|
8
|
+
interface PuzzleStateTheme {
|
|
9
|
+
/** Background color for successful moves */
|
|
10
|
+
success: string;
|
|
11
|
+
/** Background color for failed moves */
|
|
12
|
+
failure: string;
|
|
13
|
+
/** Background color for hint squares */
|
|
14
|
+
hint: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Complete theme configuration for ChessPuzzle component.
|
|
18
|
+
* Extends ChessGameTheme with puzzle-specific colors.
|
|
19
|
+
*/
|
|
20
|
+
interface ChessPuzzleTheme extends ChessGameTheme {
|
|
21
|
+
puzzle: PuzzleStateTheme;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Partial theme for puzzle customization - allows overriding only specific properties
|
|
25
|
+
*/
|
|
26
|
+
type PartialChessPuzzleTheme = DeepPartial<ChessPuzzleTheme>;
|
|
27
|
+
|
|
28
|
+
type Status = "not-started" | "in-progress" | "solved" | "failed";
|
|
29
|
+
type Hint = "none" | "piece" | "move";
|
|
30
|
+
type Puzzle = {
|
|
31
|
+
fen: string;
|
|
32
|
+
moves: string[];
|
|
33
|
+
makeFirstMove?: boolean;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
interface HintProps extends Omit<React__default.ButtonHTMLAttributes<HTMLButtonElement>, "onClick"> {
|
|
37
|
+
asChild?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* The puzzle statuses in which the hint button should be visible.
|
|
40
|
+
* @default ["not-started", "in-progress"]
|
|
41
|
+
*/
|
|
42
|
+
showOn?: Status[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface ResetProps extends Omit<React__default.ButtonHTMLAttributes<HTMLButtonElement>, "onReset"> {
|
|
46
|
+
asChild?: boolean;
|
|
47
|
+
puzzle?: Puzzle;
|
|
48
|
+
onReset?: (puzzleContext: ChessPuzzleContextType) => void;
|
|
49
|
+
/**
|
|
50
|
+
* The puzzle statuses in which the reset button should be visible.
|
|
51
|
+
* @default ["failed", "solved"]
|
|
52
|
+
*/
|
|
53
|
+
showOn?: Status[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface PuzzleBoardProps extends React__default.ComponentProps<typeof ChessGame.Board> {
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
type ChessPuzzleContextType = {
|
|
60
|
+
status: Status;
|
|
61
|
+
changePuzzle: (puzzle: Puzzle) => void;
|
|
62
|
+
resetPuzzle: () => void;
|
|
63
|
+
puzzle: Puzzle;
|
|
64
|
+
hint: Hint;
|
|
65
|
+
nextMove?: string | null;
|
|
66
|
+
isPlayerTurn: boolean;
|
|
67
|
+
onHint: () => void;
|
|
68
|
+
puzzleState: Status;
|
|
69
|
+
movesPlayed: number;
|
|
70
|
+
totalMoves: number;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
interface RootProps {
|
|
74
|
+
puzzle: Puzzle;
|
|
75
|
+
onSolve?: (puzzleContext: ChessPuzzleContextType) => void;
|
|
76
|
+
onFail?: (puzzleContext: ChessPuzzleContextType) => void;
|
|
77
|
+
/** Optional theme configuration. Supports partial themes - only override the colors you need. */
|
|
78
|
+
theme?: PartialChessPuzzleTheme;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
declare const ChessPuzzle: {
|
|
82
|
+
Root: React.FC<React.PropsWithChildren<RootProps>>;
|
|
83
|
+
Board: React.ForwardRefExoticComponent<Omit<PuzzleBoardProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
84
|
+
Reset: React.ForwardRefExoticComponent<ResetProps & {
|
|
85
|
+
children?: React.ReactNode | undefined;
|
|
86
|
+
} & React.RefAttributes<HTMLElement>>;
|
|
87
|
+
Hint: React.ForwardRefExoticComponent<HintProps & {
|
|
88
|
+
children?: React.ReactNode | undefined;
|
|
89
|
+
} & React.RefAttributes<HTMLElement>>;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
declare const useChessPuzzleContext: () => ChessPuzzleContextType;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Default theme for ChessPuzzle component.
|
|
96
|
+
* Extends the default game theme with puzzle-specific colors.
|
|
97
|
+
* These values match the original hardcoded colors for backward compatibility.
|
|
98
|
+
*/
|
|
99
|
+
declare const defaultPuzzleTheme: ChessPuzzleTheme;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Deep merges a partial puzzle theme with the default puzzle theme.
|
|
103
|
+
* Allows users to override only specific theme properties while keeping defaults for the rest.
|
|
104
|
+
*
|
|
105
|
+
* @param partialTheme - Partial theme with only the properties to override
|
|
106
|
+
* @returns Complete puzzle theme with overridden properties merged with defaults
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const customTheme = mergePuzzleTheme({
|
|
111
|
+
* puzzle: { hint: "rgba(0, 255, 255, 0.5)" }
|
|
112
|
+
* });
|
|
113
|
+
* // Returns full puzzle theme with only hint color changed
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
declare const mergePuzzleTheme: (partialTheme?: PartialChessPuzzleTheme) => ChessPuzzleTheme;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Context for ChessPuzzle theme
|
|
120
|
+
*/
|
|
121
|
+
declare const ChessPuzzleThemeContext: React__default.Context<ChessPuzzleTheme>;
|
|
122
|
+
/**
|
|
123
|
+
* Hook to access the current ChessPuzzle theme.
|
|
124
|
+
* Returns the default puzzle theme if no ThemeProvider is present.
|
|
125
|
+
*/
|
|
126
|
+
declare const useChessPuzzleTheme: () => ChessPuzzleTheme;
|
|
127
|
+
|
|
128
|
+
export { ChessPuzzle, type ChessPuzzleContextType, type ChessPuzzleTheme, ChessPuzzleThemeContext, type Hint, type HintProps, type PartialChessPuzzleTheme, type Puzzle, type PuzzleBoardProps, type PuzzleStateTheme, type ResetProps, type RootProps, type Status, defaultPuzzleTheme, mergePuzzleTheme, useChessPuzzleContext, useChessPuzzleTheme };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import { DeepPartial, ChessGameTheme, ChessGame } from '@react-chess-tools/react-chess-game';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Puzzle-specific state colors (RGBA color strings)
|
|
7
|
+
*/
|
|
8
|
+
interface PuzzleStateTheme {
|
|
9
|
+
/** Background color for successful moves */
|
|
10
|
+
success: string;
|
|
11
|
+
/** Background color for failed moves */
|
|
12
|
+
failure: string;
|
|
13
|
+
/** Background color for hint squares */
|
|
14
|
+
hint: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Complete theme configuration for ChessPuzzle component.
|
|
18
|
+
* Extends ChessGameTheme with puzzle-specific colors.
|
|
19
|
+
*/
|
|
20
|
+
interface ChessPuzzleTheme extends ChessGameTheme {
|
|
21
|
+
puzzle: PuzzleStateTheme;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Partial theme for puzzle customization - allows overriding only specific properties
|
|
25
|
+
*/
|
|
26
|
+
type PartialChessPuzzleTheme = DeepPartial<ChessPuzzleTheme>;
|
|
27
|
+
|
|
28
|
+
type Status = "not-started" | "in-progress" | "solved" | "failed";
|
|
29
|
+
type Hint = "none" | "piece" | "move";
|
|
30
|
+
type Puzzle = {
|
|
31
|
+
fen: string;
|
|
32
|
+
moves: string[];
|
|
33
|
+
makeFirstMove?: boolean;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
interface HintProps extends Omit<React__default.ButtonHTMLAttributes<HTMLButtonElement>, "onClick"> {
|
|
37
|
+
asChild?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* The puzzle statuses in which the hint button should be visible.
|
|
40
|
+
* @default ["not-started", "in-progress"]
|
|
41
|
+
*/
|
|
42
|
+
showOn?: Status[];
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface ResetProps extends Omit<React__default.ButtonHTMLAttributes<HTMLButtonElement>, "onReset"> {
|
|
46
|
+
asChild?: boolean;
|
|
47
|
+
puzzle?: Puzzle;
|
|
48
|
+
onReset?: (puzzleContext: ChessPuzzleContextType) => void;
|
|
49
|
+
/**
|
|
50
|
+
* The puzzle statuses in which the reset button should be visible.
|
|
51
|
+
* @default ["failed", "solved"]
|
|
52
|
+
*/
|
|
53
|
+
showOn?: Status[];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
interface PuzzleBoardProps extends React__default.ComponentProps<typeof ChessGame.Board> {
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
type ChessPuzzleContextType = {
|
|
60
|
+
status: Status;
|
|
61
|
+
changePuzzle: (puzzle: Puzzle) => void;
|
|
62
|
+
resetPuzzle: () => void;
|
|
63
|
+
puzzle: Puzzle;
|
|
64
|
+
hint: Hint;
|
|
65
|
+
nextMove?: string | null;
|
|
66
|
+
isPlayerTurn: boolean;
|
|
67
|
+
onHint: () => void;
|
|
68
|
+
puzzleState: Status;
|
|
69
|
+
movesPlayed: number;
|
|
70
|
+
totalMoves: number;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
interface RootProps {
|
|
74
|
+
puzzle: Puzzle;
|
|
75
|
+
onSolve?: (puzzleContext: ChessPuzzleContextType) => void;
|
|
76
|
+
onFail?: (puzzleContext: ChessPuzzleContextType) => void;
|
|
77
|
+
/** Optional theme configuration. Supports partial themes - only override the colors you need. */
|
|
78
|
+
theme?: PartialChessPuzzleTheme;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
declare const ChessPuzzle: {
|
|
82
|
+
Root: React.FC<React.PropsWithChildren<RootProps>>;
|
|
83
|
+
Board: React.ForwardRefExoticComponent<Omit<PuzzleBoardProps, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
84
|
+
Reset: React.ForwardRefExoticComponent<ResetProps & {
|
|
85
|
+
children?: React.ReactNode | undefined;
|
|
86
|
+
} & React.RefAttributes<HTMLElement>>;
|
|
87
|
+
Hint: React.ForwardRefExoticComponent<HintProps & {
|
|
88
|
+
children?: React.ReactNode | undefined;
|
|
89
|
+
} & React.RefAttributes<HTMLElement>>;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
declare const useChessPuzzleContext: () => ChessPuzzleContextType;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Default theme for ChessPuzzle component.
|
|
96
|
+
* Extends the default game theme with puzzle-specific colors.
|
|
97
|
+
* These values match the original hardcoded colors for backward compatibility.
|
|
98
|
+
*/
|
|
99
|
+
declare const defaultPuzzleTheme: ChessPuzzleTheme;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Deep merges a partial puzzle theme with the default puzzle theme.
|
|
103
|
+
* Allows users to override only specific theme properties while keeping defaults for the rest.
|
|
104
|
+
*
|
|
105
|
+
* @param partialTheme - Partial theme with only the properties to override
|
|
106
|
+
* @returns Complete puzzle theme with overridden properties merged with defaults
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const customTheme = mergePuzzleTheme({
|
|
111
|
+
* puzzle: { hint: "rgba(0, 255, 255, 0.5)" }
|
|
112
|
+
* });
|
|
113
|
+
* // Returns full puzzle theme with only hint color changed
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
declare const mergePuzzleTheme: (partialTheme?: PartialChessPuzzleTheme) => ChessPuzzleTheme;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Context for ChessPuzzle theme
|
|
120
|
+
*/
|
|
121
|
+
declare const ChessPuzzleThemeContext: React__default.Context<ChessPuzzleTheme>;
|
|
122
|
+
/**
|
|
123
|
+
* Hook to access the current ChessPuzzle theme.
|
|
124
|
+
* Returns the default puzzle theme if no ThemeProvider is present.
|
|
125
|
+
*/
|
|
126
|
+
declare const useChessPuzzleTheme: () => ChessPuzzleTheme;
|
|
127
|
+
|
|
128
|
+
export { ChessPuzzle, type ChessPuzzleContextType, type ChessPuzzleTheme, ChessPuzzleThemeContext, type Hint, type HintProps, type PartialChessPuzzleTheme, type Puzzle, type PuzzleBoardProps, type PuzzleStateTheme, type ResetProps, type RootProps, type Status, defaultPuzzleTheme, mergePuzzleTheme, useChessPuzzleContext, useChessPuzzleTheme };
|
|
@@ -3,11 +3,20 @@ import React3 from "react";
|
|
|
3
3
|
|
|
4
4
|
// src/utils/index.ts
|
|
5
5
|
import { Chess } from "chess.js";
|
|
6
|
-
import React from "react";
|
|
7
6
|
import _ from "lodash";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
|
|
8
|
+
// src/theme/defaults.ts
|
|
9
|
+
import { defaultGameTheme } from "@react-chess-tools/react-chess-game";
|
|
10
|
+
var defaultPuzzleTheme = {
|
|
11
|
+
...defaultGameTheme,
|
|
12
|
+
puzzle: {
|
|
13
|
+
success: "rgba(172, 206, 89, 0.5)",
|
|
14
|
+
failure: "rgba(201, 52, 48, 0.5)",
|
|
15
|
+
hint: "rgba(27, 172, 166, 0.5)"
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// src/utils/index.ts
|
|
11
20
|
var getOrientation = (puzzle) => {
|
|
12
21
|
const fen = puzzle.fen;
|
|
13
22
|
const game = new Chess(fen);
|
|
@@ -16,40 +25,39 @@ var getOrientation = (puzzle) => {
|
|
|
16
25
|
}
|
|
17
26
|
return game.turn();
|
|
18
27
|
};
|
|
19
|
-
var
|
|
20
|
-
var getCustomSquareStyles = (status, hint, isPlayerTurn, game, nextMove) => {
|
|
28
|
+
var getCustomSquareStyles = (status, hint, isPlayerTurn, game, nextMove, theme = defaultPuzzleTheme) => {
|
|
21
29
|
const customSquareStyles = {};
|
|
22
30
|
const lastMove = _.last(game.history({ verbose: true }));
|
|
23
31
|
if (status === "failed" && lastMove) {
|
|
24
32
|
customSquareStyles[lastMove.from] = {
|
|
25
|
-
backgroundColor:
|
|
33
|
+
backgroundColor: theme.puzzle.failure
|
|
26
34
|
};
|
|
27
35
|
customSquareStyles[lastMove.to] = {
|
|
28
|
-
backgroundColor:
|
|
36
|
+
backgroundColor: theme.puzzle.failure
|
|
29
37
|
};
|
|
30
38
|
}
|
|
31
39
|
if (lastMove && (status === "solved" || status !== "failed" && !isPlayerTurn)) {
|
|
32
40
|
customSquareStyles[lastMove.from] = {
|
|
33
|
-
backgroundColor:
|
|
41
|
+
backgroundColor: theme.puzzle.success
|
|
34
42
|
};
|
|
35
43
|
customSquareStyles[lastMove.to] = {
|
|
36
|
-
backgroundColor:
|
|
44
|
+
backgroundColor: theme.puzzle.success
|
|
37
45
|
};
|
|
38
46
|
}
|
|
39
47
|
if (hint === "piece") {
|
|
40
48
|
if (nextMove) {
|
|
41
49
|
customSquareStyles[nextMove.from] = {
|
|
42
|
-
backgroundColor:
|
|
50
|
+
backgroundColor: theme.puzzle.hint
|
|
43
51
|
};
|
|
44
52
|
}
|
|
45
53
|
}
|
|
46
54
|
if (hint === "move") {
|
|
47
55
|
if (nextMove) {
|
|
48
56
|
customSquareStyles[nextMove.from] = {
|
|
49
|
-
backgroundColor:
|
|
57
|
+
backgroundColor: theme.puzzle.hint
|
|
50
58
|
};
|
|
51
59
|
customSquareStyles[nextMove.to] = {
|
|
52
|
-
backgroundColor:
|
|
60
|
+
backgroundColor: theme.puzzle.hint
|
|
53
61
|
};
|
|
54
62
|
}
|
|
55
63
|
}
|
|
@@ -279,10 +287,10 @@ var useChessPuzzle = (puzzle, onSolve, onFail) => {
|
|
|
279
287
|
import { ChessGame } from "@react-chess-tools/react-chess-game";
|
|
280
288
|
|
|
281
289
|
// src/hooks/useChessPuzzleContext.ts
|
|
282
|
-
import
|
|
283
|
-
var ChessPuzzleContext =
|
|
290
|
+
import React from "react";
|
|
291
|
+
var ChessPuzzleContext = React.createContext(null);
|
|
284
292
|
var useChessPuzzleContext = () => {
|
|
285
|
-
const context =
|
|
293
|
+
const context = React.useContext(ChessPuzzleContext);
|
|
286
294
|
if (!context) {
|
|
287
295
|
throw new Error(
|
|
288
296
|
`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.`
|
|
@@ -291,8 +299,30 @@ var useChessPuzzleContext = () => {
|
|
|
291
299
|
return context;
|
|
292
300
|
};
|
|
293
301
|
|
|
302
|
+
// src/theme/context.tsx
|
|
303
|
+
import React2, { createContext, useContext } from "react";
|
|
304
|
+
var ChessPuzzleThemeContext = createContext(defaultPuzzleTheme);
|
|
305
|
+
var useChessPuzzleTheme = () => {
|
|
306
|
+
return useContext(ChessPuzzleThemeContext);
|
|
307
|
+
};
|
|
308
|
+
var PuzzleThemeProvider = ({
|
|
309
|
+
theme,
|
|
310
|
+
children
|
|
311
|
+
}) => {
|
|
312
|
+
return /* @__PURE__ */ React2.createElement(ChessPuzzleThemeContext.Provider, { value: theme }, children);
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
// src/theme/utils.ts
|
|
316
|
+
import { merge } from "lodash";
|
|
317
|
+
var mergePuzzleTheme = (partialTheme) => {
|
|
318
|
+
if (!partialTheme) {
|
|
319
|
+
return { ...defaultPuzzleTheme };
|
|
320
|
+
}
|
|
321
|
+
return merge({}, defaultPuzzleTheme, partialTheme);
|
|
322
|
+
};
|
|
323
|
+
|
|
294
324
|
// src/components/ChessPuzzle/parts/Root.tsx
|
|
295
|
-
var
|
|
325
|
+
var PuzzleRootInner = ({
|
|
296
326
|
puzzle,
|
|
297
327
|
onSolve,
|
|
298
328
|
onFail,
|
|
@@ -305,10 +335,21 @@ var Root = ({
|
|
|
305
335
|
puzzle,
|
|
306
336
|
onSolve,
|
|
307
337
|
onFail,
|
|
338
|
+
theme,
|
|
308
339
|
children
|
|
309
340
|
}) => {
|
|
310
|
-
|
|
341
|
+
const mergedTheme = React3.useMemo(() => mergePuzzleTheme(theme), [theme]);
|
|
342
|
+
return /* @__PURE__ */ React3.createElement(
|
|
343
|
+
ChessGame.Root,
|
|
344
|
+
{
|
|
345
|
+
fen: puzzle.fen,
|
|
346
|
+
orientation: getOrientation(puzzle),
|
|
347
|
+
theme: mergedTheme
|
|
348
|
+
},
|
|
349
|
+
/* @__PURE__ */ React3.createElement(PuzzleThemeProvider, { theme: mergedTheme }, /* @__PURE__ */ React3.createElement(PuzzleRootInner, { puzzle, onSolve, onFail }, children))
|
|
350
|
+
);
|
|
311
351
|
};
|
|
352
|
+
Root.displayName = "ChessPuzzle.Root";
|
|
312
353
|
|
|
313
354
|
// src/components/ChessPuzzle/parts/PuzzleBoard.tsx
|
|
314
355
|
import React4 from "react";
|
|
@@ -317,98 +358,104 @@ import {
|
|
|
317
358
|
deepMergeChessboardOptions,
|
|
318
359
|
useChessGameContext as useChessGameContext2
|
|
319
360
|
} from "@react-chess-tools/react-chess-game";
|
|
320
|
-
var PuzzleBoard = (
|
|
321
|
-
options
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
361
|
+
var PuzzleBoard = React4.forwardRef(
|
|
362
|
+
({ options, ...rest }, ref) => {
|
|
363
|
+
const puzzleContext = useChessPuzzleContext();
|
|
364
|
+
const gameContext = useChessGameContext2();
|
|
365
|
+
const theme = useChessPuzzleTheme();
|
|
366
|
+
if (!puzzleContext) {
|
|
367
|
+
throw new Error("PuzzleContext not found");
|
|
368
|
+
}
|
|
369
|
+
if (!gameContext) {
|
|
370
|
+
throw new Error("ChessGameContext not found");
|
|
371
|
+
}
|
|
372
|
+
const { game } = gameContext;
|
|
373
|
+
const { status, hint, isPlayerTurn, nextMove } = puzzleContext;
|
|
374
|
+
const mergedOptions = deepMergeChessboardOptions(options || {}, {
|
|
375
|
+
squareStyles: getCustomSquareStyles(
|
|
376
|
+
status,
|
|
377
|
+
hint,
|
|
378
|
+
isPlayerTurn,
|
|
379
|
+
game,
|
|
380
|
+
stringToMove(game, nextMove),
|
|
381
|
+
theme
|
|
382
|
+
)
|
|
383
|
+
});
|
|
384
|
+
return /* @__PURE__ */ React4.createElement(ChessGame2.Board, { ref, ...rest, options: mergedOptions });
|
|
331
385
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const mergedOptions = deepMergeChessboardOptions(options, {
|
|
335
|
-
squareStyles: getCustomSquareStyles(
|
|
336
|
-
status,
|
|
337
|
-
hint,
|
|
338
|
-
isPlayerTurn,
|
|
339
|
-
game,
|
|
340
|
-
stringToMove(game, nextMove)
|
|
341
|
-
)
|
|
342
|
-
});
|
|
343
|
-
return /* @__PURE__ */ React4.createElement(ChessGame2.Board, { ...rest, options: mergedOptions });
|
|
344
|
-
};
|
|
386
|
+
);
|
|
387
|
+
PuzzleBoard.displayName = "ChessPuzzle.PuzzleBoard";
|
|
345
388
|
|
|
346
389
|
// src/components/ChessPuzzle/parts/Reset.tsx
|
|
347
390
|
import React5 from "react";
|
|
391
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
348
392
|
var defaultShowOn = ["failed", "solved"];
|
|
349
|
-
var Reset = (
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
if (isClickableElement(child)) {
|
|
371
|
-
return React5.cloneElement(child, {
|
|
372
|
-
onClick: handleClick
|
|
373
|
-
});
|
|
374
|
-
} else {
|
|
375
|
-
throw new Error("Change child must be a clickable element");
|
|
393
|
+
var Reset = React5.forwardRef(
|
|
394
|
+
({
|
|
395
|
+
children,
|
|
396
|
+
asChild,
|
|
397
|
+
puzzle,
|
|
398
|
+
onReset,
|
|
399
|
+
showOn = defaultShowOn,
|
|
400
|
+
className,
|
|
401
|
+
...rest
|
|
402
|
+
}, ref) => {
|
|
403
|
+
const puzzleContext = useChessPuzzleContext();
|
|
404
|
+
if (!puzzleContext) {
|
|
405
|
+
throw new Error("PuzzleContext not found");
|
|
406
|
+
}
|
|
407
|
+
const { changePuzzle, puzzle: contextPuzzle, status } = puzzleContext;
|
|
408
|
+
const handleClick = React5.useCallback(() => {
|
|
409
|
+
changePuzzle(puzzle || contextPuzzle);
|
|
410
|
+
onReset == null ? void 0 : onReset(puzzleContext);
|
|
411
|
+
}, [changePuzzle, puzzle, contextPuzzle, puzzleContext, onReset]);
|
|
412
|
+
if (!showOn.includes(status)) {
|
|
413
|
+
return null;
|
|
376
414
|
}
|
|
415
|
+
return asChild ? /* @__PURE__ */ React5.createElement(Slot, { ref, onClick: handleClick, className, ...rest }, children) : /* @__PURE__ */ React5.createElement(
|
|
416
|
+
"button",
|
|
417
|
+
{
|
|
418
|
+
ref,
|
|
419
|
+
type: "button",
|
|
420
|
+
className,
|
|
421
|
+
onClick: handleClick,
|
|
422
|
+
...rest
|
|
423
|
+
},
|
|
424
|
+
children
|
|
425
|
+
);
|
|
377
426
|
}
|
|
378
|
-
|
|
379
|
-
|
|
427
|
+
);
|
|
428
|
+
Reset.displayName = "ChessPuzzle.Reset";
|
|
380
429
|
|
|
381
430
|
// src/components/ChessPuzzle/parts/Hint.tsx
|
|
382
431
|
import React6 from "react";
|
|
432
|
+
import { Slot as Slot2 } from "@radix-ui/react-slot";
|
|
383
433
|
var defaultShowOn2 = ["not-started", "in-progress"];
|
|
384
|
-
var Hint = ({
|
|
385
|
-
children,
|
|
386
|
-
asChild,
|
|
387
|
-
showOn = defaultShowOn2
|
|
388
|
-
}) => {
|
|
434
|
+
var Hint = React6.forwardRef(({ children, asChild, showOn = defaultShowOn2, className, ...rest }, ref) => {
|
|
389
435
|
const puzzleContext = useChessPuzzleContext();
|
|
390
436
|
if (!puzzleContext) {
|
|
391
437
|
throw new Error("PuzzleContext not found");
|
|
392
438
|
}
|
|
393
439
|
const { onHint, status } = puzzleContext;
|
|
394
|
-
const handleClick = () => {
|
|
440
|
+
const handleClick = React6.useCallback(() => {
|
|
395
441
|
onHint();
|
|
396
|
-
};
|
|
442
|
+
}, [onHint]);
|
|
397
443
|
if (!showOn.includes(status)) {
|
|
398
444
|
return null;
|
|
399
445
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
};
|
|
446
|
+
return asChild ? /* @__PURE__ */ React6.createElement(Slot2, { ref, onClick: handleClick, className, ...rest }, children) : /* @__PURE__ */ React6.createElement(
|
|
447
|
+
"button",
|
|
448
|
+
{
|
|
449
|
+
ref,
|
|
450
|
+
type: "button",
|
|
451
|
+
className,
|
|
452
|
+
onClick: handleClick,
|
|
453
|
+
...rest
|
|
454
|
+
},
|
|
455
|
+
children
|
|
456
|
+
);
|
|
457
|
+
});
|
|
458
|
+
Hint.displayName = "ChessPuzzle.Hint";
|
|
412
459
|
|
|
413
460
|
// src/components/ChessPuzzle/index.ts
|
|
414
461
|
var ChessPuzzle = {
|
|
@@ -419,6 +466,10 @@ var ChessPuzzle = {
|
|
|
419
466
|
};
|
|
420
467
|
export {
|
|
421
468
|
ChessPuzzle,
|
|
422
|
-
|
|
469
|
+
ChessPuzzleThemeContext,
|
|
470
|
+
defaultPuzzleTheme,
|
|
471
|
+
mergePuzzleTheme,
|
|
472
|
+
useChessPuzzleContext,
|
|
473
|
+
useChessPuzzleTheme
|
|
423
474
|
};
|
|
424
|
-
//# sourceMappingURL=index.
|
|
475
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ChessPuzzle/parts/Root.tsx","../src/utils/index.ts","../src/theme/defaults.ts","../src/hooks/useChessPuzzle.ts","../src/hooks/reducer.ts","../src/hooks/useChessPuzzleContext.ts","../src/theme/context.tsx","../src/theme/utils.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\";\nimport { PuzzleThemeProvider } from \"../../../theme/context\";\nimport { mergePuzzleTheme } from \"../../../theme/utils\";\nimport type { PartialChessPuzzleTheme } from \"../../../theme/types\";\n\nexport interface RootProps {\n puzzle: Puzzle;\n onSolve?: (puzzleContext: ChessPuzzleContextType) => void;\n onFail?: (puzzleContext: ChessPuzzleContextType) => void;\n /** Optional theme configuration. Supports partial themes - only override the colors you need. */\n theme?: PartialChessPuzzleTheme;\n}\n\ninterface PuzzleRootInnerProps {\n puzzle: Puzzle;\n onSolve?: (puzzleContext: ChessPuzzleContextType) => void;\n onFail?: (puzzleContext: ChessPuzzleContextType) => void;\n children: React.ReactNode;\n}\n\nconst PuzzleRootInner: React.FC<PuzzleRootInnerProps> = ({\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 theme,\n children,\n}) => {\n // Merge partial theme with defaults\n const mergedTheme = React.useMemo(() => mergePuzzleTheme(theme), [theme]);\n\n return (\n <ChessGame.Root\n fen={puzzle.fen}\n orientation={getOrientation(puzzle)}\n theme={mergedTheme}\n >\n <PuzzleThemeProvider theme={mergedTheme}>\n <PuzzleRootInner puzzle={puzzle} onSolve={onSolve} onFail={onFail}>\n {children}\n </PuzzleRootInner>\n </PuzzleThemeProvider>\n </ChessGame.Root>\n );\n};\n\nRoot.displayName = \"ChessPuzzle.Root\";\n","import { type Color, Chess, Move } from \"chess.js\";\nimport React, { CSSProperties, ReactElement, ReactNode } from \"react\";\nimport _ from \"lodash\";\nimport type { ChessPuzzleTheme } from \"../theme/types\";\nimport { defaultPuzzleTheme } from \"../theme/defaults\";\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\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\n/**\n * Generates custom square styles for puzzle states based on theme.\n *\n * @param status - Current puzzle status\n * @param hint - Current hint level\n * @param isPlayerTurn - Whether it's the player's turn\n * @param game - Chess.js game instance\n * @param nextMove - The next expected move (for hints)\n * @param theme - Theme configuration (defaults to defaultPuzzleTheme)\n * @returns Record of square names to CSS properties\n */\nexport const getCustomSquareStyles = (\n status: Status,\n hint: Hint,\n isPlayerTurn: boolean,\n game: Chess,\n nextMove?: Move | null,\n theme: ChessPuzzleTheme = defaultPuzzleTheme,\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: theme.puzzle.failure,\n };\n customSquareStyles[lastMove.to] = {\n backgroundColor: theme.puzzle.failure,\n };\n }\n\n if (\n lastMove &&\n (status === \"solved\" || (status !== \"failed\" && !isPlayerTurn))\n ) {\n customSquareStyles[lastMove.from] = {\n backgroundColor: theme.puzzle.success,\n };\n customSquareStyles[lastMove.to] = {\n backgroundColor: theme.puzzle.success,\n };\n }\n\n if (hint === \"piece\") {\n if (nextMove) {\n customSquareStyles[nextMove.from] = {\n backgroundColor: theme.puzzle.hint,\n };\n }\n }\n\n if (hint === \"move\") {\n if (nextMove) {\n customSquareStyles[nextMove.from] = {\n backgroundColor: theme.puzzle.hint,\n };\n customSquareStyles[nextMove.to] = {\n backgroundColor: theme.puzzle.hint,\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 { defaultGameTheme } from \"@react-chess-tools/react-chess-game\";\nimport type { ChessPuzzleTheme } from \"./types\";\n\n/**\n * Default theme for ChessPuzzle component.\n * Extends the default game theme with puzzle-specific colors.\n * These values match the original hardcoded colors for backward compatibility.\n */\nexport const defaultPuzzleTheme: ChessPuzzleTheme = {\n ...defaultGameTheme,\n puzzle: {\n success: \"rgba(172, 206, 89, 0.5)\",\n failure: \"rgba(201, 52, 48, 0.5)\",\n hint: \"rgba(27, 172, 166, 0.5)\",\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, { createContext, useContext } from \"react\";\nimport type { ChessPuzzleTheme } from \"./types\";\nimport { defaultPuzzleTheme } from \"./defaults\";\n\n/**\n * Context for ChessPuzzle theme\n */\nexport const ChessPuzzleThemeContext =\n createContext<ChessPuzzleTheme>(defaultPuzzleTheme);\n\n/**\n * Hook to access the current ChessPuzzle theme.\n * Returns the default puzzle theme if no ThemeProvider is present.\n */\nexport const useChessPuzzleTheme = (): ChessPuzzleTheme => {\n return useContext(ChessPuzzleThemeContext);\n};\n\nexport interface PuzzleThemeProviderProps {\n theme: ChessPuzzleTheme;\n children: React.ReactNode;\n}\n\n/**\n * Internal provider component used by Puzzle Root when a theme prop is provided.\n */\nexport const PuzzleThemeProvider: React.FC<PuzzleThemeProviderProps> = ({\n theme,\n children,\n}) => {\n return (\n <ChessPuzzleThemeContext.Provider value={theme}>\n {children}\n </ChessPuzzleThemeContext.Provider>\n );\n};\n","import { merge } from \"lodash\";\nimport type { ChessPuzzleTheme, PartialChessPuzzleTheme } from \"./types\";\nimport { defaultPuzzleTheme } from \"./defaults\";\n\n/**\n * Deep merges a partial puzzle theme with the default puzzle theme.\n * Allows users to override only specific theme properties while keeping defaults for the rest.\n *\n * @param partialTheme - Partial theme with only the properties to override\n * @returns Complete puzzle theme with overridden properties merged with defaults\n *\n * @example\n * ```typescript\n * const customTheme = mergePuzzleTheme({\n * puzzle: { hint: \"rgba(0, 255, 255, 0.5)\" }\n * });\n * // Returns full puzzle theme with only hint color changed\n * ```\n */\nexport const mergePuzzleTheme = (\n partialTheme?: PartialChessPuzzleTheme,\n): ChessPuzzleTheme => {\n if (!partialTheme) {\n return { ...defaultPuzzleTheme };\n }\n\n return merge({}, defaultPuzzleTheme, partialTheme);\n};\n","import React from \"react\";\nimport {\n ChessGame,\n deepMergeChessboardOptions,\n useChessGameContext,\n} from \"@react-chess-tools/react-chess-game\";\nimport { getCustomSquareStyles, stringToMove } from \"../../../utils\";\nimport { useChessPuzzleContext } from \"../../..\";\nimport { useChessPuzzleTheme } from \"../../../theme/context\";\n\nexport interface PuzzleBoardProps extends React.ComponentProps<\n typeof ChessGame.Board\n> {}\n\nexport const PuzzleBoard = React.forwardRef<HTMLDivElement, PuzzleBoardProps>(\n ({ options, ...rest }, ref) => {\n const puzzleContext = useChessPuzzleContext();\n const gameContext = useChessGameContext();\n const theme = useChessPuzzleTheme();\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 const mergedOptions = deepMergeChessboardOptions(options || {}, {\n squareStyles: getCustomSquareStyles(\n status,\n hint,\n isPlayerTurn,\n game,\n stringToMove(game, nextMove),\n theme,\n ),\n });\n\n return <ChessGame.Board ref={ref} {...rest} options={mergedOptions} />;\n },\n);\n\nPuzzleBoard.displayName = \"ChessPuzzle.PuzzleBoard\";\n","import React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { type Puzzle, type Status } from \"../../../utils\";\nimport { useChessPuzzleContext, type ChessPuzzleContextType } from \"../../..\";\n\nexport interface ResetProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n \"onReset\"\n> {\n asChild?: boolean;\n puzzle?: Puzzle;\n onReset?: (puzzleContext: ChessPuzzleContextType) => void;\n /**\n * The puzzle statuses in which the reset button should be visible.\n * @default [\"failed\", \"solved\"]\n */\n showOn?: Status[];\n}\n\nconst defaultShowOn: Status[] = [\"failed\", \"solved\"];\n\nexport const Reset = React.forwardRef<\n HTMLElement,\n React.PropsWithChildren<ResetProps>\n>(\n (\n {\n children,\n asChild,\n puzzle,\n onReset,\n showOn = defaultShowOn,\n className,\n ...rest\n },\n ref,\n ) => {\n const puzzleContext = useChessPuzzleContext();\n if (!puzzleContext) {\n throw new Error(\"PuzzleContext not found\");\n }\n const { changePuzzle, puzzle: contextPuzzle, status } = puzzleContext;\n\n const handleClick = React.useCallback(() => {\n changePuzzle(puzzle || contextPuzzle);\n onReset?.(puzzleContext);\n }, [changePuzzle, puzzle, contextPuzzle, puzzleContext, onReset]);\n\n if (!showOn.includes(status)) {\n return null;\n }\n\n return asChild ? (\n <Slot ref={ref} onClick={handleClick} className={className} {...rest}>\n {children}\n </Slot>\n ) : (\n <button\n ref={ref as React.RefObject<HTMLButtonElement>}\n type=\"button\"\n className={className}\n onClick={handleClick}\n {...rest}\n >\n {children}\n </button>\n );\n },\n);\n\nReset.displayName = \"ChessPuzzle.Reset\";\n","import React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { Status } from \"../../../utils\";\nimport { useChessPuzzleContext } from \"../../..\";\n\nexport interface HintProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n \"onClick\"\n> {\n asChild?: boolean;\n /**\n * The puzzle statuses in which the hint button should be visible.\n * @default [\"not-started\", \"in-progress\"]\n */\n showOn?: Status[];\n}\n\nconst defaultShowOn: Status[] = [\"not-started\", \"in-progress\"];\n\nexport const Hint = React.forwardRef<\n HTMLElement,\n React.PropsWithChildren<HintProps>\n>(({ children, asChild, showOn = defaultShowOn, className, ...rest }, ref) => {\n const puzzleContext = useChessPuzzleContext();\n if (!puzzleContext) {\n throw new Error(\"PuzzleContext not found\");\n }\n const { onHint, status } = puzzleContext;\n\n const handleClick = React.useCallback(() => {\n onHint();\n }, [onHint]);\n\n if (!showOn.includes(status)) {\n return null;\n }\n\n return asChild ? (\n <Slot ref={ref} onClick={handleClick} className={className} {...rest}>\n {children}\n </Slot>\n ) : (\n <button\n ref={ref as React.RefObject<HTMLButtonElement>}\n type=\"button\"\n className={className}\n onClick={handleClick}\n {...rest}\n >\n {children}\n </button>\n );\n});\n\nHint.displayName = \"ChessPuzzle.Hint\";\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","React","ChessGame","useChessGameContext","React","useChessGameContext","ChessGame","React","React","React","Slot","defaultShowOn","React","Slot"]}
|