@react-chess-tools/react-chess-puzzle 1.0.2 → 1.0.3
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
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-chess-tools/react-chess-puzzle",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "A lightweight, customizable React component library for rendering and interacting with chess puzzles.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"license": "MIT",
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@radix-ui/react-slot": "^1.2.4",
|
|
45
|
-
"@react-chess-tools/react-chess-game": "1.0.
|
|
45
|
+
"@react-chess-tools/react-chess-game": "1.0.2",
|
|
46
46
|
"chess.js": "^1.4.0",
|
|
47
47
|
"lodash": "^4.17.21"
|
|
48
48
|
},
|
|
@@ -18,6 +18,105 @@ const puzzles = [
|
|
|
18
18
|
},
|
|
19
19
|
];
|
|
20
20
|
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Shared Story Styles
|
|
23
|
+
// ============================================================================
|
|
24
|
+
const storyStyles = {
|
|
25
|
+
container: {
|
|
26
|
+
display: "flex",
|
|
27
|
+
flexDirection: "column" as const,
|
|
28
|
+
alignItems: "center",
|
|
29
|
+
gap: "20px",
|
|
30
|
+
padding: "24px",
|
|
31
|
+
backgroundColor: "#f8f9fa",
|
|
32
|
+
borderRadius: "12px",
|
|
33
|
+
maxWidth: "500px",
|
|
34
|
+
margin: "0 auto",
|
|
35
|
+
},
|
|
36
|
+
header: {
|
|
37
|
+
display: "flex",
|
|
38
|
+
flexDirection: "column" as const,
|
|
39
|
+
alignItems: "center",
|
|
40
|
+
gap: "8px",
|
|
41
|
+
},
|
|
42
|
+
title: {
|
|
43
|
+
fontSize: "22px",
|
|
44
|
+
fontWeight: 700,
|
|
45
|
+
color: "#2c3e50",
|
|
46
|
+
margin: 0,
|
|
47
|
+
textAlign: "center" as const,
|
|
48
|
+
},
|
|
49
|
+
subtitle: {
|
|
50
|
+
fontSize: "14px",
|
|
51
|
+
color: "#6c757d",
|
|
52
|
+
margin: 0,
|
|
53
|
+
textAlign: "center" as const,
|
|
54
|
+
},
|
|
55
|
+
boardWrapper: {
|
|
56
|
+
backgroundColor: "#fff",
|
|
57
|
+
padding: "16px",
|
|
58
|
+
borderRadius: "10px",
|
|
59
|
+
boxShadow: "0 2px 12px rgba(0,0,0,0.08)",
|
|
60
|
+
},
|
|
61
|
+
controlsSection: {
|
|
62
|
+
display: "flex",
|
|
63
|
+
gap: "10px",
|
|
64
|
+
justifyContent: "center",
|
|
65
|
+
flexWrap: "wrap" as const,
|
|
66
|
+
},
|
|
67
|
+
button: {
|
|
68
|
+
padding: "10px 20px",
|
|
69
|
+
fontSize: "14px",
|
|
70
|
+
fontWeight: 600,
|
|
71
|
+
cursor: "pointer",
|
|
72
|
+
border: "none",
|
|
73
|
+
borderRadius: "8px",
|
|
74
|
+
backgroundColor: "#fff",
|
|
75
|
+
boxShadow: "0 2px 6px rgba(0,0,0,0.08)",
|
|
76
|
+
color: "#495057",
|
|
77
|
+
transition: "all 0.2s ease",
|
|
78
|
+
} as React.CSSProperties,
|
|
79
|
+
buttonPrimary: {
|
|
80
|
+
backgroundColor: "#4dabf7",
|
|
81
|
+
color: "#fff",
|
|
82
|
+
boxShadow: "0 2px 6px rgba(77, 171, 247, 0.3)",
|
|
83
|
+
} as React.CSSProperties,
|
|
84
|
+
buttonSuccess: {
|
|
85
|
+
backgroundColor: "#51cf66",
|
|
86
|
+
color: "#fff",
|
|
87
|
+
boxShadow: "0 2px 6px rgba(81, 207, 102, 0.3)",
|
|
88
|
+
} as React.CSSProperties,
|
|
89
|
+
hintButton: {
|
|
90
|
+
padding: "8px 16px",
|
|
91
|
+
fontSize: "13px",
|
|
92
|
+
fontWeight: 500,
|
|
93
|
+
cursor: "pointer",
|
|
94
|
+
border: "1px dashed #adb5bd",
|
|
95
|
+
borderRadius: "8px",
|
|
96
|
+
backgroundColor: "transparent",
|
|
97
|
+
color: "#868e96",
|
|
98
|
+
} as React.CSSProperties,
|
|
99
|
+
infoBox: {
|
|
100
|
+
padding: "12px 16px",
|
|
101
|
+
backgroundColor: "#e7f5ff",
|
|
102
|
+
borderRadius: "8px",
|
|
103
|
+
fontSize: "13px",
|
|
104
|
+
color: "#1864ab",
|
|
105
|
+
textAlign: "center" as const,
|
|
106
|
+
},
|
|
107
|
+
statusBadge: {
|
|
108
|
+
display: "inline-flex",
|
|
109
|
+
alignItems: "center",
|
|
110
|
+
gap: "6px",
|
|
111
|
+
padding: "6px 14px",
|
|
112
|
+
fontSize: "12px",
|
|
113
|
+
fontWeight: 600,
|
|
114
|
+
backgroundColor: "#e9ecef",
|
|
115
|
+
borderRadius: "20px",
|
|
116
|
+
color: "#495057",
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
21
120
|
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
|
|
22
121
|
const meta = {
|
|
23
122
|
title: "react-chess-puzzle/Components/Puzzle",
|
|
@@ -29,15 +128,8 @@ const meta = {
|
|
|
29
128
|
},
|
|
30
129
|
parameters: {
|
|
31
130
|
actions: { argTypesRegex: "^_on.*" },
|
|
131
|
+
layout: "centered",
|
|
32
132
|
},
|
|
33
|
-
decorators: [
|
|
34
|
-
(Story) => (
|
|
35
|
-
<div style={{ width: "400px" }}>
|
|
36
|
-
{/* 👇 Decorators in Storybook also accept a function. Replace <Story/> with Story() to enable it */}
|
|
37
|
-
<Story />
|
|
38
|
-
</div>
|
|
39
|
-
),
|
|
40
|
-
],
|
|
41
133
|
} satisfies Meta<typeof ChessPuzzle.Root>;
|
|
42
134
|
|
|
43
135
|
export default meta;
|
|
@@ -48,49 +140,70 @@ export const Example = (args: RootProps) => {
|
|
|
48
140
|
const [puzzleIndex, setPuzzleIndex] = React.useState(0);
|
|
49
141
|
const puzzle = puzzles[puzzleIndex];
|
|
50
142
|
return (
|
|
51
|
-
<
|
|
52
|
-
<
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
143
|
+
<ChessPuzzle.Root {...args} puzzle={puzzle}>
|
|
144
|
+
<div style={storyStyles.container}>
|
|
145
|
+
<div style={storyStyles.header}>
|
|
146
|
+
<h3 style={storyStyles.title}>Chess Puzzle</h3>
|
|
147
|
+
<p style={storyStyles.subtitle}>Find the best move sequence</p>
|
|
148
|
+
<span style={storyStyles.statusBadge}>
|
|
149
|
+
Puzzle {puzzleIndex + 1} of {puzzles.length}
|
|
150
|
+
</span>
|
|
151
|
+
</div>
|
|
152
|
+
<div style={storyStyles.boardWrapper}>
|
|
153
|
+
<ChessPuzzle.Board />
|
|
154
|
+
</div>
|
|
155
|
+
<div style={storyStyles.controlsSection}>
|
|
156
|
+
<ChessPuzzle.Reset asChild>
|
|
157
|
+
<button style={storyStyles.button}>Restart</button>
|
|
158
|
+
</ChessPuzzle.Reset>
|
|
159
|
+
<ChessPuzzle.Reset
|
|
160
|
+
asChild
|
|
161
|
+
puzzle={puzzles[(puzzleIndex + 1) % puzzles.length]}
|
|
162
|
+
onReset={() => setPuzzleIndex((puzzleIndex + 1) % puzzles.length)}
|
|
163
|
+
>
|
|
164
|
+
<button
|
|
165
|
+
style={{ ...storyStyles.button, ...storyStyles.buttonPrimary }}
|
|
166
|
+
>
|
|
167
|
+
Next Puzzle
|
|
168
|
+
</button>
|
|
169
|
+
</ChessPuzzle.Reset>
|
|
170
|
+
<ChessPuzzle.Hint style={storyStyles.hintButton}>
|
|
171
|
+
💡 Hint
|
|
172
|
+
</ChessPuzzle.Hint>
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
</ChessPuzzle.Root>
|
|
67
176
|
);
|
|
68
177
|
};
|
|
69
178
|
|
|
70
179
|
export const WithOrientation = (args: RootProps) => {
|
|
71
|
-
const [puzzleIndex, setPuzzleIndex] = React.useState(0);
|
|
72
180
|
const puzzle = {
|
|
73
181
|
fen: "4kbnr/2p1pp1p/pp4p1/5b2/8/2NB1N2/PP3PPP/RKB4R b k - 0 1",
|
|
74
182
|
makeFirstMove: false,
|
|
75
183
|
moves: ["Bxd3"],
|
|
76
184
|
};
|
|
77
185
|
return (
|
|
78
|
-
<
|
|
79
|
-
<
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
<
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
>
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
186
|
+
<ChessPuzzle.Root {...args} puzzle={puzzle}>
|
|
187
|
+
<div style={storyStyles.container}>
|
|
188
|
+
<div style={storyStyles.header}>
|
|
189
|
+
<h3 style={storyStyles.title}>Black to Move</h3>
|
|
190
|
+
<p style={storyStyles.subtitle}>
|
|
191
|
+
Board oriented from Black's perspective
|
|
192
|
+
</p>
|
|
193
|
+
</div>
|
|
194
|
+
<div style={storyStyles.boardWrapper}>
|
|
195
|
+
<ChessPuzzle.Board options={{ boardOrientation: "black" }} />
|
|
196
|
+
</div>
|
|
197
|
+
<div style={storyStyles.controlsSection}>
|
|
198
|
+
<ChessPuzzle.Reset asChild>
|
|
199
|
+
<button style={storyStyles.button}>Restart</button>
|
|
200
|
+
</ChessPuzzle.Reset>
|
|
201
|
+
<ChessPuzzle.Hint style={storyStyles.hintButton}>
|
|
202
|
+
💡 Hint
|
|
203
|
+
</ChessPuzzle.Hint>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
</ChessPuzzle.Root>
|
|
94
207
|
);
|
|
95
208
|
};
|
|
96
209
|
|
|
@@ -101,14 +214,31 @@ export const Underpromotion = (args: RootProps) => {
|
|
|
101
214
|
makeFirstMove: true,
|
|
102
215
|
};
|
|
103
216
|
return (
|
|
104
|
-
<
|
|
105
|
-
<
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
<
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
217
|
+
<ChessPuzzle.Root {...args} puzzle={puzzle}>
|
|
218
|
+
<div style={storyStyles.container}>
|
|
219
|
+
<div style={storyStyles.header}>
|
|
220
|
+
<h3 style={storyStyles.title}>Underpromotion Challenge</h3>
|
|
221
|
+
<p style={storyStyles.subtitle}>
|
|
222
|
+
Promote to a knight instead of a queen
|
|
223
|
+
</p>
|
|
224
|
+
</div>
|
|
225
|
+
<div style={storyStyles.boardWrapper}>
|
|
226
|
+
<ChessPuzzle.Board />
|
|
227
|
+
</div>
|
|
228
|
+
<div style={storyStyles.controlsSection}>
|
|
229
|
+
<ChessPuzzle.Reset asChild>
|
|
230
|
+
<button
|
|
231
|
+
style={{ ...storyStyles.button, ...storyStyles.buttonSuccess }}
|
|
232
|
+
>
|
|
233
|
+
✓ Solved! Restart
|
|
234
|
+
</button>
|
|
235
|
+
</ChessPuzzle.Reset>
|
|
236
|
+
</div>
|
|
237
|
+
<div style={storyStyles.infoBox}>
|
|
238
|
+
Sometimes promoting to a knight is better than a queen!
|
|
239
|
+
</div>
|
|
240
|
+
</div>
|
|
241
|
+
</ChessPuzzle.Root>
|
|
112
242
|
);
|
|
113
243
|
};
|
|
114
244
|
|
|
@@ -116,7 +246,18 @@ export const WithSounds = (args: RootProps) => {
|
|
|
116
246
|
return (
|
|
117
247
|
<ChessPuzzle.Root {...args} puzzle={puzzles[0]}>
|
|
118
248
|
<ChessGame.Sounds />
|
|
119
|
-
<
|
|
249
|
+
<div style={storyStyles.container}>
|
|
250
|
+
<div style={storyStyles.header}>
|
|
251
|
+
<h3 style={storyStyles.title}>Puzzle with Sound</h3>
|
|
252
|
+
<p style={storyStyles.subtitle}>Audio feedback on every move</p>
|
|
253
|
+
</div>
|
|
254
|
+
<div style={storyStyles.boardWrapper}>
|
|
255
|
+
<ChessPuzzle.Board />
|
|
256
|
+
</div>
|
|
257
|
+
<p style={{ fontSize: "12px", color: "#868e96", textAlign: "center" }}>
|
|
258
|
+
Move pieces to hear different sounds
|
|
259
|
+
</p>
|
|
260
|
+
</div>
|
|
120
261
|
</ChessPuzzle.Root>
|
|
121
262
|
);
|
|
122
263
|
};
|
|
@@ -133,7 +274,145 @@ export const WithKeyboardControls = (args: RootProps) => {
|
|
|
133
274
|
d: (context) => context.methods.goToNextMove(),
|
|
134
275
|
}}
|
|
135
276
|
/>
|
|
136
|
-
<
|
|
277
|
+
<div style={storyStyles.container}>
|
|
278
|
+
<div style={storyStyles.header}>
|
|
279
|
+
<h3 style={storyStyles.title}>Keyboard Navigation</h3>
|
|
280
|
+
<p style={storyStyles.subtitle}>Use keyboard shortcuts to navigate</p>
|
|
281
|
+
</div>
|
|
282
|
+
<div style={storyStyles.boardWrapper}>
|
|
283
|
+
<ChessPuzzle.Board />
|
|
284
|
+
</div>
|
|
285
|
+
<div
|
|
286
|
+
style={{
|
|
287
|
+
display: "grid",
|
|
288
|
+
gridTemplateColumns: "repeat(3, auto)",
|
|
289
|
+
gap: "8px",
|
|
290
|
+
justifyContent: "center",
|
|
291
|
+
marginTop: "12px",
|
|
292
|
+
}}
|
|
293
|
+
>
|
|
294
|
+
<div
|
|
295
|
+
style={{
|
|
296
|
+
display: "flex",
|
|
297
|
+
alignItems: "center",
|
|
298
|
+
gap: "6px",
|
|
299
|
+
fontSize: "12px",
|
|
300
|
+
color: "#495057",
|
|
301
|
+
}}
|
|
302
|
+
>
|
|
303
|
+
<kbd
|
|
304
|
+
style={{
|
|
305
|
+
padding: "2px 8px",
|
|
306
|
+
backgroundColor: "#e9ecef",
|
|
307
|
+
border: "1px solid #ced4da",
|
|
308
|
+
borderRadius: "4px",
|
|
309
|
+
fontFamily: "monospace",
|
|
310
|
+
fontSize: "11px",
|
|
311
|
+
fontWeight: 600,
|
|
312
|
+
}}
|
|
313
|
+
>
|
|
314
|
+
W
|
|
315
|
+
</kbd>{" "}
|
|
316
|
+
Start
|
|
317
|
+
</div>
|
|
318
|
+
<div
|
|
319
|
+
style={{
|
|
320
|
+
display: "flex",
|
|
321
|
+
alignItems: "center",
|
|
322
|
+
gap: "6px",
|
|
323
|
+
fontSize: "12px",
|
|
324
|
+
color: "#495057",
|
|
325
|
+
}}
|
|
326
|
+
>
|
|
327
|
+
<kbd
|
|
328
|
+
style={{
|
|
329
|
+
padding: "2px 8px",
|
|
330
|
+
backgroundColor: "#e9ecef",
|
|
331
|
+
border: "1px solid #ced4da",
|
|
332
|
+
borderRadius: "4px",
|
|
333
|
+
fontFamily: "monospace",
|
|
334
|
+
fontSize: "11px",
|
|
335
|
+
fontWeight: 600,
|
|
336
|
+
}}
|
|
337
|
+
>
|
|
338
|
+
A
|
|
339
|
+
</kbd>{" "}
|
|
340
|
+
Previous
|
|
341
|
+
</div>
|
|
342
|
+
<div
|
|
343
|
+
style={{
|
|
344
|
+
display: "flex",
|
|
345
|
+
alignItems: "center",
|
|
346
|
+
gap: "6px",
|
|
347
|
+
fontSize: "12px",
|
|
348
|
+
color: "#495057",
|
|
349
|
+
}}
|
|
350
|
+
>
|
|
351
|
+
<kbd
|
|
352
|
+
style={{
|
|
353
|
+
padding: "2px 8px",
|
|
354
|
+
backgroundColor: "#e9ecef",
|
|
355
|
+
border: "1px solid #ced4da",
|
|
356
|
+
borderRadius: "4px",
|
|
357
|
+
fontFamily: "monospace",
|
|
358
|
+
fontSize: "11px",
|
|
359
|
+
fontWeight: 600,
|
|
360
|
+
}}
|
|
361
|
+
>
|
|
362
|
+
F
|
|
363
|
+
</kbd>{" "}
|
|
364
|
+
Flip
|
|
365
|
+
</div>
|
|
366
|
+
<div
|
|
367
|
+
style={{
|
|
368
|
+
display: "flex",
|
|
369
|
+
alignItems: "center",
|
|
370
|
+
gap: "6px",
|
|
371
|
+
fontSize: "12px",
|
|
372
|
+
color: "#495057",
|
|
373
|
+
}}
|
|
374
|
+
>
|
|
375
|
+
<kbd
|
|
376
|
+
style={{
|
|
377
|
+
padding: "2px 8px",
|
|
378
|
+
backgroundColor: "#e9ecef",
|
|
379
|
+
border: "1px solid #ced4da",
|
|
380
|
+
borderRadius: "4px",
|
|
381
|
+
fontFamily: "monospace",
|
|
382
|
+
fontSize: "11px",
|
|
383
|
+
fontWeight: 600,
|
|
384
|
+
}}
|
|
385
|
+
>
|
|
386
|
+
S
|
|
387
|
+
</kbd>{" "}
|
|
388
|
+
End
|
|
389
|
+
</div>
|
|
390
|
+
<div
|
|
391
|
+
style={{
|
|
392
|
+
display: "flex",
|
|
393
|
+
alignItems: "center",
|
|
394
|
+
gap: "6px",
|
|
395
|
+
fontSize: "12px",
|
|
396
|
+
color: "#495057",
|
|
397
|
+
}}
|
|
398
|
+
>
|
|
399
|
+
<kbd
|
|
400
|
+
style={{
|
|
401
|
+
padding: "2px 8px",
|
|
402
|
+
backgroundColor: "#e9ecef",
|
|
403
|
+
border: "1px solid #ced4da",
|
|
404
|
+
borderRadius: "4px",
|
|
405
|
+
fontFamily: "monospace",
|
|
406
|
+
fontSize: "11px",
|
|
407
|
+
fontWeight: 600,
|
|
408
|
+
}}
|
|
409
|
+
>
|
|
410
|
+
D
|
|
411
|
+
</kbd>{" "}
|
|
412
|
+
Next
|
|
413
|
+
</div>
|
|
414
|
+
</div>
|
|
415
|
+
</div>
|
|
137
416
|
</ChessPuzzle.Root>
|
|
138
417
|
);
|
|
139
418
|
};
|
|
@@ -147,39 +426,72 @@ const multiMatePuzzle = {
|
|
|
147
426
|
|
|
148
427
|
export const MultiMatePuzzle = (args: RootProps) => {
|
|
149
428
|
return (
|
|
150
|
-
<
|
|
151
|
-
<
|
|
152
|
-
<
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
<
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
429
|
+
<ChessPuzzle.Root {...args} puzzle={multiMatePuzzle}>
|
|
430
|
+
<div style={storyStyles.container}>
|
|
431
|
+
<div style={storyStyles.header}>
|
|
432
|
+
<h3 style={storyStyles.title}>Flexible Checkmate</h3>
|
|
433
|
+
<p style={storyStyles.subtitle}>
|
|
434
|
+
Any checkmate move solves the puzzle
|
|
435
|
+
</p>
|
|
436
|
+
</div>
|
|
437
|
+
<div
|
|
438
|
+
style={{
|
|
439
|
+
...storyStyles.infoBox,
|
|
440
|
+
backgroundColor: "#d3f9d8",
|
|
441
|
+
color: "#2b8a3e",
|
|
442
|
+
}}
|
|
443
|
+
>
|
|
444
|
+
<strong>solveOnCheckmate=true (default)</strong>
|
|
445
|
+
<br />
|
|
446
|
+
Try Qc8#, Qf8#, Rb8#, or the canonical Ra8#
|
|
447
|
+
</div>
|
|
448
|
+
<div style={storyStyles.boardWrapper}>
|
|
449
|
+
<ChessPuzzle.Board />
|
|
450
|
+
</div>
|
|
451
|
+
<div style={storyStyles.controlsSection}>
|
|
452
|
+
<ChessPuzzle.Reset asChild>
|
|
453
|
+
<button style={storyStyles.button}>Restart</button>
|
|
454
|
+
</ChessPuzzle.Reset>
|
|
455
|
+
</div>
|
|
456
|
+
</div>
|
|
457
|
+
</ChessPuzzle.Root>
|
|
163
458
|
);
|
|
164
459
|
};
|
|
165
460
|
|
|
166
461
|
export const MultiMatePuzzleStrict = (args: RootProps) => {
|
|
167
462
|
return (
|
|
168
|
-
<
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
<
|
|
174
|
-
{
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
463
|
+
<ChessPuzzle.Root
|
|
464
|
+
{...args}
|
|
465
|
+
puzzle={multiMatePuzzle}
|
|
466
|
+
solveOnCheckmate={false}
|
|
467
|
+
>
|
|
468
|
+
<div style={storyStyles.container}>
|
|
469
|
+
<div style={storyStyles.header}>
|
|
470
|
+
<h3 style={storyStyles.title}>Strict Checkmate</h3>
|
|
471
|
+
<p style={storyStyles.subtitle}>
|
|
472
|
+
Only the canonical solution is accepted
|
|
473
|
+
</p>
|
|
474
|
+
</div>
|
|
475
|
+
<div
|
|
476
|
+
style={{
|
|
477
|
+
...storyStyles.infoBox,
|
|
478
|
+
backgroundColor: "#ffe3e3",
|
|
479
|
+
color: "#c92a2a",
|
|
480
|
+
}}
|
|
481
|
+
>
|
|
482
|
+
<strong>solveOnCheckmate=false</strong>
|
|
483
|
+
<br />
|
|
484
|
+
Only Ra8# is accepted. Alternative mates like Qc8# will fail!
|
|
485
|
+
</div>
|
|
486
|
+
<div style={storyStyles.boardWrapper}>
|
|
487
|
+
<ChessPuzzle.Board />
|
|
488
|
+
</div>
|
|
489
|
+
<div style={storyStyles.controlsSection}>
|
|
490
|
+
<ChessPuzzle.Reset asChild>
|
|
491
|
+
<button style={storyStyles.button}>Restart</button>
|
|
492
|
+
</ChessPuzzle.Reset>
|
|
493
|
+
</div>
|
|
494
|
+
</div>
|
|
495
|
+
</ChessPuzzle.Root>
|
|
184
496
|
);
|
|
185
497
|
};
|