kokopu-react 3.4.0 → 3.4.2
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 +8 -0
- package/dist/lib/icons/ChessPieceIcon.js +4 -4
- package/dist/lib/icons/ChessPieceIcon.js.map +1 -1
- package/dist/lib/navigationboard/NavigationBoard.d.ts +1 -1
- package/doc_src/demo/PageChessboardBase.tsx +3 -3
- package/doc_src/demo/PageChessboardInteraction.tsx +6 -6
- package/doc_src/demo/PageChessboardMove.tsx +3 -3
- package/doc_src/demo/PageChessboardSmallScreens.tsx +1 -1
- package/doc_src/demo/PageMovetextBase.tsx +5 -5
- package/doc_src/demo/PageMovetextInteraction.tsx +2 -2
- package/doc_src/demo/PageNavigationBoardBase.tsx +4 -4
- package/doc_src/demo/PageNavigationBoardUncontrolledVsControlled.tsx +6 -6
- package/doc_src/demo/PageSynchroNavigationBoardMovetext.tsx +2 -2
- package/doc_src/demo/decs.d.ts +2 -0
- package/doc_src/demo/tsconfig.json +8 -0
- package/package.json +27 -30
- package/scripts/doc.styleguide.config.js +6 -3
- package/scripts/test-graphic.webpack.config.js +1 -1
- package/src/decs.d.ts +2 -0
- package/src/icons/ChessPieceIcon.tsx +5 -5
- package/test/01_types.js +81 -82
- package/test/02_chessboard_util.js +12 -12
- package/test/11_movetext_interaction.js +7 -7
- package/test/12_navigation_board_base.js +2 -2
- package/test/common/graphic.js +4 -4
- package/test/graphic_test_app/common/decs.d.ts +2 -0
- package/test/graphic_test_app/tsconfig.json +8 -0
- package/tsconfig.json +2 -3
- package/scripts/doc.tsconfig.json +0 -7
- package/scripts/test-graphic.tsconfig.json +0 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
ChangeLog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
+
3.4.2 (July 18, 2026)
|
|
5
|
+
---------------------
|
|
6
|
+
* Minor fixes.
|
|
7
|
+
|
|
8
|
+
3.4.1 (May 10, 2026)
|
|
9
|
+
--------------------
|
|
10
|
+
* Minor fixes.
|
|
11
|
+
|
|
4
12
|
3.4.0 (January 11, 2026)
|
|
5
13
|
------------------------
|
|
6
14
|
* Add an optional sound effect when a move is displayed in `Chessboard` or `NavigationBoard`.
|
|
@@ -30,16 +30,16 @@ import { piecesets, DEFAULT_PIECESET } from '../chessboard/piecesets';
|
|
|
30
30
|
*/
|
|
31
31
|
export function ChessPieceIcon({ size, type, pieceset = DEFAULT_PIECESET }) {
|
|
32
32
|
// Sanitize the inputs.
|
|
33
|
-
|
|
33
|
+
const localSize = sanitizeBoundedInteger(size, MIN_SQUARE_SIZE, MAX_SQUARE_SIZE, () => new IllegalArgument('ChessPieceIcon', 'size'));
|
|
34
34
|
const types = sanitizeChessPieceIconType(type, () => new IllegalArgument('ChessPieceIcon', 'type'));
|
|
35
35
|
const piecesetData = piecesets[pieceset];
|
|
36
36
|
if (!piecesetData) {
|
|
37
37
|
throw new IllegalArgument('ChessPieceIcon', 'pieceset');
|
|
38
38
|
}
|
|
39
39
|
// Render the component.
|
|
40
|
-
const width =
|
|
41
|
-
const viewBox = `0 0 ${width} ${
|
|
42
|
-
return (React.createElement("svg", { className: "kokopu-chessPieceIcon", viewBox: viewBox, width: width, height:
|
|
40
|
+
const width = localSize * types.length;
|
|
41
|
+
const viewBox = `0 0 ${width} ${localSize}`;
|
|
42
|
+
return (React.createElement("svg", { className: "kokopu-chessPieceIcon", viewBox: viewBox, width: width, height: localSize }, types.map((t, i) => React.createElement("image", { key: i, x: i * localSize, y: 0, width: localSize, height: localSize, href: piecesetData[t] }))));
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
45
|
* Sanitization method for the small-screen limits parameter.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChessPieceIcon.js","sourceRoot":"","sources":["../../../src/icons/ChessPieceIcon.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;gFAqBgF;AAGhF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAsB,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACtG,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAsBtE;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,GAAG,gBAAgB,EAAuB;IAE3F,uBAAuB;IACvB,
|
|
1
|
+
{"version":3,"file":"ChessPieceIcon.js","sourceRoot":"","sources":["../../../src/icons/ChessPieceIcon.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;gFAqBgF;AAGhF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAsB,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACtG,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAsBtE;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,GAAG,gBAAgB,EAAuB;IAE3F,uBAAuB;IACvB,MAAM,SAAS,GAAG,sBAAsB,CAAC,IAAI,EAAE,eAAe,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,IAAI,eAAe,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;IACtI,MAAM,KAAK,GAAG,0BAA0B,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,eAAe,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;IACpG,MAAM,YAAY,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,CAAC,YAAY,EAAE,CAAC;QAChB,MAAM,IAAI,eAAe,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;IAC5D,CAAC;IAED,wBAAwB;IACxB,MAAM,KAAK,GAAG,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;IACvC,MAAM,OAAO,GAAG,OAAO,KAAK,IAAI,SAAS,EAAE,CAAC;IAC5C,OAAO,CACH,6BAAK,SAAS,EAAC,uBAAuB,EAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,IACnF,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,+BAAO,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,GAAI,CAAC,CACzH,CACT,CAAC;AACN,CAAC;AAGD;;GAEG;AACH,SAAS,0BAA0B,CAAC,IAA+C,EAAE,gBAAuC;IACxH,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YAChB,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC3B,MAAM,gBAAgB,EAAE,CAAC;YAC7B,CAAC;YACD,OAAO,CAAC,CAAC;QACb,CAAC,CAAC,CAAC;IACP,CAAC;SACI,IAAI,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,OAAO,CAAE,IAAI,CAAE,CAAC;IACpB,CAAC;SACI,CAAC;QACF,MAAM,gBAAgB,EAAE,CAAC;IAC7B,CAAC;AACL,CAAC"}
|
|
@@ -151,7 +151,7 @@ export declare class NavigationBoard extends React.Component<NavigationBoardProp
|
|
|
151
151
|
turnVisible: boolean;
|
|
152
152
|
colorset: string;
|
|
153
153
|
pieceset: string;
|
|
154
|
-
smallScreenLimits?: import("
|
|
154
|
+
smallScreenLimits?: import("..").SmallScreenLimit[];
|
|
155
155
|
};
|
|
156
156
|
private navigationFieldRef;
|
|
157
157
|
private timeoutId?;
|
|
@@ -77,7 +77,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
77
77
|
|
|
78
78
|
render() {
|
|
79
79
|
return (
|
|
80
|
-
<Stack spacing={2}
|
|
80
|
+
<Stack spacing={2} sx={{ mt: 2 }}>
|
|
81
81
|
{this.renderControls()}
|
|
82
82
|
{this.renderChessboard()}
|
|
83
83
|
{this.renderCode()}
|
|
@@ -88,7 +88,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
88
88
|
private renderControls() {
|
|
89
89
|
return (
|
|
90
90
|
<>
|
|
91
|
-
<Stack direction="row" spacing={2} alignItems
|
|
91
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
92
92
|
<FormControlLabel
|
|
93
93
|
label="Flip"
|
|
94
94
|
control={<Switch checked={this.state.flipped} onChange={() => this.setState({ flipped: !this.state.flipped })} color="primary" />}
|
|
@@ -113,7 +113,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
113
113
|
min={Chessboard.minSquareSize()} max={Chessboard.maxSquareSize()} step={1} valueLabelDisplay="on" color="primary"
|
|
114
114
|
/>
|
|
115
115
|
</Box>
|
|
116
|
-
<Stack direction="row" spacing={2} alignItems
|
|
116
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
117
117
|
<FormControl variant="standard">
|
|
118
118
|
<InputLabel id="colorset-label">Colorset</InputLabel>
|
|
119
119
|
<Select labelId="colorset-label" sx={{ width: '8em' }} value={this.state.colorset} onChange={evt => this.setState({ colorset: evt.target.value })}>
|
|
@@ -87,7 +87,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
87
87
|
|
|
88
88
|
render() {
|
|
89
89
|
return (
|
|
90
|
-
<Stack spacing={2}
|
|
90
|
+
<Stack spacing={2} sx={{ mt: 2 }}>
|
|
91
91
|
{this.renderControls()}
|
|
92
92
|
{this.renderChessboard()}
|
|
93
93
|
{this.renderCode()}
|
|
@@ -98,7 +98,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
98
98
|
private renderControls() {
|
|
99
99
|
return (
|
|
100
100
|
<>
|
|
101
|
-
<Stack direction="row" spacing={2} alignItems
|
|
101
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
102
102
|
<FormControlLabel
|
|
103
103
|
label="Flip"
|
|
104
104
|
control={<Switch checked={this.state.flipped} onChange={() => this.setState({ flipped: !this.state.flipped })} color="primary" />}
|
|
@@ -118,7 +118,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
118
118
|
<FormControlLabel
|
|
119
119
|
value="addRemovePieces" control={<Radio color="primary" />}
|
|
120
120
|
label={(
|
|
121
|
-
<Stack direction="row" spacing={2} alignItems
|
|
121
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
122
122
|
<span>Add/remove pieces</span>
|
|
123
123
|
{this.renderPieceSelector()}
|
|
124
124
|
</Stack>
|
|
@@ -129,7 +129,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
129
129
|
<FormControlLabel
|
|
130
130
|
value="editSquareMarkers" control={<Radio color="primary" />}
|
|
131
131
|
label={(
|
|
132
|
-
<Stack direction="row" spacing={2} alignItems
|
|
132
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
133
133
|
<span>Edit square annotations</span>
|
|
134
134
|
{this.renderMarkerColorSelector('editSquareMarkers', this.state.squareMarkerColor, newColor => this.handleSquareMarkerColorChanged(newColor))}
|
|
135
135
|
</Stack>
|
|
@@ -138,7 +138,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
138
138
|
<FormControlLabel
|
|
139
139
|
value="editTextMarkers" control={<Radio color="primary" />}
|
|
140
140
|
label={(
|
|
141
|
-
<Stack direction="row" spacing={2} alignItems
|
|
141
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
142
142
|
<span>Edit text annotations</span>
|
|
143
143
|
{this.renderMarkerColorSelector('editTextMarkers', this.state.textMarkerColor, newColor => this.handleTextMarkerColorChanged(newColor))}
|
|
144
144
|
{this.renderTextMarkerSymbolSelector()}
|
|
@@ -148,7 +148,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
148
148
|
<FormControlLabel
|
|
149
149
|
value="editArrowMarkers" control={<Radio color="primary" />}
|
|
150
150
|
label={(
|
|
151
|
-
<Stack direction="row" spacing={2} alignItems
|
|
151
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
152
152
|
<span>Edit arrow annotations</span>
|
|
153
153
|
{this.renderMarkerColorSelector('editArrowMarkers', this.state.arrowMarkerColor, newColor => this.handleArrowMarkerColorChanged(newColor))}
|
|
154
154
|
</Stack>
|
|
@@ -78,7 +78,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
78
78
|
|
|
79
79
|
render() {
|
|
80
80
|
return (
|
|
81
|
-
<Stack spacing={2}
|
|
81
|
+
<Stack spacing={2} sx={{ mt: 2 }}>
|
|
82
82
|
{this.renderControls()}
|
|
83
83
|
{this.renderChessboard()}
|
|
84
84
|
{this.renderCode()}
|
|
@@ -89,7 +89,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
89
89
|
private renderControls() {
|
|
90
90
|
return (
|
|
91
91
|
<>
|
|
92
|
-
<Stack direction="row" spacing={2} alignItems
|
|
92
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
93
93
|
<FormControlLabel
|
|
94
94
|
label="Flip"
|
|
95
95
|
control={<Switch checked={this.state.flipped} onChange={() => this.setState({ flipped: !this.state.flipped })} color="primary" />}
|
|
@@ -108,7 +108,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
108
108
|
/>
|
|
109
109
|
{this.renderColorSelector()}
|
|
110
110
|
</Stack>
|
|
111
|
-
<Stack direction="row" spacing={2} alignItems
|
|
111
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
112
112
|
<TextField label="Move" variant="standard" value={this.state.editedMove} onChange={evt => this.setState({ editedMove: evt.target.value })} />
|
|
113
113
|
<Button color="primary" size="small" variant="contained" onClick={() => this.handlePlayClicked()}>Play</Button>
|
|
114
114
|
<ButtonGroup color="primary" size="small">
|
|
@@ -87,7 +87,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
87
87
|
|
|
88
88
|
render() {
|
|
89
89
|
return (
|
|
90
|
-
<Stack spacing={2}
|
|
90
|
+
<Stack spacing={2} sx={{ mt: 2 }}>
|
|
91
91
|
{this.renderControls()}
|
|
92
92
|
{this.renderMovetext()}
|
|
93
93
|
{this.renderCode()}
|
|
@@ -99,7 +99,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
99
99
|
const opts = this.state.diagramOptions;
|
|
100
100
|
return (
|
|
101
101
|
<>
|
|
102
|
-
<Stack direction="row" spacing={2} alignItems
|
|
102
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
103
103
|
<ButtonGroup color="primary" size="small">
|
|
104
104
|
<Button onClick={() => this.setState({ pgn: game1 })}>Game 1</Button>
|
|
105
105
|
<Button onClick={() => this.setState({ pgn: game2 })}>Game 2</Button>
|
|
@@ -114,7 +114,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
114
114
|
control={<Switch checked={this.state.diagramVisible} onChange={() => this.setState({ diagramVisible: !this.state.diagramVisible })} color="primary" />}
|
|
115
115
|
/>
|
|
116
116
|
</Stack>
|
|
117
|
-
<Stack direction="row" spacing={2} alignItems
|
|
117
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
118
118
|
<FormControl variant="standard">
|
|
119
119
|
<InputLabel id="piecesymbols-label">Piece symbols</InputLabel>
|
|
120
120
|
<Select
|
|
@@ -128,7 +128,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
128
128
|
</FormControl>
|
|
129
129
|
{this.renderCustomSymbolSelector()}
|
|
130
130
|
</Stack>
|
|
131
|
-
<Stack direction="row" spacing={2} alignItems
|
|
131
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
132
132
|
<FormControlLabel
|
|
133
133
|
label="Flip diagram(s)"
|
|
134
134
|
control={<Switch checked={opts.flipped} onChange={() => this.setDiagramOption({ flipped: !opts.flipped })} color="primary" />}
|
|
@@ -142,7 +142,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
142
142
|
control={<Switch checked={opts.turnVisible} onChange={() => this.setDiagramOption({ turnVisible: !opts.turnVisible })} color="primary" />}
|
|
143
143
|
/>
|
|
144
144
|
</Stack>
|
|
145
|
-
<Stack direction="row" spacing={2} alignItems
|
|
145
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
146
146
|
<FormControl variant="standard">
|
|
147
147
|
<InputLabel id="colorset-label">Colorset</InputLabel>
|
|
148
148
|
<Select labelId="colorset-label" sx={{ width: '8em' }} value={opts.colorset} onChange={evt => this.setDiagramOption({ colorset: evt.target.value })}>
|
|
@@ -65,7 +65,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
65
65
|
|
|
66
66
|
render() {
|
|
67
67
|
return (
|
|
68
|
-
<Stack spacing={2}
|
|
68
|
+
<Stack spacing={2} sx={{ mt: 2 }}>
|
|
69
69
|
{this.renderControls()}
|
|
70
70
|
{this.renderMovetext()}
|
|
71
71
|
{this.renderCode()}
|
|
@@ -77,7 +77,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
77
77
|
private renderControls() {
|
|
78
78
|
return (
|
|
79
79
|
<>
|
|
80
|
-
<Stack direction="row" spacing={2} alignItems
|
|
80
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
81
81
|
<ButtonGroup color="primary" size="small">
|
|
82
82
|
<Button onClick={() => this.setState({ pgn: game1, selection: '28b' })}>Game 1</Button>
|
|
83
83
|
<Button onClick={() => this.setState({ pgn: game2, selection: '15b' })}>Game 2</Button>
|
|
@@ -83,7 +83,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
83
83
|
|
|
84
84
|
render() {
|
|
85
85
|
return (
|
|
86
|
-
<Stack spacing={2}
|
|
86
|
+
<Stack spacing={2} sx={{ mt: 2 }}>
|
|
87
87
|
{this.renderControls()}
|
|
88
88
|
{this.renderNavigationBoard()}
|
|
89
89
|
{this.renderCode()}
|
|
@@ -94,7 +94,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
94
94
|
private renderControls() {
|
|
95
95
|
return (
|
|
96
96
|
<>
|
|
97
|
-
<Stack direction="row" spacing={2} alignItems
|
|
97
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
98
98
|
<FormControlLabel
|
|
99
99
|
label="Show play/stop button"
|
|
100
100
|
control={<Switch checked={this.state.playButtonVisible} onChange={() => this.setState({ playButtonVisible: !this.state.playButtonVisible })} color="primary" />}
|
|
@@ -112,7 +112,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
112
112
|
control={<Switch checked={this.state.turnVisible} onChange={() => this.setState({ turnVisible: !this.state.turnVisible })} color="primary" />}
|
|
113
113
|
/>
|
|
114
114
|
</Stack>
|
|
115
|
-
<Stack direction="row" spacing={2} alignItems
|
|
115
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
116
116
|
<FormControlLabel
|
|
117
117
|
label="Animation"
|
|
118
118
|
control={<Switch checked={this.state.animated} onChange={() => this.setState({ animated: !this.state.animated })} color="primary" />}
|
|
@@ -129,7 +129,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
129
129
|
min={Chessboard.minSquareSize()} max={Chessboard.maxSquareSize()} step={1} valueLabelDisplay="on" color="primary"
|
|
130
130
|
/>
|
|
131
131
|
</Box>
|
|
132
|
-
<Stack direction="row" spacing={2} alignItems
|
|
132
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
133
133
|
<FormControl variant="standard">
|
|
134
134
|
<InputLabel id="colorset-label">Colorset</InputLabel>
|
|
135
135
|
<Select labelId="colorset-label" sx={{ width: '8em' }} value={this.state.colorset} onChange={evt => this.setState({ colorset: evt.target.value })}>
|
|
@@ -51,7 +51,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
51
51
|
|
|
52
52
|
render() {
|
|
53
53
|
return (
|
|
54
|
-
<Stack spacing={2}
|
|
54
|
+
<Stack spacing={2} sx={{ mt: 2 }}>
|
|
55
55
|
{this.renderControls()}
|
|
56
56
|
{this.renderNavigationBoards()}
|
|
57
57
|
{this.renderCode()}
|
|
@@ -81,17 +81,17 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
81
81
|
|
|
82
82
|
private renderNavigationBoards() {
|
|
83
83
|
return (
|
|
84
|
-
<
|
|
84
|
+
<Stack direction="row" sx={{ alignItems: 'top', justifyContent: 'space-around' }}>
|
|
85
85
|
<Box>
|
|
86
86
|
<NavigationBoard game={pgn} animated sound initialNodeId="9b" />
|
|
87
|
-
<Typography
|
|
87
|
+
<Typography sx={{ mt: 2, textAlign: 'center' }}>Uncontrolled</Typography>
|
|
88
88
|
</Box>
|
|
89
89
|
<Box>
|
|
90
90
|
<NavigationBoard game={pgn} animated sound nodeId={this.state.nodeId} onNodeIdChanged={nodeId => this.setState({ nodeId: nodeId })} />
|
|
91
|
-
<Typography
|
|
92
|
-
<Typography textAlign
|
|
91
|
+
<Typography sx={{ mt: 2, textAlign: 'center' }}>Controlled</Typography>
|
|
92
|
+
<Typography sx={{ textAlign: 'center' }}>{`Current node ID: ${this.state.nodeId}`}</Typography>
|
|
93
93
|
</Box>
|
|
94
|
-
</
|
|
94
|
+
</Stack>
|
|
95
95
|
);
|
|
96
96
|
}
|
|
97
97
|
|
|
@@ -74,7 +74,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
74
74
|
|
|
75
75
|
render() {
|
|
76
76
|
return (
|
|
77
|
-
<Stack spacing={2}
|
|
77
|
+
<Stack spacing={2} sx={{ mt: 2 }}>
|
|
78
78
|
{this.renderControls()}
|
|
79
79
|
{this.renderNavigationBoardWithMovetext()}
|
|
80
80
|
{this.renderCode()}
|
|
@@ -84,7 +84,7 @@ export default class Page extends React.Component<object, PageState> {
|
|
|
84
84
|
|
|
85
85
|
private renderControls() {
|
|
86
86
|
return (
|
|
87
|
-
<Stack direction="row" spacing={2} alignItems
|
|
87
|
+
<Stack direction="row" spacing={2} sx={{ alignItems: 'center' }}>
|
|
88
88
|
<ButtonGroup color="primary" size="small">
|
|
89
89
|
<Button onClick={() => this.setState({ componentKey: 'game1', pgn: game1 })}>Game 1</Button>
|
|
90
90
|
<Button onClick={() => this.setState({ componentKey: 'game2', pgn: game2 })}>Game 2</Button>
|
package/doc_src/demo/decs.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kokopu-react",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.2",
|
|
4
4
|
"description": "A React-based library to create and display chessboard and chess-related components.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chess",
|
|
@@ -20,9 +20,7 @@
|
|
|
20
20
|
"dist/lib",
|
|
21
21
|
"doc_src",
|
|
22
22
|
"scripts/doc.styleguide.config.js",
|
|
23
|
-
"scripts/doc.tsconfig.json",
|
|
24
23
|
"scripts/docker-compose.yml",
|
|
25
|
-
"scripts/test-graphic.tsconfig.json",
|
|
26
24
|
"scripts/test-graphic.webpack.config.js",
|
|
27
25
|
"scripts/test-headless.webpack.config.js",
|
|
28
26
|
"src",
|
|
@@ -43,44 +41,43 @@
|
|
|
43
41
|
"htmlparser2": "^9.1.0"
|
|
44
42
|
},
|
|
45
43
|
"devDependencies": {
|
|
46
|
-
"@babel/preset-env": "^
|
|
47
|
-
"@babel/preset-react": "^
|
|
44
|
+
"@babel/preset-env": "^8.0.2",
|
|
45
|
+
"@babel/preset-react": "^8.0.1",
|
|
48
46
|
"@emotion/react": "^11.14.0",
|
|
49
47
|
"@emotion/styled": "^11.14.1",
|
|
50
|
-
"@eslint/js": "^9.39.
|
|
51
|
-
"@mui/material": "^
|
|
52
|
-
"@stylistic/eslint-plugin": "^5.
|
|
53
|
-
"@types/react": "^19.2.
|
|
48
|
+
"@eslint/js": "^9.39.5",
|
|
49
|
+
"@mui/material": "^9.2.0",
|
|
50
|
+
"@stylistic/eslint-plugin": "^5.10.0",
|
|
51
|
+
"@types/react": "^19.2.17",
|
|
54
52
|
"@types/react-dom": "^19.2.3",
|
|
55
|
-
"babel-loader": "^10.
|
|
56
|
-
"copy-webpack-plugin": "^
|
|
53
|
+
"babel-loader": "^10.1.1",
|
|
54
|
+
"copy-webpack-plugin": "^14.0.0",
|
|
57
55
|
"copyfiles": "^2.4.1",
|
|
58
56
|
"coverage-istanbul-loader": "^3.0.5",
|
|
59
|
-
"css-loader": "^7.1.
|
|
60
|
-
"eslint": "^9.39.
|
|
57
|
+
"css-loader": "^7.1.4",
|
|
58
|
+
"eslint": "^9.39.5",
|
|
61
59
|
"eslint-plugin-react": "^7.37.5",
|
|
62
|
-
"eslint-plugin-react-hooks": "^7.
|
|
63
|
-
"globals": "^17.
|
|
64
|
-
"html-webpack-plugin": "^5.6.
|
|
60
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
61
|
+
"globals": "^17.7.0",
|
|
62
|
+
"html-webpack-plugin": "^5.6.7",
|
|
65
63
|
"img-diff-js": "^0.5.4",
|
|
66
|
-
"kokopu": "^4.13.
|
|
67
|
-
"mocha": "^11.7.
|
|
64
|
+
"kokopu": "^4.13.4",
|
|
65
|
+
"mocha": "^11.7.6",
|
|
68
66
|
"null-loader": "^4.0.1",
|
|
69
|
-
"nyc": "^
|
|
70
|
-
"react": "^19.2.
|
|
67
|
+
"nyc": "^18.0.0",
|
|
68
|
+
"react": "^19.2.7",
|
|
71
69
|
"react-docgen-typescript": "~2.2.2",
|
|
72
|
-
"react-dom": "^19.2.
|
|
70
|
+
"react-dom": "^19.2.7",
|
|
73
71
|
"react-styleguidist": "^13.1.4",
|
|
74
|
-
"rimraf": "^6.1.
|
|
75
|
-
"selenium-webdriver": "^4.
|
|
76
|
-
"ssh2-sftp-client": "^12.
|
|
72
|
+
"rimraf": "^6.1.3",
|
|
73
|
+
"selenium-webdriver": "^4.46.0",
|
|
74
|
+
"ssh2-sftp-client": "^12.1.1",
|
|
77
75
|
"style-loader": "^4.0.0",
|
|
78
|
-
"ts-loader": "^9.
|
|
79
|
-
"typescript": "^
|
|
80
|
-
"typescript-eslint": "^8.
|
|
81
|
-
"
|
|
82
|
-
"webpack": "^
|
|
83
|
-
"webpack-cli": "^6.0.1"
|
|
76
|
+
"ts-loader": "^9.6.2",
|
|
77
|
+
"typescript": "^6.0.3",
|
|
78
|
+
"typescript-eslint": "^8.64.0",
|
|
79
|
+
"webpack": "^5.108.4",
|
|
80
|
+
"webpack-cli": "^7.2.1"
|
|
84
81
|
},
|
|
85
82
|
"scripts": {
|
|
86
83
|
"lint": "eslint doc_src src test",
|
|
@@ -112,20 +112,23 @@ module.exports = {
|
|
|
112
112
|
module: {
|
|
113
113
|
rules: [
|
|
114
114
|
{
|
|
115
|
-
test: /\.js$/i,
|
|
115
|
+
test: /\.m?js$/i,
|
|
116
116
|
use: {
|
|
117
117
|
loader: 'babel-loader',
|
|
118
118
|
options: {
|
|
119
119
|
presets: [ '@babel/preset-env', '@babel/preset-react' ],
|
|
120
120
|
},
|
|
121
|
-
}
|
|
121
|
+
},
|
|
122
|
+
resolve: {
|
|
123
|
+
fullySpecified: false,
|
|
124
|
+
},
|
|
122
125
|
},
|
|
123
126
|
{
|
|
124
127
|
test: /\.tsx?$/i,
|
|
125
128
|
use: {
|
|
126
129
|
loader: 'ts-loader',
|
|
127
130
|
options: {
|
|
128
|
-
configFile: path.resolve(__dirname,
|
|
131
|
+
configFile: path.resolve(__dirname, `${docSrcDir}/demo/tsconfig.json`),
|
|
129
132
|
},
|
|
130
133
|
},
|
|
131
134
|
},
|
package/src/decs.d.ts
CHANGED
|
@@ -55,7 +55,7 @@ export interface ChessPieceIconProps {
|
|
|
55
55
|
export function ChessPieceIcon({ size, type, pieceset = DEFAULT_PIECESET }: ChessPieceIconProps) {
|
|
56
56
|
|
|
57
57
|
// Sanitize the inputs.
|
|
58
|
-
|
|
58
|
+
const localSize = sanitizeBoundedInteger(size, MIN_SQUARE_SIZE, MAX_SQUARE_SIZE, () => new IllegalArgument('ChessPieceIcon', 'size'));
|
|
59
59
|
const types = sanitizeChessPieceIconType(type, () => new IllegalArgument('ChessPieceIcon', 'type'));
|
|
60
60
|
const piecesetData = piecesets[pieceset];
|
|
61
61
|
if (!piecesetData) {
|
|
@@ -63,11 +63,11 @@ export function ChessPieceIcon({ size, type, pieceset = DEFAULT_PIECESET }: Ches
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// Render the component.
|
|
66
|
-
const width =
|
|
67
|
-
const viewBox = `0 0 ${width} ${
|
|
66
|
+
const width = localSize * types.length;
|
|
67
|
+
const viewBox = `0 0 ${width} ${localSize}`;
|
|
68
68
|
return (
|
|
69
|
-
<svg className="kokopu-chessPieceIcon" viewBox={viewBox} width={width} height={
|
|
70
|
-
{types.map((t, i) => <image key={i} x={i *
|
|
69
|
+
<svg className="kokopu-chessPieceIcon" viewBox={viewBox} width={width} height={localSize}>
|
|
70
|
+
{types.map((t, i) => <image key={i} x={i * localSize} y={0} width={localSize} height={localSize} href={piecesetData[t]} />)}
|
|
71
71
|
</svg>
|
|
72
72
|
);
|
|
73
73
|
}
|
package/test/01_types.js
CHANGED
|
@@ -24,14 +24,14 @@
|
|
|
24
24
|
|
|
25
25
|
const { exception, isPieceSymbolMapping, isAnnotationSymbol, isAnnotationColor, flattenSquareMarkers, parseSquareMarkers, flattenTextMarkers, parseTextMarkers,
|
|
26
26
|
flattenArrowMarkers, parseArrowMarkers } = require('../build/test_headless/index');
|
|
27
|
-
const
|
|
27
|
+
const assert = require('node:assert/strict');
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
describe('Is piece symbol mapping', () => {
|
|
31
31
|
|
|
32
32
|
function itIsPieceSymbolMapping(label, value, expected) {
|
|
33
33
|
it(label, () => {
|
|
34
|
-
|
|
34
|
+
assert.deepEqual(isPieceSymbolMapping(value), expected);
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -50,7 +50,7 @@ describe('Is Annotation symbol', () => {
|
|
|
50
50
|
|
|
51
51
|
function itIsAnnotationSymbol(label, value, expected) {
|
|
52
52
|
it(label, () => {
|
|
53
|
-
|
|
53
|
+
assert.deepEqual(isAnnotationSymbol(value), expected);
|
|
54
54
|
});
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -71,7 +71,7 @@ describe('Is Annotation color', () => {
|
|
|
71
71
|
|
|
72
72
|
function itIsAnnotationColor(label, value, expected) {
|
|
73
73
|
it(label, () => {
|
|
74
|
-
|
|
74
|
+
assert.deepEqual(isAnnotationColor(value), expected);
|
|
75
75
|
});
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -89,114 +89,114 @@ describe('Is Annotation color', () => {
|
|
|
89
89
|
|
|
90
90
|
describe('Flatten square markers', () => {
|
|
91
91
|
|
|
92
|
-
it('Re4', () => {
|
|
93
|
-
it('Gd3,Yh8', () => {
|
|
94
|
-
it('Ga1,Yc5,Rd2,Bh7,Yh8', () => {
|
|
95
|
-
it('<empty>', () => {
|
|
92
|
+
it('Re4', () => { assert.deepEqual(flattenSquareMarkers({ e4: 'r' }), 'Re4'); });
|
|
93
|
+
it('Gd3,Yh8', () => { assert.deepEqual(flattenSquareMarkers({ h8: 'y', d3: 'g' }), 'Gd3,Yh8'); });
|
|
94
|
+
it('Ga1,Yc5,Rd2,Bh7,Yh8', () => { assert.deepEqual(flattenSquareMarkers({ c5: 'y', h8: 'y', a1: 'g', h7: 'b', d2: 'r' }), 'Ga1,Yc5,Rd2,Bh7,Yh8'); });
|
|
95
|
+
it('<empty>', () => { assert.deepEqual(flattenSquareMarkers({}), ''); });
|
|
96
96
|
|
|
97
|
-
it('Wrong square', () => {
|
|
98
|
-
it('Wrong color', () => {
|
|
97
|
+
it('Wrong square', () => { assert.deepEqual(flattenSquareMarkers({ e1: 'r', k9: 'g', whatever: 'y' }), 'Re1'); });
|
|
98
|
+
it('Wrong color', () => { assert.deepEqual(flattenSquareMarkers({ a2: 'g', b5: 'R', c4: 42, h8: 'yellow' }), 'Ga2'); });
|
|
99
99
|
|
|
100
|
-
it('Wrong type (not an object)', () => {
|
|
101
|
-
it('Wrong type (null)', () => {
|
|
102
|
-
it('Wrong type (undefined)', () => {
|
|
100
|
+
it('Wrong type (not an object)', () => { assert.throws(() => flattenSquareMarkers('whatever'), exception.IllegalArgument); });
|
|
101
|
+
it('Wrong type (null)', () => { assert.throws(() => flattenSquareMarkers(null), exception.IllegalArgument); });
|
|
102
|
+
it('Wrong type (undefined)', () => { assert.throws(() => flattenSquareMarkers(undefined), exception.IllegalArgument); });
|
|
103
103
|
});
|
|
104
104
|
|
|
105
105
|
|
|
106
106
|
describe('Parse square markers', () => {
|
|
107
107
|
|
|
108
|
-
it('Re4', () => {
|
|
109
|
-
it('Gd3,Yh8', () => {
|
|
110
|
-
it('Ga1,Yc5,Rd2,Bh7,Yh8', () => {
|
|
111
|
-
it('<empty>', () => {
|
|
112
|
-
it('<blank>', () => {
|
|
108
|
+
it('Re4', () => { assert.deepEqual(parseSquareMarkers('Re4'), { e4: 'r' }); });
|
|
109
|
+
it('Gd3,Yh8', () => { assert.deepEqual(parseSquareMarkers('Gd3,Yh8'), { h8: 'y', d3: 'g' }); });
|
|
110
|
+
it('Ga1,Yc5,Rd2,Bh7,Yh8', () => { assert.deepEqual(parseSquareMarkers(' Ga1, Yh8,Yc5 ,Rd2, Bh7 '), { c5: 'y', h8: 'y', a1: 'g', h7: 'b', d2: 'r' }); });
|
|
111
|
+
it('<empty>', () => { assert.deepEqual(parseSquareMarkers(''), {}); });
|
|
112
|
+
it('<blank>', () => { assert.deepEqual(parseSquareMarkers(' '), {}); });
|
|
113
113
|
|
|
114
|
-
it('Wrong square', () => {
|
|
115
|
-
it('Duplicated square', () => {
|
|
116
|
-
it('Wrong color', () => {
|
|
117
|
-
it('Wrong format', () => {
|
|
114
|
+
it('Wrong square', () => { assert.deepEqual(parseSquareMarkers('Rg9,Ye1'), { e1: 'y' }); });
|
|
115
|
+
it('Duplicated square', () => { assert.deepEqual(parseSquareMarkers('Ra3,Ya3'), { a3: 'y' }); });
|
|
116
|
+
it('Wrong color', () => { assert.deepEqual(parseSquareMarkers('Ga6,Cg5'), { a6: 'g' }); });
|
|
117
|
+
it('Wrong format', () => { assert.deepEqual(parseSquareMarkers('Something Ra2 invalid, Ye4, G g3'), { e4: 'y' }); });
|
|
118
118
|
|
|
119
|
-
it('Wrong type (not a string)', () => {
|
|
120
|
-
it('Wrong type (null)', () => {
|
|
121
|
-
it('Wrong type (undefined)', () => {
|
|
119
|
+
it('Wrong type (not a string)', () => { assert.throws(() => parseSquareMarkers(42), exception.IllegalArgument); });
|
|
120
|
+
it('Wrong type (null)', () => { assert.throws(() => parseSquareMarkers(null), exception.IllegalArgument); });
|
|
121
|
+
it('Wrong type (undefined)', () => { assert.throws(() => parseSquareMarkers(undefined), exception.IllegalArgument); });
|
|
122
122
|
});
|
|
123
123
|
|
|
124
124
|
|
|
125
125
|
describe('Flatten text markers', () => {
|
|
126
126
|
|
|
127
|
-
it('RAe4', () => {
|
|
127
|
+
it('RAe4', () => { assert.deepEqual(flattenTextMarkers({ e4: { symbol: 'A', color: 'r' } }), 'RAe4'); });
|
|
128
128
|
it('Gzd3,Y1h8', () => {
|
|
129
|
-
|
|
129
|
+
assert.deepEqual(flattenTextMarkers({
|
|
130
130
|
h8: { symbol: '1', color: 'y' },
|
|
131
131
|
d3: { symbol: 'z', color: 'g' },
|
|
132
|
-
})
|
|
132
|
+
}), 'Gzd3,Y1h8');
|
|
133
133
|
});
|
|
134
134
|
it('G2a1,YMc5,RLd2,Rxh7,Bwh8', () => {
|
|
135
|
-
|
|
135
|
+
assert.deepEqual(flattenTextMarkers({
|
|
136
136
|
c5: { symbol: 'M', color: 'y' },
|
|
137
137
|
h8: { symbol: 'w', color: 'b' },
|
|
138
138
|
a1: { symbol: '2', color: 'g' },
|
|
139
139
|
h7: { symbol: 'x', color: 'r' },
|
|
140
140
|
d2: { symbol: 'L', color: 'r' },
|
|
141
|
-
})
|
|
141
|
+
}), 'G2a1,YMc5,RLd2,Rxh7,Bwh8');
|
|
142
142
|
});
|
|
143
143
|
it('Multi-character symbols', () => {
|
|
144
|
-
|
|
144
|
+
assert.deepEqual(flattenTextMarkers({
|
|
145
145
|
a1: { symbol: 'A', color: 'y' },
|
|
146
146
|
a7: { symbol: 'plus', color: 'g' },
|
|
147
147
|
b3: { symbol: 'times', color: 'r' },
|
|
148
148
|
g5: { symbol: 'dot', color: 'y' },
|
|
149
149
|
h3: { symbol: 'circle', color: 'g' },
|
|
150
|
-
})
|
|
150
|
+
}), 'YAa1,G(plus)a7,R(times)b3,Y(dot)g5,G(circle)h3');
|
|
151
151
|
});
|
|
152
|
-
it('<empty>', () => {
|
|
152
|
+
it('<empty>', () => { assert.deepEqual(flattenTextMarkers({}), ''); });
|
|
153
153
|
|
|
154
154
|
it('Wrong square', () => {
|
|
155
|
-
|
|
155
|
+
assert.deepEqual(flattenTextMarkers({
|
|
156
156
|
e1: { symbol: 'H', color: 'r' },
|
|
157
157
|
j5: { symbol: 'A', color: 'g' },
|
|
158
|
-
})
|
|
158
|
+
}), 'RHe1');
|
|
159
159
|
});
|
|
160
160
|
it('Wrong color', () => {
|
|
161
|
-
|
|
161
|
+
assert.deepEqual(flattenTextMarkers({
|
|
162
162
|
a2: { symbol: '0', color: 'g' },
|
|
163
163
|
b5: { symbol: 'A', color: 'R' },
|
|
164
164
|
h8: { symbol: 'A' },
|
|
165
|
-
})
|
|
165
|
+
}), 'G0a2');
|
|
166
166
|
});
|
|
167
167
|
it('Wrong symbol', () => {
|
|
168
|
-
|
|
168
|
+
assert.deepEqual(flattenTextMarkers({
|
|
169
169
|
a2: { symbol: '0', color: 'g' },
|
|
170
170
|
b5: { symbol: '', color: 'r' },
|
|
171
171
|
h8: { color: 'g' },
|
|
172
172
|
d8: { symbol: '-', color: 'r' },
|
|
173
173
|
c1: { symbol: 'abcd', color: 'r' },
|
|
174
|
-
})
|
|
174
|
+
}), 'G0a2');
|
|
175
175
|
});
|
|
176
176
|
it('Wrong multi-character symbol', () => {
|
|
177
|
-
|
|
177
|
+
assert.deepEqual(flattenTextMarkers({
|
|
178
178
|
a2: { symbol: '0', color: 'g' },
|
|
179
179
|
b5: { symbol: 'whatever', color: 'r' },
|
|
180
|
-
})
|
|
180
|
+
}), 'G0a2');
|
|
181
181
|
});
|
|
182
182
|
|
|
183
|
-
it('Wrong type (not an object)', () => {
|
|
184
|
-
it('Wrong type (null)', () => {
|
|
185
|
-
it('Wrong type (undefined)', () => {
|
|
183
|
+
it('Wrong type (not an object)', () => { assert.throws(() => flattenTextMarkers('whatever'), exception.IllegalArgument); });
|
|
184
|
+
it('Wrong type (null)', () => { assert.throws(() => flattenTextMarkers(null), exception.IllegalArgument); });
|
|
185
|
+
it('Wrong type (undefined)', () => { assert.throws(() => flattenTextMarkers(undefined), exception.IllegalArgument); });
|
|
186
186
|
});
|
|
187
187
|
|
|
188
188
|
|
|
189
189
|
describe('Parse text markers', () => {
|
|
190
190
|
|
|
191
|
-
it('RAe4', () => {
|
|
191
|
+
it('RAe4', () => { assert.deepEqual(parseTextMarkers('RAe4'), { e4: { symbol: 'A', color: 'r' } }); });
|
|
192
192
|
it('Gzd3,Y1h8', () => {
|
|
193
|
-
|
|
193
|
+
assert.deepEqual(parseTextMarkers('Gzd3,Y1h8'), {
|
|
194
194
|
h8: { symbol: '1', color: 'y' },
|
|
195
195
|
d3: { symbol: 'z', color: 'g' },
|
|
196
196
|
});
|
|
197
197
|
});
|
|
198
198
|
it('G2a1,YMc5,RLd2,Rxh7,Bwh8', () => {
|
|
199
|
-
|
|
199
|
+
assert.deepEqual(parseTextMarkers(' G2a1, Rxh7 ,YMc5 ,RLd2,Bwh8 '), {
|
|
200
200
|
c5: { symbol: 'M', color: 'y' },
|
|
201
201
|
h8: { symbol: 'w', color: 'b' },
|
|
202
202
|
a1: { symbol: '2', color: 'g' },
|
|
@@ -205,7 +205,7 @@ describe('Parse text markers', () => {
|
|
|
205
205
|
});
|
|
206
206
|
});
|
|
207
207
|
it('Multi-character symbols', () => {
|
|
208
|
-
|
|
208
|
+
assert.deepEqual(parseTextMarkers('YAa1,G(plus)a7, R(times)b3 ,Y(dot)g5,G(circle)h3'), {
|
|
209
209
|
a1: { symbol: 'A', color: 'y' },
|
|
210
210
|
a7: { symbol: 'plus', color: 'g' },
|
|
211
211
|
b3: { symbol: 'times', color: 'r' },
|
|
@@ -213,56 +213,55 @@ describe('Parse text markers', () => {
|
|
|
213
213
|
h3: { symbol: 'circle', color: 'g' },
|
|
214
214
|
});
|
|
215
215
|
});
|
|
216
|
-
it('<empty>', () => {
|
|
217
|
-
it('<blank>', () => {
|
|
218
|
-
|
|
219
|
-
it('
|
|
220
|
-
it('
|
|
221
|
-
it('Wrong
|
|
222
|
-
it('Wrong symbol', () => {
|
|
223
|
-
it('Wrong
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
it('Wrong type (
|
|
227
|
-
it('Wrong type (
|
|
228
|
-
it('Wrong type (undefined)', () => { test.exception(() => parseTextMarkers(undefined)).isInstanceOf(exception.IllegalArgument); });
|
|
216
|
+
it('<empty>', () => { assert.deepEqual(parseTextMarkers(''), {}); });
|
|
217
|
+
it('<blank>', () => { assert.deepEqual(parseTextMarkers(' '), {}); });
|
|
218
|
+
it('Wrong square', () => { assert.deepEqual(parseTextMarkers('RHg9,Yxe1'), { e1: { symbol: 'x', color: 'y' } }); });
|
|
219
|
+
it('Duplicated square', () => { assert.deepEqual(parseTextMarkers('Rka3,Gba3'), { a3: { symbol: 'b', color: 'g' } }); });
|
|
220
|
+
it('Wrong color', () => { assert.deepEqual(parseTextMarkers('G3a6,CAg5'), { a6: { symbol: '3', color: 'g' } }); });
|
|
221
|
+
it('Wrong symbol', () => { assert.deepEqual(parseTextMarkers('Rb2,RAg5,G.d3,Yabcde7'), { g5: { symbol: 'A', color: 'r' } }); });
|
|
222
|
+
it('Wrong multi-character symbol', () => { assert.deepEqual(parseTextMarkers('RZb2,Y(whatever)e4'), { b2: { symbol: 'Z', color: 'r' } }); });
|
|
223
|
+
it('Wrong format', () => { assert.deepEqual(parseTextMarkers('Something RHa2 invalid, Yqe4, G g3'), { e4: { symbol: 'q', color: 'y' } }); });
|
|
224
|
+
|
|
225
|
+
it('Wrong type (not a string)', () => { assert.throws(() => parseTextMarkers(42), exception.IllegalArgument); });
|
|
226
|
+
it('Wrong type (null)', () => { assert.throws(() => parseTextMarkers(null), exception.IllegalArgument); });
|
|
227
|
+
it('Wrong type (undefined)', () => { assert.throws(() => parseTextMarkers(undefined), exception.IllegalArgument); });
|
|
229
228
|
});
|
|
230
229
|
|
|
231
230
|
|
|
232
231
|
describe('Flatten arrow markers', () => {
|
|
233
232
|
|
|
234
|
-
it('Re4d6', () => {
|
|
235
|
-
it('Gd3b4,Yh8h7', () => {
|
|
233
|
+
it('Re4d6', () => { assert.deepEqual(flattenArrowMarkers({ e4d6: 'r' }), 'Re4d6'); });
|
|
234
|
+
it('Gd3b4,Yh8h7', () => { assert.deepEqual(flattenArrowMarkers({ h8h7: 'y', d3b4: 'g' }), 'Gd3b4,Yh8h7'); });
|
|
236
235
|
it('Ga1h8,Yc5a1,Rd2d2,Rh7h8,Bh8c5', () => {
|
|
237
|
-
|
|
236
|
+
assert.deepEqual(flattenArrowMarkers({ c5a1: 'y', h8c5: 'b', a1h8: 'g', h7h8: 'r', d2d2: 'r' }), 'Ga1h8,Yc5a1,Rd2d2,Rh7h8,Bh8c5');
|
|
238
237
|
});
|
|
239
|
-
it('<empty>', () => {
|
|
238
|
+
it('<empty>', () => { assert.deepEqual(flattenArrowMarkers({}), ''); });
|
|
240
239
|
|
|
241
|
-
it('Wrong vector', () => {
|
|
242
|
-
it('Wrong color', () => {
|
|
240
|
+
it('Wrong vector', () => { assert.deepEqual(flattenArrowMarkers({ e1c2: 'r', a1b9: 'g', c0d2: 'r', i3d4: 'r', f2k3: 'g', whatever: 'y' }), 'Re1c2'); });
|
|
241
|
+
it('Wrong color', () => { assert.deepEqual(flattenArrowMarkers({ a2b3: 'g', b5c1: 'R', c4d8: 42, h8g1: 'yellow' }), 'Ga2b3'); });
|
|
243
242
|
|
|
244
|
-
it('Wrong type (not an object)', () => {
|
|
245
|
-
it('Wrong type (null)', () => {
|
|
246
|
-
it('Wrong type (undefined)', () => {
|
|
243
|
+
it('Wrong type (not an object)', () => { assert.throws(() => flattenArrowMarkers('whatever'), exception.IllegalArgument); });
|
|
244
|
+
it('Wrong type (null)', () => { assert.throws(() => flattenArrowMarkers(null), exception.IllegalArgument); });
|
|
245
|
+
it('Wrong type (undefined)', () => { assert.throws(() => flattenArrowMarkers(undefined), exception.IllegalArgument); });
|
|
247
246
|
});
|
|
248
247
|
|
|
249
248
|
|
|
250
249
|
describe('Parse arrow markers', () => {
|
|
251
250
|
|
|
252
|
-
it('Re4d6', () => {
|
|
253
|
-
it('Gd3b4,Yh8h7', () => {
|
|
251
|
+
it('Re4d6', () => { assert.deepEqual(parseArrowMarkers('Re4d6'), { e4d6: 'r' }); });
|
|
252
|
+
it('Gd3b4,Yh8h7', () => { assert.deepEqual(parseArrowMarkers('Gd3b4,Yh8h7'), { h8h7: 'y', d3b4: 'g' }); });
|
|
254
253
|
it('Ga1h8,Yc5a1,Rd2d2,Rh7h8,Bh8c5', () => {
|
|
255
|
-
|
|
254
|
+
assert.deepEqual(parseArrowMarkers(' Bh8c5,Ga1h8 , Yc5a1 , Rd2d2,Rh7h8 '), { c5a1: 'y', h8c5: 'b', a1h8: 'g', h7h8: 'r', d2d2: 'r' });
|
|
256
255
|
});
|
|
257
|
-
it('<empty>', () => {
|
|
258
|
-
it('<blank>', () => {
|
|
256
|
+
it('<empty>', () => { assert.deepEqual(parseArrowMarkers(''), {}); });
|
|
257
|
+
it('<blank>', () => { assert.deepEqual(parseArrowMarkers(' '), {}); });
|
|
259
258
|
|
|
260
|
-
it('Wrong vector', () => {
|
|
261
|
-
it('Duplicated vector', () => {
|
|
262
|
-
it('Wrong color', () => {
|
|
263
|
-
it('Wrong format', () => {
|
|
259
|
+
it('Wrong vector', () => { assert.deepEqual(parseArrowMarkers('Re1c2,Ga1b9,Rc0d2,Ri3d4,Gf2k3'), { e1c2: 'r' }); });
|
|
260
|
+
it('Duplicated vector', () => { assert.deepEqual(parseArrowMarkers('Ya3b4,Ra3b4'), { a3b4: 'r' }); });
|
|
261
|
+
it('Wrong color', () => { assert.deepEqual(parseArrowMarkers('Ga6c5,Cg5e2'), { a6c5: 'g' }); });
|
|
262
|
+
it('Wrong format', () => { assert.deepEqual(parseArrowMarkers('Something Rb1a2 invalid, Ye4c7, G g3b1'), { e4c7: 'y' }); });
|
|
264
263
|
|
|
265
|
-
it('Wrong type (not a string)', () => {
|
|
266
|
-
it('Wrong type (null)', () => {
|
|
267
|
-
it('Wrong type (undefined)', () => {
|
|
264
|
+
it('Wrong type (not a string)', () => { assert.throws(() => parseArrowMarkers(42), exception.IllegalArgument); });
|
|
265
|
+
it('Wrong type (null)', () => { assert.throws(() => parseArrowMarkers(null), exception.IllegalArgument); });
|
|
266
|
+
it('Wrong type (undefined)', () => { assert.throws(() => parseArrowMarkers(undefined), exception.IllegalArgument); });
|
|
268
267
|
});
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
const { exception, Chessboard, NavigationBoard } = require('../build/test_headless/index');
|
|
26
|
-
const
|
|
26
|
+
const assert = require('node:assert/strict');
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
function itInvalidArgument(label, action) {
|
|
30
|
-
it(label, () => {
|
|
30
|
+
it(label, () => { assert.throws(action, exception.IllegalArgument); });
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
|
|
@@ -35,7 +35,7 @@ describe('Chessboard.size()', () => {
|
|
|
35
35
|
|
|
36
36
|
function itChessboardSize(label, expectedWidth, expectedHeight, attr) {
|
|
37
37
|
it(label, () => {
|
|
38
|
-
|
|
38
|
+
assert.deepEqual(Chessboard.size(attr), { width: expectedWidth, height: expectedHeight });
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -74,7 +74,7 @@ describe('NavigationBoard.size()', () => {
|
|
|
74
74
|
|
|
75
75
|
function itNavigationBoardSize(label, expectedWidth, expectedHeight, attr) {
|
|
76
76
|
it(label, () => {
|
|
77
|
-
|
|
77
|
+
assert.deepEqual(NavigationBoard.size(attr), { width: expectedWidth, height: expectedHeight });
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
80
|
|
|
@@ -104,11 +104,11 @@ describe('NavigationBoard.size()', () => {
|
|
|
104
104
|
|
|
105
105
|
function testAdaptSquareSize(expectedSquareSize, width, height, coordinateVisible, turnVisible, smallScreenLimits) {
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
assert.deepEqual(Chessboard.adaptSquareSize(width, height, {
|
|
108
108
|
coordinateVisible: coordinateVisible,
|
|
109
109
|
turnVisible: turnVisible,
|
|
110
110
|
smallScreenLimits: smallScreenLimits,
|
|
111
|
-
})
|
|
111
|
+
}), expectedSquareSize);
|
|
112
112
|
|
|
113
113
|
const actualSize = Chessboard.size({
|
|
114
114
|
squareSize: expectedSquareSize,
|
|
@@ -116,7 +116,7 @@ function testAdaptSquareSize(expectedSquareSize, width, height, coordinateVisibl
|
|
|
116
116
|
turnVisible: turnVisible,
|
|
117
117
|
smallScreenLimits: smallScreenLimits,
|
|
118
118
|
});
|
|
119
|
-
|
|
119
|
+
assert(actualSize.width <= width && actualSize.height <= height);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
|
|
@@ -129,14 +129,14 @@ function testAdaptSquareSizeWithIncrement(expectedSquareSize, width, height, coo
|
|
|
129
129
|
turnVisible: turnVisible,
|
|
130
130
|
smallScreenLimits: smallScreenLimits,
|
|
131
131
|
});
|
|
132
|
-
|
|
132
|
+
assert(actualSizeIncremented.width > width || actualSizeIncremented.height > height);
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
|
|
136
136
|
describe('Adapt square-size', () => {
|
|
137
137
|
|
|
138
|
-
it('Very small', () => {
|
|
139
|
-
it('Very large', () => {
|
|
138
|
+
it('Very small', () => { assert.deepEqual(Chessboard.adaptSquareSize(10, 10, { coordinateVisible: false, turnVisible: false }), Chessboard.minSquareSize()); });
|
|
139
|
+
it('Very large', () => { assert.deepEqual(Chessboard.adaptSquareSize(9999, 9999), Chessboard.maxSquareSize()); });
|
|
140
140
|
|
|
141
141
|
it('Size 185x300 with coordinates & turn', () => testAdaptSquareSizeWithIncrement(19, 185, 300, true, true));
|
|
142
142
|
it('Size 185x300 without coordinates', () => testAdaptSquareSizeWithIncrement(20, 185, 300, false, true));
|
|
@@ -171,13 +171,13 @@ describe('Adapt square-size (NavigationBoard)', () => {
|
|
|
171
171
|
|
|
172
172
|
function itAdaptSquareSize(label, width, height, attributes, expectedSquareSize) {
|
|
173
173
|
it(label, () => {
|
|
174
|
-
|
|
174
|
+
assert.deepEqual(NavigationBoard.adaptSquareSize(width, height, attributes), expectedSquareSize);
|
|
175
175
|
|
|
176
176
|
const actualSizeIncremented = NavigationBoard.size({
|
|
177
177
|
...attributes,
|
|
178
178
|
squareSize: expectedSquareSize + 1,
|
|
179
179
|
});
|
|
180
|
-
|
|
180
|
+
assert(actualSizeIncremented.width > width || actualSizeIncremented.height > height);
|
|
181
181
|
});
|
|
182
182
|
}
|
|
183
183
|
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
const { describeWithBrowser, itCustom, setSandbox, compareSandbox, takeScreenshot, compareScreenshot, itChecksScreenshots } = require('./common/graphic');
|
|
26
26
|
const { By, Key } = require('selenium-webdriver');
|
|
27
|
-
const
|
|
27
|
+
const assert = require('node:assert/strict');
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
describeWithBrowser('Movetext interaction', browserContext => {
|
|
@@ -74,15 +74,15 @@ describeWithBrowser('Movetext interaction', browserContext => {
|
|
|
74
74
|
|
|
75
75
|
// Handle components for which no interaction is defined.
|
|
76
76
|
if (focusFieldElements.length === 0) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
assert.deepEqual('', expectedOnGoFirst);
|
|
78
|
+
assert.deepEqual('', expectedOnGoPrevious);
|
|
79
|
+
assert.deepEqual('', expectedOnGoNext);
|
|
80
|
+
assert.deepEqual('', expectedOnGoLast);
|
|
81
|
+
assert.deepEqual('', expectedOnExit);
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
assert.deepEqual(focusFieldElements.length, 1);
|
|
86
86
|
const focusFieldElement = focusFieldElements[0];
|
|
87
87
|
|
|
88
88
|
await setSandbox(browserContext, '');
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
const { describeWithBrowser, itCustom, setSandbox, compareSandbox, takeScreenshot, compareScreenshot, itChecksScreenshots } = require('./common/graphic');
|
|
26
26
|
const { By, Key } = require('selenium-webdriver');
|
|
27
|
-
const
|
|
27
|
+
const assert = require('node:assert/strict');
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
describeWithBrowser('Navigation board - Uncontrolled behavior', browserContext => {
|
|
@@ -83,7 +83,7 @@ describeWithBrowser('Navigation board - Uncontrolled behavior', browserContext =
|
|
|
83
83
|
await setSandbox(browserContext, '');
|
|
84
84
|
const focusFieldElements = await element.findElements(By.className('kokopu-focusField'));
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
assert.deepEqual(focusFieldElements.length, 1);
|
|
87
87
|
const focusFieldElement = focusFieldElements[0];
|
|
88
88
|
|
|
89
89
|
for (let i = 0; i < keys.length; ++i) {
|
package/test/common/graphic.js
CHANGED
|
@@ -26,7 +26,7 @@ const fs = require('fs');
|
|
|
26
26
|
const path = require('path');
|
|
27
27
|
const { Builder, By, Capabilities } = require('selenium-webdriver');
|
|
28
28
|
const { imgDiff } = require('img-diff-js');
|
|
29
|
-
const
|
|
29
|
+
const assert = require('node:assert/strict');
|
|
30
30
|
|
|
31
31
|
const rootDir = __dirname + '/../..';
|
|
32
32
|
const referenceDir = rootDir + '/test/graphic_references';
|
|
@@ -200,7 +200,7 @@ const compareScreenshot = exports.compareScreenshot = async function (browserCon
|
|
|
200
200
|
expectedFilename: expectedFilename,
|
|
201
201
|
diffFilename: differenceFilename,
|
|
202
202
|
});
|
|
203
|
-
|
|
203
|
+
assert.deepEqual(result.imagesAreSame, true);
|
|
204
204
|
};
|
|
205
205
|
|
|
206
206
|
|
|
@@ -209,7 +209,7 @@ const compareScreenshot = exports.compareScreenshot = async function (browserCon
|
|
|
209
209
|
*/
|
|
210
210
|
exports.compareSandbox = async function (browserContext, expectedText) {
|
|
211
211
|
const actualText = await browserContext.driver.findElement(By.id('sandbox')).getText();
|
|
212
|
-
|
|
212
|
+
assert.deepEqual(actualText, expectedText);
|
|
213
213
|
};
|
|
214
214
|
|
|
215
215
|
|
|
@@ -229,7 +229,7 @@ exports.setSandbox = async function (browserContext, value) {
|
|
|
229
229
|
*/
|
|
230
230
|
exports.compareGlobalVar = async function (browserContext, variableName, expectedValue) {
|
|
231
231
|
const actualValue = await browserContext.driver.executeScript(`return window["${variableName}"];`);
|
|
232
|
-
|
|
232
|
+
assert.deepEqual(actualValue, expectedValue);
|
|
233
233
|
};
|
|
234
234
|
|
|
235
235
|
|
package/tsconfig.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"include": [ "./src/**/*" ],
|
|
3
3
|
"compilerOptions": {
|
|
4
|
+
"rootDir": "./src",
|
|
4
5
|
"sourceMap": true,
|
|
5
6
|
"declaration": true,
|
|
6
7
|
"module": "es2020",
|
|
@@ -8,8 +9,6 @@
|
|
|
8
9
|
"jsx": "react",
|
|
9
10
|
"types": [],
|
|
10
11
|
"allowJs": false,
|
|
11
|
-
"strict": true
|
|
12
|
-
"forceConsistentCasingInFileNames": true,
|
|
13
|
-
"moduleResolution": "node"
|
|
12
|
+
"strict": true
|
|
14
13
|
}
|
|
15
14
|
}
|