kokopu-react 1.4.0 → 1.5.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.
Files changed (195) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +1 -1
  3. package/dist/lib/ArrowMarkerIcon.js +3 -3
  4. package/dist/lib/Chessboard.js +6 -8
  5. package/dist/lib/ErrorBox.js +85 -5
  6. package/dist/lib/Movetext.js +851 -0
  7. package/dist/lib/SquareMarkerIcon.js +1 -1
  8. package/dist/lib/TextMarkerIcon.js +1 -1
  9. package/dist/lib/css/arrow.css +1 -1
  10. package/dist/lib/css/chessboard.css +6 -1
  11. package/dist/lib/css/error_box.css +13 -2
  12. package/dist/lib/css/{label.css → fonts.css} +11 -6
  13. package/dist/lib/css/movetext.css +117 -0
  14. package/dist/lib/css/symbol.css +9 -1
  15. package/dist/lib/fonts/chessalpha.woff +0 -0
  16. package/dist/lib/fonts/chessalpha.woff2 +0 -0
  17. package/dist/lib/i18n.js +17 -2
  18. package/dist/lib/impl/ArrowTip.js +1 -1
  19. package/dist/lib/impl/HtmlSanitizer.js +171 -0
  20. package/dist/lib/impl/TextSymbol.js +2 -4
  21. package/dist/lib/impl/colorsets.js +1 -1
  22. package/dist/lib/impl/piecesets.js +1 -1
  23. package/dist/lib/impl/util.js +1 -1
  24. package/dist/lib/index.js +8 -0
  25. package/doc_src/demo/PageChessboardBase.js +1 -1
  26. package/doc_src/demo/{PageChessboardEdition.js → PageChessboardInteraction.js} +2 -4
  27. package/doc_src/demo/PageChessboardMove.js +1 -1
  28. package/doc_src/demo/PageChessboardSmallScreens.js +1 -1
  29. package/doc_src/demo/PageMovetextBase.js +214 -0
  30. package/doc_src/demo/PageMovetextInteraction.js +159 -0
  31. package/doc_src/demo/demo.css +8 -1
  32. package/doc_src/demo/game-1.pgn +23 -0
  33. package/doc_src/demo/game-2.pgn +22 -0
  34. package/doc_src/demo/game-invalid.pgn +10 -0
  35. package/doc_src/demo/util.js +1 -1
  36. package/doc_src/examples/Movetext.md +15 -0
  37. package/doc_src/home.md +2 -0
  38. package/doc_src/theming/LogoRenderer.js +1 -1
  39. package/doc_src/theming/theming.css +1 -1
  40. package/graphic_test_app/01_marker_icons.js +1 -1
  41. package/graphic_test_app/02_chessboard_simple.js +1 -1
  42. package/graphic_test_app/03_chessboard_flipped.js +1 -1
  43. package/graphic_test_app/04_chessboard_annotations.js +1 -1
  44. package/graphic_test_app/05_chessboard_move.js +1 -1
  45. package/graphic_test_app/06_chessboard_theme.js +1 -1
  46. package/graphic_test_app/07_chessboard_click_squares.js +1 -1
  47. package/graphic_test_app/08_chessboard_move_pieces.js +1 -1
  48. package/graphic_test_app/09_chessboard_edit_arrows.js +1 -1
  49. package/graphic_test_app/10_chessboard_play_moves.js +1 -1
  50. package/graphic_test_app/11_chessboard_play_promotions.js +1 -1
  51. package/graphic_test_app/12_movetext_simple.js +41 -0
  52. package/graphic_test_app/13_movetext_error.js +38 -0
  53. package/graphic_test_app/14_movetext_html.js +40 -0
  54. package/graphic_test_app/15_movetext_options.js +42 -0
  55. package/graphic_test_app/16_movetext_interaction.js +42 -0
  56. package/graphic_test_app/common/dummy.pgn +8 -0
  57. package/graphic_test_app/common/games.pgn +167 -0
  58. package/graphic_test_app/common/heartbeat.txt +1 -0
  59. package/graphic_test_app/common/test_app.css +20 -4
  60. package/graphic_test_app/common/test_app.js +6 -6
  61. package/package.json +26 -25
  62. package/scripts/test_graphic/clean-graphic-output.js +1 -1
  63. package/scripts/test_graphic/docker-compose.yml +1 -1
  64. package/scripts/test_graphic/webpack-config.js +7 -3
  65. package/scripts/test_headless.webpack-config.js +2 -2
  66. package/src/ArrowMarkerIcon.js +1 -1
  67. package/src/Chessboard.js +6 -7
  68. package/src/ErrorBox.js +80 -1
  69. package/src/Movetext.js +627 -0
  70. package/src/SquareMarkerIcon.js +1 -1
  71. package/src/TextMarkerIcon.js +1 -1
  72. package/src/css/arrow.css +1 -1
  73. package/src/css/chessboard.css +6 -1
  74. package/src/css/error_box.css +13 -2
  75. package/src/css/{label.css → fonts.css} +11 -6
  76. package/src/css/movetext.css +117 -0
  77. package/src/css/symbol.css +9 -1
  78. package/src/fonts/chessalpha.woff +0 -0
  79. package/src/fonts/chessalpha.woff2 +0 -0
  80. package/src/i18n.js +12 -1
  81. package/src/impl/ArrowTip.js +1 -1
  82. package/src/impl/HtmlSanitizer.js +120 -0
  83. package/src/impl/TextSymbol.js +2 -3
  84. package/src/impl/colorsets.js +1 -1
  85. package/src/impl/piecesets.js +1 -1
  86. package/src/impl/util.js +1 -1
  87. package/src/index.js +2 -1
  88. package/src/markers.js +1 -1
  89. package/test/1_markers.js +1 -1
  90. package/test/2_chessboard_util.js +1 -1
  91. package/test/3_marker_icons_graphic.js +1 -1
  92. package/test/4_chessboard_graphic.js +1 -1
  93. package/test/5_chessboard_interaction.js +1 -1
  94. package/test/6_chessboard_play_moves.js +1 -1
  95. package/test/7_movetext_graphic.js +43 -0
  96. package/test/8_movetext_interaction.js +103 -0
  97. package/test/common/graphic.js +2 -2
  98. package/test/references/01_marker_icons/0.png +0 -0
  99. package/test/references/01_marker_icons/1.png +0 -0
  100. package/test/references/01_marker_icons/10.png +0 -0
  101. package/test/references/01_marker_icons/2.png +0 -0
  102. package/test/references/01_marker_icons/3.png +0 -0
  103. package/test/references/01_marker_icons/4.png +0 -0
  104. package/test/references/01_marker_icons/5.png +0 -0
  105. package/test/references/01_marker_icons/6.png +0 -0
  106. package/test/references/01_marker_icons/7.png +0 -0
  107. package/test/references/01_marker_icons/8.png +0 -0
  108. package/test/references/01_marker_icons/9.png +0 -0
  109. package/test/references/02_chessboard_simple/0.png +0 -0
  110. package/test/references/02_chessboard_simple/1.png +0 -0
  111. package/test/references/02_chessboard_simple/2.png +0 -0
  112. package/test/references/02_chessboard_simple/3.png +0 -0
  113. package/test/references/02_chessboard_simple/4.png +0 -0
  114. package/test/references/02_chessboard_simple/5.png +0 -0
  115. package/test/references/03_chessboard_flipped/0.png +0 -0
  116. package/test/references/03_chessboard_flipped/1.png +0 -0
  117. package/test/references/03_chessboard_flipped/2.png +0 -0
  118. package/test/references/03_chessboard_flipped/3.png +0 -0
  119. package/test/references/03_chessboard_flipped/4.png +0 -0
  120. package/test/references/04_chessboard_annotations/0.png +0 -0
  121. package/test/references/04_chessboard_annotations/1.png +0 -0
  122. package/test/references/04_chessboard_annotations/2.png +0 -0
  123. package/test/references/04_chessboard_annotations/3.png +0 -0
  124. package/test/references/04_chessboard_annotations/4.png +0 -0
  125. package/test/references/04_chessboard_annotations/5.png +0 -0
  126. package/test/references/05_chessboard_move/0.png +0 -0
  127. package/test/references/05_chessboard_move/1.png +0 -0
  128. package/test/references/05_chessboard_move/2.png +0 -0
  129. package/test/references/05_chessboard_move/3.png +0 -0
  130. package/test/references/05_chessboard_move/4.png +0 -0
  131. package/test/references/05_chessboard_move/5.png +0 -0
  132. package/test/references/05_chessboard_move/6.png +0 -0
  133. package/test/references/05_chessboard_move/7.png +0 -0
  134. package/test/references/05_chessboard_move/8.png +0 -0
  135. package/test/references/06_chessboard_theme/0.png +0 -0
  136. package/test/references/06_chessboard_theme/1.png +0 -0
  137. package/test/references/06_chessboard_theme/2.png +0 -0
  138. package/test/references/06_chessboard_theme/3.png +0 -0
  139. package/test/references/06_chessboard_theme/4.png +0 -0
  140. package/test/references/06_chessboard_theme/5.png +0 -0
  141. package/test/references/06_chessboard_theme/6.png +0 -0
  142. package/test/references/06_chessboard_theme/7.png +0 -0
  143. package/test/references/06_chessboard_theme/8.png +0 -0
  144. package/test/references/08_chessboard_move_pieces/after_move.png +0 -0
  145. package/test/references/08_chessboard_move_pieces/empty_square.png +0 -0
  146. package/test/references/08_chessboard_move_pieces/null_vector.png +0 -0
  147. package/test/references/08_chessboard_move_pieces/out_of_board.png +0 -0
  148. package/test/references/08_chessboard_move_pieces/over_arrow_marker.png +0 -0
  149. package/test/references/08_chessboard_move_pieces/over_empty.png +0 -0
  150. package/test/references/08_chessboard_move_pieces/over_non_empty_1.png +0 -0
  151. package/test/references/08_chessboard_move_pieces/over_non_empty_2.png +0 -0
  152. package/test/references/08_chessboard_move_pieces/over_square_marker.png +0 -0
  153. package/test/references/08_chessboard_move_pieces/over_text_marker.png +0 -0
  154. package/test/references/09_chessboard_edit_arrows/base_1.png +0 -0
  155. package/test/references/09_chessboard_edit_arrows/base_2.png +0 -0
  156. package/test/references/09_chessboard_edit_arrows/edit_color_not_set.png +0 -0
  157. package/test/references/09_chessboard_edit_arrows/null_vector.png +0 -0
  158. package/test/references/09_chessboard_edit_arrows/out_of_board.png +0 -0
  159. package/test/references/09_chessboard_edit_arrows/over_arrow_marker.png +0 -0
  160. package/test/references/09_chessboard_edit_arrows/over_square_marker.png +0 -0
  161. package/test/references/10_chessboard_play_moves/castling_move.png +0 -0
  162. package/test/references/10_chessboard_play_moves/chess960_ambiguous_king_move.png +0 -0
  163. package/test/references/10_chessboard_play_moves/chess960_castling_move_1.png +0 -0
  164. package/test/references/10_chessboard_play_moves/chess960_castling_move_2.png +0 -0
  165. package/test/references/10_chessboard_play_moves/chess960_non_kxr_castling.png +0 -0
  166. package/test/references/10_chessboard_play_moves/illegal_move.png +0 -0
  167. package/test/references/10_chessboard_play_moves/illegal_position.png +0 -0
  168. package/test/references/10_chessboard_play_moves/null_vector.png +0 -0
  169. package/test/references/10_chessboard_play_moves/out_of_board.png +0 -0
  170. package/test/references/10_chessboard_play_moves/regular_move_1.png +0 -0
  171. package/test/references/10_chessboard_play_moves/regular_move_2.png +0 -0
  172. package/test/references/10_chessboard_play_moves/wrong_color.png +0 -0
  173. package/test/references/11_chessboard_play_promotions/antichess_promotion.png +0 -0
  174. package/test/references/11_chessboard_play_promotions/cancel_promotion.png +0 -0
  175. package/test/references/11_chessboard_play_promotions/regular_promotion_1.png +0 -0
  176. package/test/references/11_chessboard_play_promotions/regular_promotion_2.png +0 -0
  177. package/test/references/12_movetext_simple/0.png +0 -0
  178. package/test/references/12_movetext_simple/1.png +0 -0
  179. package/test/references/12_movetext_simple/2.png +0 -0
  180. package/test/references/12_movetext_simple/3.png +0 -0
  181. package/test/references/13_movetext_error/0.png +0 -0
  182. package/test/references/13_movetext_error/1.png +0 -0
  183. package/test/references/13_movetext_error/2.png +0 -0
  184. package/test/references/13_movetext_error/3.png +0 -0
  185. package/test/references/14_movetext_html/0.png +0 -0
  186. package/test/references/14_movetext_html/1.png +0 -0
  187. package/test/references/14_movetext_html/2.png +0 -0
  188. package/test/references/15_movetext_options/0.png +0 -0
  189. package/test/references/15_movetext_options/1.png +0 -0
  190. package/test/references/15_movetext_options/2.png +0 -0
  191. package/test/references/15_movetext_options/3.png +0 -0
  192. package/test/references/16_movetext_interaction/0.png +0 -0
  193. package/test/references/16_movetext_interaction/1.png +0 -0
  194. package/test/references/16_movetext_interaction/2.png +0 -0
  195. package/graphic_test_app/common/healthcheck.txt +0 -1
