@react-chess-tools/react-chess-puzzle 0.6.2 → 1.0.0
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 +20 -0
- package/dist/index.cjs +510 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +116 -0
- package/dist/index.d.ts +116 -0
- package/dist/{index.mjs → index.js} +76 -28
- package/dist/index.js.map +1 -0
- package/package.json +18 -9
- package/src/components/ChessPuzzle/ThemePuzzle.stories.tsx +300 -0
- package/src/components/ChessPuzzle/parts/PuzzleBoard.tsx +7 -2
- package/src/components/ChessPuzzle/parts/Root.tsx +27 -5
- 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/index.ts +21 -11
- package/dist/index.d.mts +0 -57
- package/dist/index.mjs.map +0 -1
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
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 {
|
|
37
|
+
asChild?: boolean;
|
|
38
|
+
showOn?: Status[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface ResetProps {
|
|
42
|
+
asChild?: boolean;
|
|
43
|
+
puzzle?: Puzzle;
|
|
44
|
+
onReset?: (puzzleContext: ChessPuzzleContextType) => void;
|
|
45
|
+
showOn?: Status[];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface PuzzleBoardProps extends React__default.ComponentProps<typeof ChessGame.Board> {
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
type ChessPuzzleContextType = {
|
|
52
|
+
status: Status;
|
|
53
|
+
changePuzzle: (puzzle: Puzzle) => void;
|
|
54
|
+
resetPuzzle: () => void;
|
|
55
|
+
puzzle: Puzzle;
|
|
56
|
+
hint: Hint;
|
|
57
|
+
nextMove?: string | null;
|
|
58
|
+
isPlayerTurn: boolean;
|
|
59
|
+
onHint: () => void;
|
|
60
|
+
puzzleState: Status;
|
|
61
|
+
movesPlayed: number;
|
|
62
|
+
totalMoves: number;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
interface RootProps {
|
|
66
|
+
puzzle: Puzzle;
|
|
67
|
+
onSolve?: (puzzleContext: ChessPuzzleContextType) => void;
|
|
68
|
+
onFail?: (puzzleContext: ChessPuzzleContextType) => void;
|
|
69
|
+
/** Optional theme configuration. Supports partial themes - only override the colors you need. */
|
|
70
|
+
theme?: PartialChessPuzzleTheme;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
declare const ChessPuzzle: {
|
|
74
|
+
Root: React.FC<React.PropsWithChildren<RootProps>>;
|
|
75
|
+
Board: React.FC<PuzzleBoardProps>;
|
|
76
|
+
Reset: React.FC<React.PropsWithChildren<ResetProps>>;
|
|
77
|
+
Hint: React.FC<React.PropsWithChildren<HintProps>>;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
declare const useChessPuzzleContext: () => ChessPuzzleContextType;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Default theme for ChessPuzzle component.
|
|
84
|
+
* Extends the default game theme with puzzle-specific colors.
|
|
85
|
+
* These values match the original hardcoded colors for backward compatibility.
|
|
86
|
+
*/
|
|
87
|
+
declare const defaultPuzzleTheme: ChessPuzzleTheme;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Deep merges a partial puzzle theme with the default puzzle theme.
|
|
91
|
+
* Allows users to override only specific theme properties while keeping defaults for the rest.
|
|
92
|
+
*
|
|
93
|
+
* @param partialTheme - Partial theme with only the properties to override
|
|
94
|
+
* @returns Complete puzzle theme with overridden properties merged with defaults
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const customTheme = mergePuzzleTheme({
|
|
99
|
+
* puzzle: { hint: "rgba(0, 255, 255, 0.5)" }
|
|
100
|
+
* });
|
|
101
|
+
* // Returns full puzzle theme with only hint color changed
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
declare const mergePuzzleTheme: (partialTheme?: PartialChessPuzzleTheme) => ChessPuzzleTheme;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Context for ChessPuzzle theme
|
|
108
|
+
*/
|
|
109
|
+
declare const ChessPuzzleThemeContext: React__default.Context<ChessPuzzleTheme>;
|
|
110
|
+
/**
|
|
111
|
+
* Hook to access the current ChessPuzzle theme.
|
|
112
|
+
* Returns the default puzzle theme if no ThemeProvider is present.
|
|
113
|
+
*/
|
|
114
|
+
declare const useChessPuzzleTheme: () => ChessPuzzleTheme;
|
|
115
|
+
|
|
116
|
+
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,116 @@
|
|
|
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 {
|
|
37
|
+
asChild?: boolean;
|
|
38
|
+
showOn?: Status[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface ResetProps {
|
|
42
|
+
asChild?: boolean;
|
|
43
|
+
puzzle?: Puzzle;
|
|
44
|
+
onReset?: (puzzleContext: ChessPuzzleContextType) => void;
|
|
45
|
+
showOn?: Status[];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface PuzzleBoardProps extends React__default.ComponentProps<typeof ChessGame.Board> {
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
type ChessPuzzleContextType = {
|
|
52
|
+
status: Status;
|
|
53
|
+
changePuzzle: (puzzle: Puzzle) => void;
|
|
54
|
+
resetPuzzle: () => void;
|
|
55
|
+
puzzle: Puzzle;
|
|
56
|
+
hint: Hint;
|
|
57
|
+
nextMove?: string | null;
|
|
58
|
+
isPlayerTurn: boolean;
|
|
59
|
+
onHint: () => void;
|
|
60
|
+
puzzleState: Status;
|
|
61
|
+
movesPlayed: number;
|
|
62
|
+
totalMoves: number;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
interface RootProps {
|
|
66
|
+
puzzle: Puzzle;
|
|
67
|
+
onSolve?: (puzzleContext: ChessPuzzleContextType) => void;
|
|
68
|
+
onFail?: (puzzleContext: ChessPuzzleContextType) => void;
|
|
69
|
+
/** Optional theme configuration. Supports partial themes - only override the colors you need. */
|
|
70
|
+
theme?: PartialChessPuzzleTheme;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
declare const ChessPuzzle: {
|
|
74
|
+
Root: React.FC<React.PropsWithChildren<RootProps>>;
|
|
75
|
+
Board: React.FC<PuzzleBoardProps>;
|
|
76
|
+
Reset: React.FC<React.PropsWithChildren<ResetProps>>;
|
|
77
|
+
Hint: React.FC<React.PropsWithChildren<HintProps>>;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
declare const useChessPuzzleContext: () => ChessPuzzleContextType;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Default theme for ChessPuzzle component.
|
|
84
|
+
* Extends the default game theme with puzzle-specific colors.
|
|
85
|
+
* These values match the original hardcoded colors for backward compatibility.
|
|
86
|
+
*/
|
|
87
|
+
declare const defaultPuzzleTheme: ChessPuzzleTheme;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Deep merges a partial puzzle theme with the default puzzle theme.
|
|
91
|
+
* Allows users to override only specific theme properties while keeping defaults for the rest.
|
|
92
|
+
*
|
|
93
|
+
* @param partialTheme - Partial theme with only the properties to override
|
|
94
|
+
* @returns Complete puzzle theme with overridden properties merged with defaults
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const customTheme = mergePuzzleTheme({
|
|
99
|
+
* puzzle: { hint: "rgba(0, 255, 255, 0.5)" }
|
|
100
|
+
* });
|
|
101
|
+
* // Returns full puzzle theme with only hint color changed
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
declare const mergePuzzleTheme: (partialTheme?: PartialChessPuzzleTheme) => ChessPuzzleTheme;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Context for ChessPuzzle theme
|
|
108
|
+
*/
|
|
109
|
+
declare const ChessPuzzleThemeContext: React__default.Context<ChessPuzzleTheme>;
|
|
110
|
+
/**
|
|
111
|
+
* Hook to access the current ChessPuzzle theme.
|
|
112
|
+
* Returns the default puzzle theme if no ThemeProvider is present.
|
|
113
|
+
*/
|
|
114
|
+
declare const useChessPuzzleTheme: () => ChessPuzzleTheme;
|
|
115
|
+
|
|
116
|
+
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 };
|
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
// src/components/ChessPuzzle/parts/Root.tsx
|
|
2
|
-
import
|
|
2
|
+
import React4 from "react";
|
|
3
3
|
|
|
4
4
|
// src/utils/index.ts
|
|
5
5
|
import { Chess } from "chess.js";
|
|
6
6
|
import React from "react";
|
|
7
7
|
import _ from "lodash";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
|
|
9
|
+
// src/theme/defaults.ts
|
|
10
|
+
import { defaultGameTheme } from "@react-chess-tools/react-chess-game";
|
|
11
|
+
var defaultPuzzleTheme = {
|
|
12
|
+
...defaultGameTheme,
|
|
13
|
+
puzzle: {
|
|
14
|
+
success: "rgba(172, 206, 89, 0.5)",
|
|
15
|
+
failure: "rgba(201, 52, 48, 0.5)",
|
|
16
|
+
hint: "rgba(27, 172, 166, 0.5)"
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// src/utils/index.ts
|
|
11
21
|
var getOrientation = (puzzle) => {
|
|
12
22
|
const fen = puzzle.fen;
|
|
13
23
|
const game = new Chess(fen);
|
|
@@ -17,39 +27,39 @@ var getOrientation = (puzzle) => {
|
|
|
17
27
|
return game.turn();
|
|
18
28
|
};
|
|
19
29
|
var isClickableElement = (element) => React.isValidElement(element);
|
|
20
|
-
var getCustomSquareStyles = (status, hint, isPlayerTurn, game, nextMove) => {
|
|
30
|
+
var getCustomSquareStyles = (status, hint, isPlayerTurn, game, nextMove, theme = defaultPuzzleTheme) => {
|
|
21
31
|
const customSquareStyles = {};
|
|
22
32
|
const lastMove = _.last(game.history({ verbose: true }));
|
|
23
33
|
if (status === "failed" && lastMove) {
|
|
24
34
|
customSquareStyles[lastMove.from] = {
|
|
25
|
-
backgroundColor:
|
|
35
|
+
backgroundColor: theme.puzzle.failure
|
|
26
36
|
};
|
|
27
37
|
customSquareStyles[lastMove.to] = {
|
|
28
|
-
backgroundColor:
|
|
38
|
+
backgroundColor: theme.puzzle.failure
|
|
29
39
|
};
|
|
30
40
|
}
|
|
31
41
|
if (lastMove && (status === "solved" || status !== "failed" && !isPlayerTurn)) {
|
|
32
42
|
customSquareStyles[lastMove.from] = {
|
|
33
|
-
backgroundColor:
|
|
43
|
+
backgroundColor: theme.puzzle.success
|
|
34
44
|
};
|
|
35
45
|
customSquareStyles[lastMove.to] = {
|
|
36
|
-
backgroundColor:
|
|
46
|
+
backgroundColor: theme.puzzle.success
|
|
37
47
|
};
|
|
38
48
|
}
|
|
39
49
|
if (hint === "piece") {
|
|
40
50
|
if (nextMove) {
|
|
41
51
|
customSquareStyles[nextMove.from] = {
|
|
42
|
-
backgroundColor:
|
|
52
|
+
backgroundColor: theme.puzzle.hint
|
|
43
53
|
};
|
|
44
54
|
}
|
|
45
55
|
}
|
|
46
56
|
if (hint === "move") {
|
|
47
57
|
if (nextMove) {
|
|
48
58
|
customSquareStyles[nextMove.from] = {
|
|
49
|
-
backgroundColor:
|
|
59
|
+
backgroundColor: theme.puzzle.hint
|
|
50
60
|
};
|
|
51
61
|
customSquareStyles[nextMove.to] = {
|
|
52
|
-
backgroundColor:
|
|
62
|
+
backgroundColor: theme.puzzle.hint
|
|
53
63
|
};
|
|
54
64
|
}
|
|
55
65
|
}
|
|
@@ -291,27 +301,59 @@ var useChessPuzzleContext = () => {
|
|
|
291
301
|
return context;
|
|
292
302
|
};
|
|
293
303
|
|
|
304
|
+
// src/theme/context.tsx
|
|
305
|
+
import React3, { createContext, useContext } from "react";
|
|
306
|
+
var ChessPuzzleThemeContext = createContext(defaultPuzzleTheme);
|
|
307
|
+
var useChessPuzzleTheme = () => {
|
|
308
|
+
return useContext(ChessPuzzleThemeContext);
|
|
309
|
+
};
|
|
310
|
+
var PuzzleThemeProvider = ({
|
|
311
|
+
theme,
|
|
312
|
+
children
|
|
313
|
+
}) => {
|
|
314
|
+
return /* @__PURE__ */ React3.createElement(ChessPuzzleThemeContext.Provider, { value: theme }, children);
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
// src/theme/utils.ts
|
|
318
|
+
import { merge } from "lodash";
|
|
319
|
+
var mergePuzzleTheme = (partialTheme) => {
|
|
320
|
+
if (!partialTheme) {
|
|
321
|
+
return { ...defaultPuzzleTheme };
|
|
322
|
+
}
|
|
323
|
+
return merge({}, defaultPuzzleTheme, partialTheme);
|
|
324
|
+
};
|
|
325
|
+
|
|
294
326
|
// src/components/ChessPuzzle/parts/Root.tsx
|
|
295
|
-
var
|
|
327
|
+
var PuzzleRootInner = ({
|
|
296
328
|
puzzle,
|
|
297
329
|
onSolve,
|
|
298
330
|
onFail,
|
|
299
331
|
children
|
|
300
332
|
}) => {
|
|
301
333
|
const context = useChessPuzzle(puzzle, onSolve, onFail);
|
|
302
|
-
return /* @__PURE__ */
|
|
334
|
+
return /* @__PURE__ */ React4.createElement(ChessPuzzleContext.Provider, { value: context }, children);
|
|
303
335
|
};
|
|
304
336
|
var Root = ({
|
|
305
337
|
puzzle,
|
|
306
338
|
onSolve,
|
|
307
339
|
onFail,
|
|
340
|
+
theme,
|
|
308
341
|
children
|
|
309
342
|
}) => {
|
|
310
|
-
|
|
343
|
+
const mergedTheme = React4.useMemo(() => mergePuzzleTheme(theme), [theme]);
|
|
344
|
+
return /* @__PURE__ */ React4.createElement(
|
|
345
|
+
ChessGame.Root,
|
|
346
|
+
{
|
|
347
|
+
fen: puzzle.fen,
|
|
348
|
+
orientation: getOrientation(puzzle),
|
|
349
|
+
theme: mergedTheme
|
|
350
|
+
},
|
|
351
|
+
/* @__PURE__ */ React4.createElement(PuzzleThemeProvider, { theme: mergedTheme }, /* @__PURE__ */ React4.createElement(PuzzleRootInner, { puzzle, onSolve, onFail }, children))
|
|
352
|
+
);
|
|
311
353
|
};
|
|
312
354
|
|
|
313
355
|
// src/components/ChessPuzzle/parts/PuzzleBoard.tsx
|
|
314
|
-
import
|
|
356
|
+
import React5 from "react";
|
|
315
357
|
import {
|
|
316
358
|
ChessGame as ChessGame2,
|
|
317
359
|
deepMergeChessboardOptions,
|
|
@@ -323,6 +365,7 @@ var PuzzleBoard = ({
|
|
|
323
365
|
}) => {
|
|
324
366
|
const puzzleContext = useChessPuzzleContext();
|
|
325
367
|
const gameContext = useChessGameContext2();
|
|
368
|
+
const theme = useChessPuzzleTheme();
|
|
326
369
|
if (!puzzleContext) {
|
|
327
370
|
throw new Error("PuzzleContext not found");
|
|
328
371
|
}
|
|
@@ -337,14 +380,15 @@ var PuzzleBoard = ({
|
|
|
337
380
|
hint,
|
|
338
381
|
isPlayerTurn,
|
|
339
382
|
game,
|
|
340
|
-
stringToMove(game, nextMove)
|
|
383
|
+
stringToMove(game, nextMove),
|
|
384
|
+
theme
|
|
341
385
|
)
|
|
342
386
|
});
|
|
343
|
-
return /* @__PURE__ */
|
|
387
|
+
return /* @__PURE__ */ React5.createElement(ChessGame2.Board, { ...rest, options: mergedOptions });
|
|
344
388
|
};
|
|
345
389
|
|
|
346
390
|
// src/components/ChessPuzzle/parts/Reset.tsx
|
|
347
|
-
import
|
|
391
|
+
import React6 from "react";
|
|
348
392
|
var defaultShowOn = ["failed", "solved"];
|
|
349
393
|
var Reset = ({
|
|
350
394
|
children,
|
|
@@ -366,20 +410,20 @@ var Reset = ({
|
|
|
366
410
|
return null;
|
|
367
411
|
}
|
|
368
412
|
if (asChild) {
|
|
369
|
-
const child =
|
|
413
|
+
const child = React6.Children.only(children);
|
|
370
414
|
if (isClickableElement(child)) {
|
|
371
|
-
return
|
|
415
|
+
return React6.cloneElement(child, {
|
|
372
416
|
onClick: handleClick
|
|
373
417
|
});
|
|
374
418
|
} else {
|
|
375
419
|
throw new Error("Change child must be a clickable element");
|
|
376
420
|
}
|
|
377
421
|
}
|
|
378
|
-
return /* @__PURE__ */
|
|
422
|
+
return /* @__PURE__ */ React6.createElement("button", { type: "button", onClick: handleClick }, children);
|
|
379
423
|
};
|
|
380
424
|
|
|
381
425
|
// src/components/ChessPuzzle/parts/Hint.tsx
|
|
382
|
-
import
|
|
426
|
+
import React7 from "react";
|
|
383
427
|
var defaultShowOn2 = ["not-started", "in-progress"];
|
|
384
428
|
var Hint = ({
|
|
385
429
|
children,
|
|
@@ -398,16 +442,16 @@ var Hint = ({
|
|
|
398
442
|
return null;
|
|
399
443
|
}
|
|
400
444
|
if (asChild) {
|
|
401
|
-
const child =
|
|
445
|
+
const child = React7.Children.only(children);
|
|
402
446
|
if (isClickableElement(child)) {
|
|
403
|
-
return
|
|
447
|
+
return React7.cloneElement(child, {
|
|
404
448
|
onClick: handleClick
|
|
405
449
|
});
|
|
406
450
|
} else {
|
|
407
451
|
throw new Error("Change child must be a clickable element");
|
|
408
452
|
}
|
|
409
453
|
}
|
|
410
|
-
return /* @__PURE__ */
|
|
454
|
+
return /* @__PURE__ */ React7.createElement("button", { type: "button", onClick: handleClick }, children);
|
|
411
455
|
};
|
|
412
456
|
|
|
413
457
|
// src/components/ChessPuzzle/index.ts
|
|
@@ -419,6 +463,10 @@ var ChessPuzzle = {
|
|
|
419
463
|
};
|
|
420
464
|
export {
|
|
421
465
|
ChessPuzzle,
|
|
422
|
-
|
|
466
|
+
ChessPuzzleThemeContext,
|
|
467
|
+
defaultPuzzleTheme,
|
|
468
|
+
mergePuzzleTheme,
|
|
469
|
+
useChessPuzzleContext,
|
|
470
|
+
useChessPuzzleTheme
|
|
423
471
|
};
|
|
424
|
-
//# sourceMappingURL=index.
|
|
472
|
+
//# 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","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\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\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.FC<PuzzleBoardProps> = ({\n options = {},\n ...rest\n}) => {\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 {...rest} options={mergedOptions} />;\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":";AAAA,OAAOA,YAAW;;;ACAlB,SAAqB,aAAmB;AACxC,OAAO,WAAuD;AAC9D,OAAO,OAAO;;;ACFd,SAAS,wBAAwB;AAQ1B,IAAM,qBAAuC;AAAA,EAClD,GAAG;AAAA,EACH,QAAQ;AAAA,IACN,SAAS;AAAA,IACT,SAAS;AAAA,IACT,MAAM;AAAA,EACR;AACF;;;ADEO,IAAM,iBAAiB,CAAC,WAA0B;AACvD,QAAM,MAAM,OAAO;AACnB,QAAM,OAAO,IAAI,MAAM,GAAG;AAC1B,MAAI,OAAO,eAAe;AACxB,SAAK,KAAK,OAAO,MAAM,CAAC,CAAC;AAAA,EAC3B;AACA,SAAO,KAAK,KAAK;AACnB;AAQO,IAAM,qBAAqB,CAChC,YACgC,MAAM,eAAe,OAAO;AAavD,IAAM,wBAAwB,CACnC,QACA,MACA,cACA,MACA,UACA,QAA0B,uBACvB;AACH,QAAM,qBAAoD,CAAC;AAE3D,QAAM,WAAW,EAAE,KAAK,KAAK,QAAQ,EAAE,SAAS,KAAK,CAAC,CAAC;AAEvD,MAAI,WAAW,YAAY,UAAU;AACnC,uBAAmB,SAAS,IAAI,IAAI;AAAA,MAClC,iBAAiB,MAAM,OAAO;AAAA,IAChC;AACA,uBAAmB,SAAS,EAAE,IAAI;AAAA,MAChC,iBAAiB,MAAM,OAAO;AAAA,IAChC;AAAA,EACF;AAEA,MACE,aACC,WAAW,YAAa,WAAW,YAAY,CAAC,eACjD;AACA,uBAAmB,SAAS,IAAI,IAAI;AAAA,MAClC,iBAAiB,MAAM,OAAO;AAAA,IAChC;AACA,uBAAmB,SAAS,EAAE,IAAI;AAAA,MAChC,iBAAiB,MAAM,OAAO;AAAA,IAChC;AAAA,EACF;AAEA,MAAI,SAAS,SAAS;AACpB,QAAI,UAAU;AACZ,yBAAmB,SAAS,IAAI,IAAI;AAAA,QAClC,iBAAiB,MAAM,OAAO;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,SAAS,QAAQ;AACnB,QAAI,UAAU;AACZ,yBAAmB,SAAS,IAAI,IAAI;AAAA,QAClC,iBAAiB,MAAM,OAAO;AAAA,MAChC;AACA,yBAAmB,SAAS,EAAE,IAAI;AAAA,QAChC,iBAAiB,MAAM,OAAO;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,IAAM,eAAe,CAAC,MAAa,SAAoC;AAC5E,QAAM,OAAO,IAAI,MAAM,KAAK,IAAI,CAAC;AACjC,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WAAO;AAAA,EACT;AACA,MAAI;AACF,WAAO,KAAK,KAAK,IAAI;AAAA,EACvB,SAAS,GAAG;AACV,WAAO;AAAA,EACT;AACF;;;AEhHA,SAAS,WAAW,YAAY,aAAa,eAAe;;;AC0CrD,IAAM,mBAAmB,CAAC,EAAE,OAAO,MAAiC;AACzE,SAAO;AAAA,IACL;AAAA,IACA,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,UAAU,OAAO,MAAM,CAAC;AAAA,IACxB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa,CAAC,CAAC,OAAO;AAAA,IACtB,cAAc,CAAC,OAAO;AAAA,IACtB,gBAAgB;AAAA,IAChB,eAAe;AAAA,EACjB;AACF;AAEO,IAAM,UAAU,CAAC,OAAc,WAA0B;AAC9D,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,GAAG,iBAAiB,OAAO,OAAO;AAAA,MACpC;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,GAAG,iBAAiB;AAAA,UAClB,QAAQ,MAAM;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,IACF,KAAK;AACH,UAAI,MAAM,SAAS,QAAQ;AACzB,eAAO,EAAE,GAAG,OAAO,MAAM,QAAQ;AAAA,MACnC;AACA,aAAO,EAAE,GAAG,OAAO,MAAM,OAAO;AAAA,IAClC,KAAK;AACH,UAAI,MAAM,cAAc;AACtB,eAAO;AAAA,MACT;AACA,UAAI,CAAC,UAAU,QAAQ,EAAE,SAAS,MAAM,MAAM,GAAG;AAC/C,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,QACL,GAAG;AAAA,QACH,kBAAkB,MAAM,mBAAmB;AAAA,QAC3C,SAAS,MAAM,OAAO,MAAM,MAAM,gBAAgB;AAAA,QAClD,UACE,MAAM,mBAAmB,MAAM,OAAO,MAAM,SAAS,IACjD,MAAM,OAAO,MAAM,MAAM,mBAAmB,CAAC,IAC7C;AAAA,QACN,aAAa;AAAA,QACb,cAAc;AAAA,QACd,QAAQ;AAAA,MACV;AAAA,IAEF,KAAK,eAAe;AAClB,YAAM,EAAE,KAAK,IAAI,OAAO;AAExB,YAAM,cAAc,CAAC,6BAAM,KAAK,6BAAM,GAAG,EAAE;AAAA,SACzC,+BAAO,aAAY;AAAA,MACrB;AACA,YAAM,iBACJ,MAAM,qBAAqB,MAAM,OAAO,MAAM,SAAS;AAEzD,UAAI,CAAC,aAAa;AAChB,eAAO;AAAA,UACL,GAAG;AAAA,UACH,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,MAAM;AAAA,UACN,cAAc;AAAA,UACd,eAAe;AAAA,QACjB;AAAA,MACF;AAEA,UAAI,gBAAgB;AAClB,eAAO;AAAA,UACL,GAAG;AAAA,UACH,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,MAAM;AAAA,UACN,cAAc;AAAA,UACd,gBAAgB;AAAA,QAClB;AAAA,MACF;AAEA,aAAO;AAAA,QACL,GAAG;AAAA,QACH,MAAM;AAAA,QACN,kBAAkB,MAAM,mBAAmB;AAAA,QAC3C,UAAU,MAAM,OAAO,MAAM,MAAM,mBAAmB,CAAC;AAAA,QACvD,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,cAAc;AAAA,MAChB;AAAA,IACF;AAAA,IAEA,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,gBAAgB;AAAA,MAClB;AAAA,IAEF,KAAK;AACH,aAAO;AAAA,QACL,GAAG;AAAA,QACH,eAAe;AAAA,MACjB;AAAA,IAEF;AACE,aAAO;AAAA,EACX;AACF;;;ADvJA,SAAS,2BAA2B;AAgB7B,IAAM,iBAAiB,CAC5B,QACA,SACA,WAC2B;AAvB7B;AAwBE,QAAM,cAAc,oBAAoB;AAExC,QAAM,CAAC,OAAO,QAAQ,IAAI,WAAW,SAAS,EAAE,OAAO,GAAG,gBAAgB;AAE1E,QAAM;AAAA,IACJ;AAAA,IACA,SAAS,EAAE,UAAU,YAAY;AAAA,EACnC,IAAI;AAEJ,QAAM,eAAe;AAAA,IACnB,CAACC,YAAmB;AAClB,kBAAYA,QAAO,KAAK,eAAeA,OAAM,CAAC;AAC9C,eAAS,EAAE,MAAM,cAAc,SAAS,EAAE,QAAAA,QAAO,EAAE,CAAC;AAAA,IACtD;AAAA,IACA,CAAC,WAAW;AAAA,EACd;AAEA,YAAU,MAAM;AACd,iBAAa,MAAM;AAAA,EACrB,GAAG,CAAC,KAAK,UAAU,MAAM,GAAG,YAAY,CAAC;AAEzC,YAAU,MAAM;AACd,QAAI,eAAe,KAAK,IAAI,MAAM,OAAO,OAAO,MAAM,aAAa;AACjE;AAAA,QACE,MACE,SAAS;AAAA,UACP,MAAM;AAAA,QACR,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG,CAAC,aAAa,MAAM,WAAW,CAAC;AAEnC,YAAU,MAAM;AACd,QAAI,MAAM,SAAS;AACjB,eAAS,MAAM,OAAO;AAAA,IACxB;AAAA,EACF,GAAG,CAAC,MAAM,OAAO,CAAC;AAElB,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AAEA,QAAM,SAAS,YAAY,MAAM;AAC/B,aAAS,EAAE,MAAM,cAAc,CAAC;AAAA,EAClC,GAAG,CAAC,CAAC;AAEL,QAAM,cAAc,YAAY,MAAM;AACpC,iBAAa,MAAM;AAAA,EACrB,GAAG,CAAC,cAAc,MAAM,CAAC;AAEzB,QAAM,gBAAwC;AAAA,IAC5C,OAAO;AAAA,MACL,QAAQ,MAAM;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,MAAM;AAAA,MACZ;AAAA,MACA,UAAU,MAAM;AAAA,MAChB,cAAc,MAAM;AAAA,MACpB,aAAa,MAAM;AAAA,MACnB,aAAa,MAAM;AAAA,MACnB,YAAY,OAAO,MAAM;AAAA,IAC3B;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AAEA,YAAU,MAAM;AAtGlB,QAAAC,KAAA;AAuGI,UAAIA,MAAA,6BAAM,cAAN,gBAAAA,IAAiB,WAAU,KAAK,OAAO,gBAAgB,IAAI,IAAI;AACjE;AAAA,IACF;AACA,QAAI,KAAK,QAAQ,EAAE,SAAS,OAAO,OAAO,gBAAgB,IAAI,IAAI;AAChE,eAAS;AAAA,QACP,MAAM;AAAA,QACN,SAAS;AAAA,UACP,QAAM,sDAAa,SAAb,mBAAmB,QAAQ,EAAE,SAAS,KAAK,OAA3C,mBAA+C,UAAS;AAAA,UAC9D;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAED,eAAS;AAAA,QACP,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AAAA,EACF,GAAG,EAAC,kCAAM,cAAN,mBAAiB,MAAM,CAAC;AAE5B,YAAU,MAAM;AACd,QAAI,MAAM,WAAW,YAAY,CAAC,MAAM,kBAAkB,SAAS;AACjE,cAAQ,aAAa;AACrB,eAAS,EAAE,MAAM,qBAAqB,CAAC;AAAA,IACzC;AAAA,EACF,GAAG,CAAC,MAAM,QAAQ,MAAM,cAAc,CAAC;AAEvC,YAAU,MAAM;AACd,QAAI,MAAM,WAAW,YAAY,CAAC,MAAM,iBAAiB,QAAQ;AAC/D,aAAO,aAAa;AACpB,eAAS,EAAE,MAAM,oBAAoB,CAAC;AAAA,IACxC;AAAA,EACF,GAAG,CAAC,MAAM,QAAQ,MAAM,aAAa,CAAC;AAEtC,SAAO;AACT;;;AHnIA,SAAS,iBAAiB;;;AKN1B,OAAOC,YAAW;AAGX,IAAM,qBAAqBA,OAAM,cAE9B,IAAI;AAEP,IAAM,wBAAwB,MAAM;AACzC,QAAM,UAAUA,OAAM,WAAW,kBAAkB;AACnD,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;;;ACfA,OAAOC,UAAS,eAAe,kBAAkB;AAO1C,IAAM,0BACX,cAAgC,kBAAkB;AAM7C,IAAM,sBAAsB,MAAwB;AACzD,SAAO,WAAW,uBAAuB;AAC3C;AAUO,IAAM,sBAA0D,CAAC;AAAA,EACtE;AAAA,EACA;AACF,MAAM;AACJ,SACE,gBAAAC,OAAA,cAAC,wBAAwB,UAAxB,EAAiC,OAAO,SACtC,QACH;AAEJ;;;ACnCA,SAAS,aAAa;AAmBf,IAAM,mBAAmB,CAC9B,iBACqB;AACrB,MAAI,CAAC,cAAc;AACjB,WAAO,EAAE,GAAG,mBAAmB;AAAA,EACjC;AAEA,SAAO,MAAM,CAAC,GAAG,oBAAoB,YAAY;AACnD;;;APAA,IAAM,kBAAkD,CAAC;AAAA,EACvD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,UAAU,eAAe,QAAQ,SAAS,MAAM;AAEtD,SACE,gBAAAC,OAAA,cAAC,mBAAmB,UAAnB,EAA4B,OAAO,WACjC,QACH;AAEJ;AAEO,IAAM,OAAqD,CAAC;AAAA,EACjE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AAEJ,QAAM,cAAcA,OAAM,QAAQ,MAAM,iBAAiB,KAAK,GAAG,CAAC,KAAK,CAAC;AAExE,SACE,gBAAAA,OAAA;AAAA,IAAC,UAAU;AAAA,IAAV;AAAA,MACC,KAAK,OAAO;AAAA,MACZ,aAAa,eAAe,MAAM;AAAA,MAClC,OAAO;AAAA;AAAA,IAEP,gBAAAA,OAAA,cAAC,uBAAoB,OAAO,eAC1B,gBAAAA,OAAA,cAAC,mBAAgB,QAAgB,SAAkB,UAChD,QACH,CACF;AAAA,EACF;AAEJ;;;AQjEA,OAAOC,YAAW;AAClB;AAAA,EACE,aAAAC;AAAA,EACA;AAAA,EACA,uBAAAC;AAAA,OACK;AASA,IAAM,cAA0C,CAAC;AAAA,EACtD,UAAU,CAAC;AAAA,EACX,GAAG;AACL,MAAM;AACJ,QAAM,gBAAgB,sBAAsB;AAC5C,QAAM,cAAcC,qBAAoB;AACxC,QAAM,QAAQ,oBAAoB;AAElC,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AACA,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI,MAAM,4BAA4B;AAAA,EAC9C;AAEA,QAAM,EAAE,KAAK,IAAI;AACjB,QAAM,EAAE,QAAQ,MAAM,cAAc,SAAS,IAAI;AAEjD,QAAM,gBAAgB,2BAA2B,SAAS;AAAA,IACxD,cAAc;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,MAAM,QAAQ;AAAA,MAC3B;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO,gBAAAC,OAAA,cAACC,WAAU,OAAV,EAAiB,GAAG,MAAM,SAAS,eAAe;AAC5D;;;AC5CA,OAAOC,YAAW;AAWlB,IAAM,gBAA0B,CAAC,UAAU,QAAQ;AAE5C,IAAM,QAAuD,CAAC;AAAA,EACnE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AACX,MAAM;AACJ,QAAM,gBAAgB,sBAAsB;AAC5C,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AACA,QAAM,EAAE,cAAc,OAAO,IAAI;AACjC,QAAM,cAAc,MAAM;AACxB,iBAAa,UAAU,cAAc,MAAM;AAC3C,uCAAU;AAAA,EACZ;AAEA,MAAI,CAAC,OAAO,SAAS,MAAM,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,MAAI,SAAS;AACX,UAAM,QAAQC,OAAM,SAAS,KAAK,QAAQ;AAC1C,QAAI,mBAAmB,KAAK,GAAG;AAC7B,aAAOA,OAAM,aAAa,OAAO;AAAA,QAC/B,SAAS;AAAA,MACX,CAAC;AAAA,IACH,OAAO;AACL,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AAAA,EACF;AAEA,SACE,gBAAAA,OAAA,cAAC,YAAO,MAAK,UAAS,SAAS,eAC5B,QACH;AAEJ;;;AClDA,OAAOC,YAAW;AASlB,IAAMC,iBAA0B,CAAC,eAAe,aAAa;AAEtD,IAAM,OAAqD,CAAC;AAAA,EACjE;AAAA,EACA;AAAA,EACA,SAASA;AACX,MAAM;AACJ,QAAM,gBAAgB,sBAAsB;AAC5C,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AACA,QAAM,EAAE,QAAQ,OAAO,IAAI;AAC3B,QAAM,cAAc,MAAM;AACxB,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,OAAO,SAAS,MAAM,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,MAAI,SAAS;AACX,UAAM,QAAQC,OAAM,SAAS,KAAK,QAAQ;AAC1C,QAAI,mBAAmB,KAAK,GAAG;AAC7B,aAAOA,OAAM,aAAa,OAAO;AAAA,QAC/B,SAAS;AAAA,MACX,CAAC;AAAA,IACH,OAAO;AACL,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AAAA,EACF;AAEA,SACE,gBAAAA,OAAA,cAAC,YAAO,MAAK,UAAS,SAAS,eAC5B,QACH;AAEJ;;;ACxCO,IAAM,cAAc;AAAA,EACzB;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AACF;","names":["React","puzzle","_a","React","React","React","React","React","ChessGame","useChessGameContext","useChessGameContext","React","ChessGame","React","React","React","defaultShowOn","React"]}
|
package/package.json
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-chess-tools/react-chess-puzzle",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "A lightweight, customizable React component library for rendering and interacting with chess puzzles.",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"require": "./dist/index.cjs",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"main": "./dist/index.cjs",
|
|
15
|
+
"module": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
8
17
|
"scripts": {
|
|
9
18
|
"build": "tsup src/index.ts",
|
|
10
19
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -32,14 +41,14 @@
|
|
|
32
41
|
"author": "Daniele Cammareri <daniele.cammareri@gmail.com>",
|
|
33
42
|
"license": "MIT",
|
|
34
43
|
"dependencies": {
|
|
35
|
-
"@react-chess-tools/react-chess-game": "0.
|
|
36
|
-
"chess.js": "^1.
|
|
44
|
+
"@react-chess-tools/react-chess-game": "1.0.0",
|
|
45
|
+
"chess.js": "^1.4.0",
|
|
37
46
|
"lodash": "^4.17.21"
|
|
38
47
|
},
|
|
39
48
|
"devDependencies": {
|
|
40
|
-
"@types/lodash": "^4.17.
|
|
41
|
-
"react": "^19.
|
|
42
|
-
"react-dom": "^19.
|
|
49
|
+
"@types/lodash": "^4.17.21",
|
|
50
|
+
"react": "^19.2.3",
|
|
51
|
+
"react-dom": "^19.2.3"
|
|
43
52
|
},
|
|
44
53
|
"peerDependencies": {
|
|
45
54
|
"react": ">=16.14.0",
|