kokopu-react 1.3.1 → 1.5.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 +12 -0
- package/README.md +1 -1
- package/dist/lib/ArrowMarkerIcon.js +5 -7
- package/dist/lib/Chessboard.js +23 -33
- package/dist/lib/ErrorBox.js +85 -5
- package/dist/lib/Movetext.js +839 -0
- package/dist/lib/SquareMarkerIcon.js +1 -1
- package/dist/lib/TextMarkerIcon.js +12 -11
- package/dist/lib/css/arrow.css +1 -1
- package/dist/lib/css/chessboard.css +6 -1
- package/dist/lib/css/error_box.css +13 -2
- package/dist/lib/css/fonts.css +34 -0
- package/dist/lib/css/movetext.css +117 -0
- package/dist/lib/css/{label.css → symbol.css} +6 -2
- package/dist/lib/fonts/chessalpha.woff +0 -0
- package/dist/lib/fonts/chessalpha.woff2 +0 -0
- package/dist/lib/i18n.js +17 -2
- package/dist/lib/impl/ArrowTip.js +3 -8
- package/dist/lib/impl/HtmlSanitizer.js +171 -0
- package/dist/lib/impl/TextSymbol.js +98 -0
- package/dist/lib/impl/colorsets.js +1 -1
- package/dist/lib/impl/piecesets.js +1 -1
- package/dist/lib/impl/util.js +6 -6
- package/dist/lib/index.js +32 -24
- package/dist/lib/markers.js +10 -10
- package/doc_src/demo/PageChessboardBase.js +1 -1
- package/doc_src/demo/{PageChessboardEdition.js → PageChessboardInteraction.js} +4 -5
- package/doc_src/demo/PageChessboardMove.js +1 -1
- package/doc_src/demo/PageChessboardSmallScreens.js +1 -1
- package/doc_src/demo/PageMovetextBase.js +214 -0
- package/doc_src/demo/PageMovetextInteraction.js +155 -0
- package/doc_src/demo/demo.css +8 -1
- package/doc_src/demo/game-1.pgn +23 -0
- package/doc_src/demo/game-2.pgn +22 -0
- package/doc_src/demo/game-invalid.pgn +10 -0
- package/doc_src/demo/util.js +1 -1
- package/doc_src/examples/Movetext.md +15 -0
- package/doc_src/home.md +2 -0
- package/doc_src/theming/LogoRenderer.js +1 -1
- package/doc_src/theming/kokopu-react-favicon.png +0 -0
- package/doc_src/theming/theming.css +1 -1
- package/graphic_test_app/01_marker_icons.js +6 -4
- package/graphic_test_app/02_chessboard_simple.js +1 -1
- package/graphic_test_app/03_chessboard_flipped.js +1 -1
- package/graphic_test_app/04_chessboard_annotations.js +2 -2
- package/graphic_test_app/05_chessboard_move.js +1 -1
- package/graphic_test_app/06_chessboard_theme.js +1 -1
- package/graphic_test_app/07_chessboard_click_squares.js +1 -1
- package/graphic_test_app/08_chessboard_move_pieces.js +1 -1
- package/graphic_test_app/09_chessboard_edit_arrows.js +1 -1
- package/graphic_test_app/10_chessboard_play_moves.js +1 -1
- package/graphic_test_app/11_chessboard_play_promotions.js +1 -1
- package/graphic_test_app/12_movetext_simple.js +41 -0
- package/graphic_test_app/13_movetext_error.js +38 -0
- package/graphic_test_app/14_movetext_html.js +40 -0
- package/graphic_test_app/15_movetext_options.js +42 -0
- package/graphic_test_app/16_movetext_interaction.js +42 -0
- package/graphic_test_app/common/dummy.pgn +8 -0
- package/graphic_test_app/common/games.pgn +167 -0
- package/graphic_test_app/common/heartbeat.txt +1 -0
- package/graphic_test_app/common/test_app.css +20 -4
- package/graphic_test_app/common/test_app.js +6 -6
- package/package.json +26 -25
- package/scripts/test_graphic/clean-graphic-output.js +1 -1
- package/scripts/test_graphic/docker-compose.yml +1 -1
- package/scripts/test_graphic/webpack-config.js +8 -3
- package/scripts/test_headless.webpack-config.js +3 -2
- package/src/ArrowMarkerIcon.js +2 -2
- package/src/Chessboard.js +11 -11
- package/src/ErrorBox.js +80 -1
- package/src/Movetext.js +616 -0
- package/src/SquareMarkerIcon.js +1 -1
- package/src/TextMarkerIcon.js +7 -7
- package/src/css/arrow.css +1 -1
- package/src/css/chessboard.css +6 -1
- package/src/css/error_box.css +13 -2
- package/src/css/fonts.css +34 -0
- package/src/css/movetext.css +117 -0
- package/src/css/{label.css → symbol.css} +6 -2
- package/src/fonts/chessalpha.woff +0 -0
- package/src/fonts/chessalpha.woff2 +0 -0
- package/src/i18n.js +12 -1
- package/src/impl/ArrowTip.js +3 -7
- package/src/impl/HtmlSanitizer.js +120 -0
- package/src/impl/TextSymbol.js +76 -0
- package/src/impl/colorsets.js +1 -1
- package/src/impl/piecesets.js +1 -1
- package/src/impl/util.js +2 -2
- package/src/index.js +2 -1
- package/src/markers.js +8 -7
- package/test/1_markers.js +20 -1
- package/test/2_chessboard_util.js +1 -1
- package/test/3_marker_icons_graphic.js +2 -2
- package/test/4_chessboard_graphic.js +1 -1
- package/test/5_chessboard_interaction.js +1 -1
- package/test/6_chessboard_play_moves.js +1 -1
- package/test/7_movetext_graphic.js +43 -0
- package/test/8_movetext_interaction.js +99 -0
- package/test/common/graphic.js +2 -2
- package/test/references/01_marker_icons/10.png +0 -0
- package/test/references/01_marker_icons/9.png +0 -0
- package/test/references/04_chessboard_annotations/4.png +0 -0
- package/test/references/04_chessboard_annotations/5.png +0 -0
- package/test/references/05_chessboard_move/3.png +0 -0
- package/test/references/12_movetext_simple/0.png +0 -0
- package/test/references/12_movetext_simple/1.png +0 -0
- package/test/references/12_movetext_simple/2.png +0 -0
- package/test/references/12_movetext_simple/3.png +0 -0
- package/test/references/13_movetext_error/0.png +0 -0
- package/test/references/13_movetext_error/1.png +0 -0
- package/test/references/13_movetext_error/2.png +0 -0
- package/test/references/13_movetext_error/3.png +0 -0
- package/test/references/14_movetext_html/0.png +0 -0
- package/test/references/14_movetext_html/1.png +0 -0
- package/test/references/14_movetext_html/2.png +0 -0
- package/test/references/15_movetext_options/0.png +0 -0
- package/test/references/15_movetext_options/1.png +0 -0
- package/test/references/15_movetext_options/2.png +0 -0
- package/test/references/15_movetext_options/3.png +0 -0
- package/test/references/16_movetext_interaction/0.png +0 -0
- package/test/references/16_movetext_interaction/1.png +0 -0
- package/test/references/16_movetext_interaction/2.png +0 -0
- package/graphic_test_app/common/healthcheck.txt +0 -1
package/dist/lib/impl/util.js
CHANGED
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.MIN_SQUARE_SIZE = exports.MAX_SQUARE_SIZE = void 0;
|
|
6
7
|
exports.generateRandomId = generateRandomId;
|
|
7
|
-
exports.sanitizeInteger = sanitizeInteger;
|
|
8
|
-
exports.isValidSquare = isValidSquare;
|
|
9
|
-
exports.isValidVector = isValidVector;
|
|
10
8
|
exports.isValidColor = isValidColor;
|
|
9
|
+
exports.isValidSquare = isValidSquare;
|
|
11
10
|
exports.isValidSymbol = isValidSymbol;
|
|
12
|
-
exports.
|
|
11
|
+
exports.isValidVector = isValidVector;
|
|
12
|
+
exports.sanitizeInteger = sanitizeInteger;
|
|
13
13
|
|
|
14
14
|
/******************************************************************************
|
|
15
15
|
* *
|
|
16
16
|
* This file is part of Kokopu-React, a JavaScript chess library. *
|
|
17
|
-
* Copyright (C) 2021 Yoann Le Montagner <yo35 -at- melix.net>
|
|
17
|
+
* Copyright (C) 2021-2022 Yoann Le Montagner <yo35 -at- melix.net> *
|
|
18
18
|
* *
|
|
19
19
|
* This program is free software: you can redistribute it and/or *
|
|
20
20
|
* modify it under the terms of the GNU Lesser General Public License *
|
|
@@ -65,5 +65,5 @@ function isValidColor(color) {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
function isValidSymbol(symbol) {
|
|
68
|
-
return /^[A-Za-z0-9]$/.test(symbol);
|
|
68
|
+
return /^(?:[A-Za-z0-9]|plus|times|dot|circle)$/.test(symbol);
|
|
69
69
|
}
|
package/dist/lib/index.js
CHANGED
|
@@ -3,76 +3,82 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
Object.defineProperty(exports, "
|
|
6
|
+
Object.defineProperty(exports, "ArrowMarkerIcon", {
|
|
7
7
|
enumerable: true,
|
|
8
8
|
get: function get() {
|
|
9
|
-
return
|
|
9
|
+
return _ArrowMarkerIcon["default"];
|
|
10
10
|
}
|
|
11
11
|
});
|
|
12
|
-
Object.defineProperty(exports, "
|
|
12
|
+
Object.defineProperty(exports, "Chessboard", {
|
|
13
13
|
enumerable: true,
|
|
14
14
|
get: function get() {
|
|
15
|
-
return
|
|
15
|
+
return _Chessboard["default"];
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
|
-
Object.defineProperty(exports, "
|
|
18
|
+
Object.defineProperty(exports, "ErrorBox", {
|
|
19
19
|
enumerable: true,
|
|
20
20
|
get: function get() {
|
|
21
|
-
return
|
|
21
|
+
return _ErrorBox["default"];
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
|
-
Object.defineProperty(exports, "
|
|
24
|
+
Object.defineProperty(exports, "Movetext", {
|
|
25
25
|
enumerable: true,
|
|
26
26
|
get: function get() {
|
|
27
|
-
return
|
|
27
|
+
return _Movetext["default"];
|
|
28
28
|
}
|
|
29
29
|
});
|
|
30
|
-
Object.defineProperty(exports, "
|
|
30
|
+
Object.defineProperty(exports, "SquareMarkerIcon", {
|
|
31
31
|
enumerable: true,
|
|
32
32
|
get: function get() {
|
|
33
|
-
return
|
|
33
|
+
return _SquareMarkerIcon["default"];
|
|
34
34
|
}
|
|
35
35
|
});
|
|
36
|
-
Object.defineProperty(exports, "
|
|
36
|
+
Object.defineProperty(exports, "TextMarkerIcon", {
|
|
37
37
|
enumerable: true,
|
|
38
38
|
get: function get() {
|
|
39
|
-
return
|
|
39
|
+
return _TextMarkerIcon["default"];
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
|
-
Object.defineProperty(exports, "
|
|
42
|
+
Object.defineProperty(exports, "flattenArrowMarkers", {
|
|
43
43
|
enumerable: true,
|
|
44
44
|
get: function get() {
|
|
45
|
-
return
|
|
45
|
+
return _markers.flattenArrowMarkers;
|
|
46
46
|
}
|
|
47
47
|
});
|
|
48
|
-
Object.defineProperty(exports, "
|
|
48
|
+
Object.defineProperty(exports, "flattenSquareMarkers", {
|
|
49
49
|
enumerable: true,
|
|
50
50
|
get: function get() {
|
|
51
|
-
return
|
|
51
|
+
return _markers.flattenSquareMarkers;
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
|
-
Object.defineProperty(exports, "
|
|
54
|
+
Object.defineProperty(exports, "flattenTextMarkers", {
|
|
55
55
|
enumerable: true,
|
|
56
56
|
get: function get() {
|
|
57
|
-
return
|
|
57
|
+
return _markers.flattenTextMarkers;
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
|
-
Object.defineProperty(exports, "
|
|
60
|
+
Object.defineProperty(exports, "i18n", {
|
|
61
61
|
enumerable: true,
|
|
62
62
|
get: function get() {
|
|
63
|
-
return
|
|
63
|
+
return _i18n["default"];
|
|
64
64
|
}
|
|
65
65
|
});
|
|
66
|
-
Object.defineProperty(exports, "
|
|
66
|
+
Object.defineProperty(exports, "parseArrowMarkers", {
|
|
67
67
|
enumerable: true,
|
|
68
68
|
get: function get() {
|
|
69
|
-
return
|
|
69
|
+
return _markers.parseArrowMarkers;
|
|
70
70
|
}
|
|
71
71
|
});
|
|
72
|
-
Object.defineProperty(exports, "
|
|
72
|
+
Object.defineProperty(exports, "parseSquareMarkers", {
|
|
73
73
|
enumerable: true,
|
|
74
74
|
get: function get() {
|
|
75
|
-
return
|
|
75
|
+
return _markers.parseSquareMarkers;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
Object.defineProperty(exports, "parseTextMarkers", {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
get: function get() {
|
|
81
|
+
return _markers.parseTextMarkers;
|
|
76
82
|
}
|
|
77
83
|
});
|
|
78
84
|
|
|
@@ -84,6 +90,8 @@ var _Chessboard = _interopRequireDefault(require("./Chessboard"));
|
|
|
84
90
|
|
|
85
91
|
var _ErrorBox = _interopRequireDefault(require("./ErrorBox"));
|
|
86
92
|
|
|
93
|
+
var _Movetext = _interopRequireDefault(require("./Movetext"));
|
|
94
|
+
|
|
87
95
|
var _SquareMarkerIcon = _interopRequireDefault(require("./SquareMarkerIcon"));
|
|
88
96
|
|
|
89
97
|
var _TextMarkerIcon = _interopRequireDefault(require("./TextMarkerIcon"));
|
package/dist/lib/markers.js
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.flattenArrowMarkers = flattenArrowMarkers;
|
|
6
7
|
exports.flattenSquareMarkers = flattenSquareMarkers;
|
|
7
8
|
exports.flattenTextMarkers = flattenTextMarkers;
|
|
8
|
-
exports.
|
|
9
|
+
exports.parseArrowMarkers = parseArrowMarkers;
|
|
9
10
|
exports.parseSquareMarkers = parseSquareMarkers;
|
|
10
11
|
exports.parseTextMarkers = parseTextMarkers;
|
|
11
|
-
exports.parseArrowMarkers = parseArrowMarkers;
|
|
12
12
|
|
|
13
13
|
var _util = require("./impl/util");
|
|
14
14
|
|
|
@@ -50,8 +50,8 @@ function flattenSquareMarkers(markers) {
|
|
|
50
50
|
/**
|
|
51
51
|
* Transform a set of text markers defined as a "square -> (symbol, color)" struct into a comma-separated string.
|
|
52
52
|
*
|
|
53
|
-
* @param {object} markers For example: `{ e4: { symbol: 'A', color: 'g' }, d5: { symbol: 'z', color: 'r' }}`
|
|
54
|
-
* @returns {string} For example: `'Rzd5,GAe4'`
|
|
53
|
+
* @param {object} markers For example: `{ e4: { symbol: 'A', color: 'g' }, d5: { symbol: 'z', color: 'r' }, h3: { symbol: 'plus', color: 'y' } }`
|
|
54
|
+
* @returns {string} For example: `'Rzd5,GAe4,Y(plus)h3'`
|
|
55
55
|
*/
|
|
56
56
|
|
|
57
57
|
|
|
@@ -69,7 +69,7 @@ function flattenTextMarkers(markers) {
|
|
|
69
69
|
sq = _ref8[0],
|
|
70
70
|
desc = _ref8[1];
|
|
71
71
|
|
|
72
|
-
return desc.color.toUpperCase() + desc.symbol + sq;
|
|
72
|
+
return desc.color.toUpperCase() + (desc.symbol.length === 1 ? desc.symbol : '(' + desc.symbol + ')') + sq;
|
|
73
73
|
}).join(',');
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
@@ -130,17 +130,17 @@ function parseSquareMarkers(markers) {
|
|
|
130
130
|
/**
|
|
131
131
|
* Parse a set of text markers defined as a comma-separated string into a "square -> (symbol, color)" struct.
|
|
132
132
|
*
|
|
133
|
-
* @param {string} markers For example: `'Rzd5,GAe4'`
|
|
134
|
-
* @returns {object} For example: `{ e4: { symbol: 'A', color: 'g' }, d5: { symbol: 'z', color: 'r' }}`
|
|
133
|
+
* @param {string} markers For example: `'Rzd5,GAe4,Y(plus)h3'`
|
|
134
|
+
* @returns {object} For example: `{ e4: { symbol: 'A', color: 'g' }, d5: { symbol: 'z', color: 'r' }, h3: { symbol: 'plus', color: 'y' } }`
|
|
135
135
|
*/
|
|
136
136
|
|
|
137
137
|
|
|
138
138
|
function parseTextMarkers(markers) {
|
|
139
139
|
return parseMarkers(markers, function (token) {
|
|
140
|
-
return /^([GRY])([A-Za-z0-9])([a-h][1-8])$/.test(token) ? {
|
|
141
|
-
key: RegExp.$
|
|
140
|
+
return /^([GRY])(?:([A-Za-z0-9])|\((plus|times|dot|circle)\))([a-h][1-8])$/.test(token) ? {
|
|
141
|
+
key: RegExp.$4,
|
|
142
142
|
value: {
|
|
143
|
-
symbol: RegExp.$2,
|
|
143
|
+
symbol: RegExp.$2 || RegExp.$3,
|
|
144
144
|
color: RegExp.$1.toLowerCase()
|
|
145
145
|
}
|
|
146
146
|
} : undefined;
|
|
@@ -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 *
|
|
@@ -92,9 +92,7 @@ export default class Page extends React.Component {
|
|
|
92
92
|
</ButtonGroup>
|
|
93
93
|
</Stack>
|
|
94
94
|
<Box>
|
|
95
|
-
<Typography gutterBottom>
|
|
96
|
-
Edition mode
|
|
97
|
-
</Typography>
|
|
95
|
+
<Typography gutterBottom>Interaction mode</Typography>
|
|
98
96
|
<RadioGroup value={this.state.interactionMode} onChange={evt => this.set('interactionMode', evt.target.value)}>
|
|
99
97
|
<FormControlLabel value="" control={<Radio color="primary" />} label="None" />
|
|
100
98
|
<Stack direction="row" spacing={2} alignItems="center">
|
|
@@ -152,9 +150,10 @@ export default class Page extends React.Component {
|
|
|
152
150
|
if (this.state.interactionMode !== 'editTextMarkers') {
|
|
153
151
|
return undefined;
|
|
154
152
|
}
|
|
153
|
+
let availableSymbols = [ 'plus', 'times', 'dot', 'circle' ].concat([...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789']);
|
|
155
154
|
return (
|
|
156
155
|
<Select variant="standard" value={this.state.textMarkerSymbol} onChange={evt => this.set('textMarkerSymbol', evt.target.value)}>
|
|
157
|
-
{
|
|
156
|
+
{availableSymbols.map(mode => <MenuItem key={mode} value={mode}>{mode}</MenuItem>)}
|
|
158
157
|
</Select>
|
|
159
158
|
);
|
|
160
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 *
|
|
@@ -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,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,155 @@
|
|
|
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
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
render() {
|
|
57
|
+
return (
|
|
58
|
+
<Stack spacing={2} mt={2}>
|
|
59
|
+
{this.renderControls()}
|
|
60
|
+
{this.renderMovetext()}
|
|
61
|
+
{this.renderCode()}
|
|
62
|
+
{this.renderNavigationBoard()}
|
|
63
|
+
</Stack>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
renderControls() {
|
|
68
|
+
return (<>
|
|
69
|
+
<Stack direction="row" spacing={2} alignItems="center">
|
|
70
|
+
<ButtonGroup color="primary" size="small">
|
|
71
|
+
<Button onClick={() => this.set('pgn', game1, 'selection', '28b')}>Game 1</Button>
|
|
72
|
+
<Button onClick={() => this.set('pgn', game2, 'selection', '15b')}>Game 2</Button>
|
|
73
|
+
</ButtonGroup>
|
|
74
|
+
</Stack>
|
|
75
|
+
<Box>
|
|
76
|
+
<Typography gutterBottom>Interaction mode</Typography>
|
|
77
|
+
<RadioGroup value={this.state.interactionMode} onChange={evt => this.set('interactionMode', evt.target.value)}>
|
|
78
|
+
<FormControlLabel value="" control={<Radio color="primary" />} label="None" />
|
|
79
|
+
<FormControlLabel value="selectMove" control={<Radio color="primary" />} label="Select moves" />
|
|
80
|
+
</RadioGroup>
|
|
81
|
+
</Box>
|
|
82
|
+
</>);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
renderMovetext() {
|
|
86
|
+
return (
|
|
87
|
+
<Box>
|
|
88
|
+
<Movetext
|
|
89
|
+
game={this.state.pgn}
|
|
90
|
+
selection={this.state.selection}
|
|
91
|
+
pieceSymbols="figurines"
|
|
92
|
+
diagramVisible={false}
|
|
93
|
+
interactionMode={this.state.interactionMode}
|
|
94
|
+
onMoveSelected={nodeId => this.handleMoveSelected(nodeId)}
|
|
95
|
+
/>
|
|
96
|
+
</Box>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
renderCode() {
|
|
101
|
+
let attributes = [];
|
|
102
|
+
attributes.push('game={pgn}');
|
|
103
|
+
attributes.push('pieceSymbols="figurines"');
|
|
104
|
+
attributes.push('diagramVisible={false}');
|
|
105
|
+
attributes.push(`selection="${this.state.selection}"`);
|
|
106
|
+
switch(this.state.interactionMode) {
|
|
107
|
+
case 'selectMove':
|
|
108
|
+
attributes.push('interactionMode="selectMove"');
|
|
109
|
+
attributes.push('onMoveSelected={nodeId => handleMoveSelected(nodeId)}');
|
|
110
|
+
break;
|
|
111
|
+
default:
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
let pgnDeclaration = 'const pgn = `\n' + this.state.pgn.trim() + '`;\n\n';
|
|
115
|
+
return <pre className="kokopu-demoCode">{pgnDeclaration + buildComponentDemoCode('Movetext', attributes)}</pre>;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
renderNavigationBoard() {
|
|
119
|
+
let button = <Button size="small" onClick={() => this.handlePopupToggled()}>{this.state.withPopup ? 'Reduce' : 'Open'}</Button>;
|
|
120
|
+
let { position, csl, cal } = this.getCurrentPositionAndAnnotations();
|
|
121
|
+
let content = this.state.withPopup ? <Stack><Chessboard position={position} squareMarkers={csl} arrowMarkers={cal} />{button}</Stack> : button;
|
|
122
|
+
return <Paper className="kokopu-fixedPopup" elevation={3}>{content}</Paper>;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
handleMoveSelected(nodeId) {
|
|
126
|
+
if (nodeId) {
|
|
127
|
+
this.set('selection', nodeId);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
handlePopupToggled() {
|
|
132
|
+
this.set('withPopup', !this.state.withPopup);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
set(attributeName, newValue, attributeName2, newValue2) {
|
|
136
|
+
let newState = {};
|
|
137
|
+
newState[attributeName] = newValue;
|
|
138
|
+
if (attributeName2) {
|
|
139
|
+
newState[attributeName2] = newValue2;
|
|
140
|
+
}
|
|
141
|
+
this.setState(newState);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
getCurrentPositionAndAnnotations() {
|
|
145
|
+
let game = kokopu.pgnRead(this.state.pgn, 0);
|
|
146
|
+
if (this.state.selection === 'start') {
|
|
147
|
+
let mainVariation = game.mainVariation();
|
|
148
|
+
return { position: mainVariation.initialPosition(), csl: mainVariation.tag('csl'), cal: mainVariation.tag('cal') };
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
let node = game.findById(this.state.selection);
|
|
152
|
+
return { position: node.position(), csl: node.tag('csl'), cal: node.tag('cal') };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
package/doc_src/demo/demo.css
CHANGED
|
@@ -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
|
+
}
|