@@ -0,0 +1,214 @@
1
+ /******************************************************************************
2
+ * *
3
+ * This file is part of Kokopu-React, a JavaScript chess library. *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
+ * *
6
+ * This program is free software: you can redistribute it and/or *
7
+ * modify it under the terms of the GNU Lesser General Public License *
8
+ * as published by the Free Software Foundation, either version 3 of *
9
+ * the License, or (at your option) any later version. *
10
+ * *
11
+ * This program is distributed in the hope that it will be useful, *
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
+ * GNU Lesser General Public License for more details. *
15
+ * *
16
+ * You should have received a copy of the GNU Lesser General *
17
+ * Public License along with this program. If not, see *
18
+ * <http://www.gnu.org/licenses/>. *
19
+ * *
20
+ ******************************************************************************/
21
+
22
+
23
+ import React from 'react';
24
+
25
+ import { Chessboard, Movetext } from '../../src/index';
26
+ import { buildComponentDemoCode } from './util';
27
+
28
+ import Box from '@mui/material/Box';
29
+ import Button from '@mui/material/Button';
30
+ import ButtonGroup from '@mui/material/ButtonGroup';
31
+ import FormControl from '@mui/material/FormControl';
32
+ import FormControlLabel from '@mui/material/FormControlLabel';
33
+ import InputLabel from '@mui/material/InputLabel';
34
+ import MenuItem from '@mui/material/MenuItem';
35
+ import Select from '@mui/material/Select';
36
+ import Slider from '@mui/material/Slider';
37
+ import Stack from '@mui/material/Stack';
38
+ import Switch from '@mui/material/Switch';
39
+ import TextField from '@mui/material/TextField';
40
+ import Typography from '@mui/material/Typography';
41
+
42
+ import './demo.css';
43
+ import game1 from './game-1.pgn';
44
+ import game2 from './game-2.pgn';
45
+ import invalidGame from './game-invalid.pgn';
46
+
47
+
48
+ export default class Page extends React.Component {
49
+
50
+ constructor(props) {
51
+ super(props);
52
+ this.state = {
53
+ pgn: game1,
54
+ headerVisible: true,
55
+ diagramVisible: true,
56
+ pieceSymbols: 'figurines',
57
+ customSymbols: { K:'R', Q:'D', R:'T', B:'F', N:'C', P:'P' },
58
+ diagramOptions: {
59
+ flipped: false,
60
+ squareSize: 32,
61
+ coordinateVisible: true,
62
+ colorset: 'original',
63
+ pieceset: 'cburnett',
64
+ },
65
+ };
66
+ }
67
+
68
+ render() {
69
+ return (
70
+ <Stack spacing={2} mt={2}>
71
+ {this.renderControls()}
72
+ {this.renderMovetext()}
73
+ {this.renderCode()}
74
+ </Stack>
75
+ );
76
+ }
77
+
78
+ renderControls() {
79
+ let opts = this.state.diagramOptions;
80
+ return (<>
81
+ <Stack direction="row" spacing={2} alignItems="center">
82
+ <ButtonGroup color="primary" size="small">
83
+ <Button onClick={() => this.set('pgn', game1)}>Game 1</Button>
84
+ <Button onClick={() => this.set('pgn', game2)}>Game 2</Button>
85
+ <Button onClick={() => this.set('pgn', invalidGame)}>Invalid game</Button>
86
+ </ButtonGroup>
87
+ <FormControlLabel label="Show headers"
88
+ control={<Switch checked={this.state.headerVisible} onChange={() => this.set('headerVisible', !this.state.headerVisible)} color="primary" />}
89
+ />
90
+ <FormControlLabel label="Show diagrams"
91
+ control={<Switch checked={this.state.diagramVisible} onChange={() => this.set('diagramVisible', !this.state.diagramVisible)} color="primary" />}
92
+ />
93
+ </Stack>
94
+ <Stack direction="row" spacing={2} alignItems="center">
95
+ <FormControl variant="standard">
96
+ <InputLabel id="piecesymbols-label">Piece symbols</InputLabel>
97
+ <Select labelId="piecesymbols-label" sx={{ width: '8em' }} value={this.state.pieceSymbols} onChange={evt => this.set('pieceSymbols', evt.target.value)}>
98
+ <MenuItem value="native">Native</MenuItem>
99
+ <MenuItem value="figurines">Figurines</MenuItem>
100
+ <MenuItem value="custom">Custom</MenuItem>
101
+ </Select>
102
+ </FormControl>
103
+ {this.renderCustomSymbolSelector()}
104
+ </Stack>
105
+ <Stack direction="row" spacing={2} alignItems="center">
106
+ <FormControlLabel label="Flip diagram(s)"
107
+ control={<Switch checked={opts.flipped} onChange={() => this.setDiagramOption('flipped', !opts.flipped)} color="primary" />}
108
+ />
109
+ <FormControlLabel label="Show coordinates in diagram(s)"
110
+ control={<Switch checked={opts.coordinateVisible} onChange={() => this.setDiagramOption('coordinateVisible', !opts.coordinateVisible)} color="primary" />}
111
+ />
112
+ <FormControl variant="standard">
113
+ <InputLabel id="colorset-label">Colorset</InputLabel>
114
+ <Select labelId="colorset-label" sx={{ width: '8em' }} value={opts.colorset} onChange={evt => this.setDiagramOption('colorset', evt.target.value)}>
115
+ {Object.keys(Chessboard.colorsets()).sort().map(colorset => <MenuItem key={colorset} value={colorset}>{colorset}</MenuItem>)}
116
+ </Select>
117
+ </FormControl>
118
+ <FormControl variant="standard">
119
+ <InputLabel id="pieceset-label">Pieceset</InputLabel>
120
+ <Select labelId="pieceset-label" sx={{ width: '8em' }} value={opts.pieceset} onChange={evt => this.setDiagramOption('pieceset', evt.target.value)}>
121
+ {Object.keys(Chessboard.piecesets()).sort().map(pieceset => <MenuItem key={pieceset} value={pieceset}>{pieceset}</MenuItem>)}
122
+ </Select>
123
+ </FormControl>
124
+ </Stack>
125
+ <Box>
126
+ <Typography gutterBottom>Diagram square size</Typography>
127
+ <Slider
128
+ value={opts.squareSize} onChange={(_, newValue) => this.setDiagramOption('squareSize', newValue)}
129
+ min={Chessboard.minSquareSize()} max={Chessboard.maxSquareSize()} step={1} valueLabelDisplay="on" color="primary"
130
+ />
131
+ </Box>
132
+ </>);
133
+ }
134
+
135
+ renderCustomSymbolSelector() {
136
+ if (this.state.pieceSymbols !== 'custom') {
137
+ return undefined;
138
+ }
139
+ let symbols = this.state.customSymbols;
140
+ return (<>
141
+ <TextField variant="standard" sx={{ width: '3em' }} label="King" value={symbols.K} onChange={evt => this.setCustomSymbol('K', evt.target.value)} />
142
+ <TextField variant="standard" sx={{ width: '3em' }} label="Queen" value={symbols.Q} onChange={evt => this.setCustomSymbol('Q', evt.target.value)} />
143
+ <TextField variant="standard" sx={{ width: '3em' }} label="Rook" value={symbols.R} onChange={evt => this.setCustomSymbol('R', evt.target.value)} />
144
+ <TextField variant="standard" sx={{ width: '3em' }} label="Bishop" value={symbols.B} onChange={evt => this.setCustomSymbol('B', evt.target.value)} />
145
+ <TextField variant="standard" sx={{ width: '3em' }} label="Knight" value={symbols.N} onChange={evt => this.setCustomSymbol('N', evt.target.value)} />
146
+ <TextField variant="standard" sx={{ width: '3em' }} label="Pawn" value={symbols.P} onChange={evt => this.setCustomSymbol('P', evt.target.value)} />
147
+ </>);
148
+ }
149
+
150
+ renderMovetext() {
151
+ return (
152
+ <Box>
153
+ <Movetext
154
+ game={this.state.pgn}
155
+ headerVisible={this.state.headerVisible}
156
+ diagramVisible={this.state.diagramVisible}
157
+ pieceSymbols={this.state.pieceSymbols === 'custom' ? this.state.customSymbols : this.state.pieceSymbols}
158
+ diagramOptions={this.state.diagramOptions}
159
+ />
160
+ </Box>
161
+ );
162
+ }
163
+
164
+ renderCode() {
165
+ let attributes = [];
166
+ attributes.push('game={pgn}');
167
+ attributes.push(`headerVisible={${this.state.headerVisible}}`);
168
+ attributes.push(`pieceSymbols=${this.getPieceSymbolsAsText()}`);
169
+ attributes.push(`diagramVisible={${this.state.diagramVisible}}`);
170
+ attributes.push(`diagramOptions={{ ${this.getDiagramAttributesAsText()} }}`);
171
+ let pgnDeclaration = 'const pgn = `\n' + this.state.pgn.trim() + '`;\n\n';
172
+ return <pre className="kokopu-demoCode">{pgnDeclaration + buildComponentDemoCode('Movetext', attributes)}</pre>;
173
+ }
174
+
175
+ set(attributeName, newValue) {
176
+ let newState = {};
177
+ newState[attributeName] = newValue;
178
+ this.setState(newState);
179
+ }
180
+
181
+ setCustomSymbol(key, value) {
182
+ let symbols = {...this.state.customSymbols};
183
+ symbols[key] = value;
184
+ this.set('customSymbols', symbols);
185
+ }
186
+
187
+ getPieceSymbolsAsText() {
188
+ if (this.state.pieceSymbols === 'custom') {
189
+ let symbols = this.state.customSymbols;
190
+ return `{{ K:'${symbols.K}', Q:'${symbols.Q}', R:'${symbols.R}', B:'${symbols.B}', N:'${symbols.N}', P:'${symbols.P}' }}`;
191
+ }
192
+ else {
193
+ return `"${this.state.pieceSymbols}"`;
194
+ }
195
+ }
196
+
197
+ setDiagramOption(key, value) {
198
+ let diagramOptions = {...this.state.diagramOptions};
199
+ diagramOptions[key] = value;
200
+ this.set('diagramOptions', diagramOptions);
201
+ }
202
+
203
+ getDiagramAttributesAsText() {
204
+ let attributes = [];
205
+ if (this.state.diagramOptions.flipped) {
206
+ attributes.push('flipped:true');
207
+ }
208
+ attributes.push(`squareSize:${this.state.diagramOptions.squareSize}`);
209
+ attributes.push(`coordinateVisible:${this.state.diagramOptions.coordinateVisible}`);
210
+ attributes.push(`colorset:'${this.state.diagramOptions.colorset}'`);
211
+ attributes.push(`pieceset:'${this.state.diagramOptions.pieceset}'`);
212
+ return attributes.join(', ');
213
+ }
214
+ }
@@ -0,0 +1,159 @@
1
+ /******************************************************************************
2
+ * *
3
+ * This file is part of Kokopu-React, a JavaScript chess library. *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
+ * *
6
+ * This program is free software: you can redistribute it and/or *
7
+ * modify it under the terms of the GNU Lesser General Public License *
8
+ * as published by the Free Software Foundation, either version 3 of *
9
+ * the License, or (at your option) any later version. *
10
+ * *
11
+ * This program is distributed in the hope that it will be useful, *
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
+ * GNU Lesser General Public License for more details. *
15
+ * *
16
+ * You should have received a copy of the GNU Lesser General *
17
+ * Public License along with this program. If not, see *
18
+ * <http://www.gnu.org/licenses/>. *
19
+ * *
20
+ ******************************************************************************/
21
+
22
+
23
+ import React from 'react';
24
+ import kokopu from 'kokopu';
25
+
26
+ import { Chessboard, Movetext } from '../../src/index';
27
+ import { buildComponentDemoCode } from './util';
28
+
29
+ import Box from '@mui/material/Box';
30
+ import Button from '@mui/material/Button';
31
+ import ButtonGroup from '@mui/material/ButtonGroup';
32
+ import FormControlLabel from '@mui/material/FormControlLabel';
33
+ import Paper from '@mui/material/Paper';
34
+ import Radio from '@mui/material/Radio';
35
+ import RadioGroup from '@mui/material/RadioGroup';
36
+ import Stack from '@mui/material/Stack';
37
+ import Typography from '@mui/material/Typography';
38
+
39
+ import './demo.css';
40
+ import game1 from './game-1.pgn';
41
+ import game2 from './game-2.pgn';
42
+
43
+
44
+ export default class Page extends React.Component {
45
+
46
+ constructor(props) {
47
+ super(props);
48
+ this.state = {
49
+ pgn: game1,
50
+ selection: '28b',
51
+ interactionMode: 'selectMove',
52
+ withPopup: true,
53
+ withMove: false,
54
+ };
55
+ }
56
+
57
+ render() {
58
+ return (
59
+ <Stack spacing={2} mt={2}>
60
+ {this.renderControls()}
61
+ {this.renderMovetext()}
62
+ {this.renderCode()}
63
+ {this.renderNavigationBoard()}
64
+ </Stack>
65
+ );
66
+ }
67
+
68
+ renderControls() {
69
+ return (<>
70
+ <Stack direction="row" spacing={2} alignItems="center">
71
+ <ButtonGroup color="primary" size="small">
72
+ <Button onClick={() => this.set('pgn', game1, 'selection', '28b')}>Game 1</Button>
73
+ <Button onClick={() => this.set('pgn', game2, 'selection', '15b')}>Game 2</Button>
74
+ </ButtonGroup>
75
+ </Stack>
76
+ <Box>
77
+ <Typography gutterBottom>Interaction mode</Typography>
78
+ <RadioGroup value={this.state.interactionMode} onChange={evt => this.set('interactionMode', evt.target.value)}>
79
+ <FormControlLabel value="" control={<Radio color="primary" />} label="None" />
80
+ <FormControlLabel value="selectMove" control={<Radio color="primary" />} label="Select moves" />
81
+ </RadioGroup>
82
+ </Box>
83
+ </>);
84
+ }
85
+
86
+ renderMovetext() {
87
+ return (
88
+ <Box>
89
+ <Movetext
90
+ game={this.state.pgn}
91
+ selection={this.state.selection}
92
+ pieceSymbols="figurines"
93
+ diagramVisible={false}
94
+ interactionMode={this.state.interactionMode}
95
+ onMoveSelected={(nodeId, evtOrigin) => this.handleMoveSelected(nodeId, evtOrigin)}
96
+ />
97
+ </Box>
98
+ );
99
+ }
100
+
101
+ renderCode() {
102
+ let attributes = [];
103
+ attributes.push('game={pgn}');
104
+ attributes.push('pieceSymbols="figurines"');
105
+ attributes.push('diagramVisible={false}');
106
+ attributes.push(`selection="${this.state.selection}"`);
107
+ switch(this.state.interactionMode) {
108
+ case 'selectMove':
109
+ attributes.push('interactionMode="selectMove"');
110
+ attributes.push('onMoveSelected={nodeId => handleMoveSelected(nodeId)}');
111
+ break;
112
+ default:
113
+ break;
114
+ }
115
+ let pgnDeclaration = 'const pgn = `\n' + this.state.pgn.trim() + '`;\n\n';
116
+ return <pre className="kokopu-demoCode">{pgnDeclaration + buildComponentDemoCode('Movetext', attributes)}</pre>;
117
+ }
118
+
119
+ renderNavigationBoard() {
120
+ let button = <Button size="small" onClick={() => this.handlePopupToggled()}>{this.state.withPopup ? 'Reduce' : 'Open'}</Button>;
121
+ let { position, move, csl, cal } = this.getCurrentPositionAndAnnotations();
122
+ let content = this.state.withPopup ? <Stack><Chessboard position={position} move={move} squareMarkers={csl} arrowMarkers={cal} animated={true} />{button}</Stack> : button;
123
+ return <Paper className="kokopu-fixedPopup" elevation={3}>{content}</Paper>;
124
+ }
125
+
126
+ handleMoveSelected(nodeId, evtOrigin) {
127
+ if (nodeId) {
128
+ this.set('selection', nodeId, 'withMove', evtOrigin === 'key-next');
129
+ }
130
+ }
131
+
132
+ handlePopupToggled() {
133
+ this.set('withPopup', !this.state.withPopup);
134
+ }
135
+
136
+ set(attributeName, newValue, attributeName2, newValue2) {
137
+ let newState = {};
138
+ newState[attributeName] = newValue;
139
+ if (attributeName2) {
140
+ newState[attributeName2] = newValue2;
141
+ }
142
+ this.setState(newState);
143
+ }
144
+
145
+ getCurrentPositionAndAnnotations() {
146
+ let game = kokopu.pgnRead(this.state.pgn, 0);
147
+ if (this.state.selection === 'start') {
148
+ let mainVariation = game.mainVariation();
149
+ return { position: mainVariation.initialPosition(), csl: mainVariation.tag('csl'), cal: mainVariation.tag('cal') };
150
+ }
151
+ else {
152
+ let node = game.findById(this.state.selection);
153
+ let result = this.state.withMove ? { position: node.positionBefore(), move: node.notation() } : { position: node.position() };
154
+ result.csl = node.tag('csl');
155
+ result.cal = node.tag('cal');
156
+ return result;
157
+ }
158
+ }
159
+ }
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -32,3 +32,10 @@
32
32
  .MuiToggleButton-root.kokopu-fixTextTransform {
33
33
  text-transform: none;
34
34
  }
35
+
36
+ .kokopu-fixedPopup {
37
+ position: fixed;
38
+ bottom: 20px;
39
+ right: 20px;
40
+ padding: 10px;
41
+ }
@@ -0,0 +1,23 @@
1
+ [Event "1<sup>st</sup> American Chess Congress"]
2
+ [Site "?"]
3
+ [Date "1857.11.03"]
4
+ [Round "4.6"]
5
+ [White "Paulsen, Louis"]
6
+ [Black "Morphy, Paul"]
7
+ [Result "0-1"]
8
+
9
+ 1. e4 e5 2. Nf3 Nc6 3. Nc3 Nf6 4. Bb5 Bc5 5. O-O O-O 6. Nxe5 Re8 7. Nxc6 dxc6
10
+ 8. Bc4 b5 9. Be2 Nxe4 10. Nxe4 Rxe4 11. Bf3 Re6 12. c3 Qd3 13. b4 Bb6 14. a4 bxa4
11
+ 15. Qxa4 Bd7 16. Ra2 Rae8 17. Qa6
12
+
13
+ {[#] Morphy took twelve minutes over his next move, probably to assure himself
14
+ that the combination was sound and that he had a forced win in every variation.}
15
+
16
+ 17... Qxf3 !! 18. gxf3 Rg6+ 19. Kh1 Bh3 20. Rd1
17
+ ({Not} 20. Rg1 Rxg1+ 21. Kxg1 Re1+ -+)
18
+ 20... Bg2+ 21. Kg1 Bxf3+ 22. Kf1 Bg2+
19
+
20
+ (22...Rg2 ! {would have won more quickly. For instance:} 23. Qd3 Rxf2+ 24. Kg1 Rg2+ 25. Kh1 Rg1#)
21
+
22
+ 23. Kg1 Bh3+ 24. Kh1 Bxf2 25. Qf1 {Absolutely forced.} 25... Bxf1 26. Rxf1 Re2
23
+ 27. Ra1 Rh6 28. d4 Be3 0-1
@@ -0,0 +1,22 @@
1
+ [Event "Checkmate with Bishop + Knight"]
2
+ [Site "?"]
3
+ [Date "????.??.??"]
4
+ [Round "?"]
5
+ [White "?"]
6
+ [Black "?"]
7
+ [Result "*"]
8
+ [FEN "1k6/2N5/2K5/8/8/8/5B2/8 w - - 0 1"]
9
+
10
+ {[#][%cal Gc6g6,Rc7d5,Rd5e7,Re7f5,Rf5g7] How to checkmate in this situation?
11
+ The key point is to remember that the knight follows a W-shaped path between
12
+ ranks 5 and 7, while the white king stays on rank 6.}
13
+
14
+ 1.Be3 Kc8 2.Ba7 Kd8 3.Nd5 Ke8 4.Kd6 Kf7 5.Ne7 Kf6 6.Be3
15
+
16
+ {The black king is trapped behind the squares controlled by the white pieces.
17
+ [#][%csl Re5,Rf5,Rg5,Rg6,Rh6]}
18
+
19
+ 6...Kf7 7.Bd4 Ke8 8.Ke6 Kd8 9.Bb6+ Ke8 10.Nf5 Kf8 11.Ba5 Ke8 12.Ng7+ Kf8
20
+ 13.Kf6 Kg8 14.Kg6 Kf8 15.Bb4+ Kg8 +-
21
+
22
+ {[#] ... and checkmate in four moves.} *
@@ -0,0 +1,10 @@
1
+ [Event "Scholar's mate"]
2
+ [Site "?"]
3
+ [Date "????.??.??"]
4
+ [Round "?"]
5
+ [White "?"]
6
+ [Black "?"]
7
+ [Result "1-0"]
8
+
9
+ 1.e4 e5 2.Bc3 Nc6 3.Qh5 Nf6 4.Qxf7# 1-0
10
+
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -0,0 +1,15 @@
1
+ ```js
2
+ let pgn = `
3
+ [Event "Television Exhibition"]
4
+ [Site "London ENG"]
5
+ [Date "2014.01.23"]
6
+ [Round "?"]
7
+ [White "Bill Gates"]
8
+ [Black "Magnus Carlsen"]
9
+ [Result "0-1"]
10
+
11
+ 1.e4 Nc6 2.Nf3 d5 3.Bd3 Nf6 4.exd5 Qxd5 5.Nc3 Qh5 6.O-O Bg4
12
+ 7.h3 Ne5 8.hxg4 Nfxg4 {[#]} 9.Nxe5 Qh2# 0-1`;
13
+
14
+ <Movetext game={pgn} pieceSymbols="figurines" />
15
+ ```
package/doc_src/home.md CHANGED
@@ -21,6 +21,8 @@ Main components
21
21
 
22
22
  - [Chessboard](#/Components/Chessboard): SVG image representing a chessboard diagram. Optionally, the user may interact with the board
23
23
  (move pieces, click on squares...). Annotations such as square markers or arrows can also be added to the board.
24
+ - [Movetext](#/Components/Movetext): represents a chess game, i.e. the headers (name of the players, event, etc.), the moves,
25
+ and all the related annotations if any (comments, variations, NAGs...).
24
26
 
25
27
 
26
28
 
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *
@@ -1,7 +1,7 @@
1
1
  /******************************************************************************
2
2
  * *
3
3
  * This file is part of Kokopu-React, a JavaScript chess library. *
4
- * Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net> *
4
+ * Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
5
5
  * *
6
6
  * This program is free software: you can redistribute it and/or *
7
7
  * modify it under the terms of the GNU Lesser General Public License *