kokopu-react 3.1.0 → 3.3.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/.eslintrc.yml +1 -1
- package/CHANGELOG.md +10 -0
- package/dist/lib/chessboard/BoardProperties.js.map +1 -1
- package/dist/lib/chessboard/Chessboard.css +13 -13
- package/dist/lib/chessboard/Chessboard.d.ts +27 -2
- package/dist/lib/chessboard/Chessboard.js +36 -17
- package/dist/lib/chessboard/Chessboard.js.map +1 -1
- package/dist/lib/chessboard/ChessboardImpl.js.map +1 -1
- package/dist/lib/chessboard/Draggable.js.map +1 -1
- package/dist/lib/chessboard/Motion.js.map +1 -1
- package/dist/lib/chessboard/colorsets.js.map +1 -1
- package/dist/lib/chessboard/piecesets.js.map +1 -1
- package/dist/lib/errorbox/ErrorBox.css +18 -18
- package/dist/lib/errorbox/ErrorBox.js.map +1 -1
- package/dist/lib/errorbox/parsing.js.map +1 -1
- package/dist/lib/exception.js.map +1 -1
- package/dist/lib/i18n.d.ts +1 -0
- package/dist/lib/i18n.js +1 -0
- package/dist/lib/i18n.js.map +1 -1
- package/dist/lib/icons/AnnotationSymbolShape.css +6 -6
- package/dist/lib/icons/AnnotationSymbolShape.js.map +1 -1
- package/dist/lib/icons/ArrowMarkerIcon.js.map +1 -1
- package/dist/lib/icons/ArrowTip.js.map +1 -1
- package/dist/lib/icons/ChessPieceIcon.js.map +1 -1
- package/dist/lib/icons/SquareMarkerIcon.js.map +1 -1
- package/dist/lib/icons/TextMarkerIcon.js.map +1 -1
- package/dist/lib/icons/arrow.css +1 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.js +1 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/movetext/Movetext.css +27 -27
- package/dist/lib/movetext/Movetext.js.map +1 -1
- package/dist/lib/movetext/MovetextImpl.js.map +1 -1
- package/dist/lib/movetext/fonts.css +7 -7
- package/dist/lib/movetext/htmlFilter.js.map +1 -1
- package/dist/lib/movetext/moveFormatter.js.map +1 -1
- package/dist/lib/navigationboard/NavigationBoard.d.ts +68 -1
- package/dist/lib/navigationboard/NavigationBoard.js +141 -13
- package/dist/lib/navigationboard/NavigationBoard.js.map +1 -1
- package/dist/lib/navigationboard/NavigationButton.d.ts +66 -0
- package/dist/lib/navigationboard/NavigationButton.js +67 -0
- package/dist/lib/navigationboard/NavigationButton.js.map +1 -0
- package/dist/lib/navigationboard/NavigationField.css +7 -7
- package/dist/lib/navigationboard/NavigationField.js.map +1 -1
- package/dist/lib/navigationboard/NavigationToolbar.css +16 -13
- package/dist/lib/navigationboard/NavigationToolbar.d.ts +10 -10
- package/dist/lib/navigationboard/NavigationToolbar.js +61 -79
- package/dist/lib/navigationboard/NavigationToolbar.js.map +1 -1
- package/dist/lib/navigationboard/iconPaths.d.ts +29 -0
- package/dist/lib/navigationboard/iconPaths.js +91 -0
- package/dist/lib/navigationboard/iconPaths.js.map +1 -0
- package/dist/lib/sanitization.js.map +1 -1
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/util.js.map +1 -1
- package/doc_src/demo/PageChessboardBase.tsx +115 -115
- package/doc_src/demo/PageChessboardInteraction.tsx +303 -303
- package/doc_src/demo/PageChessboardMove.tsx +173 -173
- package/doc_src/demo/PageChessboardSmallScreens.tsx +94 -94
- package/doc_src/demo/PageMovetextBase.tsx +180 -180
- package/doc_src/demo/PageMovetextInteraction.tsx +123 -123
- package/doc_src/demo/PageNavigationBoardBase.tsx +144 -137
- package/doc_src/demo/PageNavigationBoardUncontrolledVsControlled.tsx +69 -69
- package/doc_src/demo/decs.d.ts +4 -4
- package/doc_src/demo/demo.css +12 -12
- package/doc_src/demo/util.ts +1 -1
- package/doc_src/examples/NavigationBoard.md +1 -1
- package/doc_src/theming/LogoRenderer.js +13 -13
- package/doc_src/theming/theming.css +5 -5
- package/package.json +95 -95
- package/scripts/doc.styleguide.config.js +131 -131
- package/scripts/doc.tsconfig.json +5 -5
- package/scripts/docker-compose.yml +1 -1
- package/scripts/test-graphic.tsconfig.json +5 -5
- package/scripts/test-graphic.webpack.config.js +57 -57
- package/scripts/test-headless.webpack.config.js +29 -29
- package/src/chessboard/BoardProperties.ts +68 -68
- package/src/chessboard/Chessboard.css +13 -13
- package/src/chessboard/Chessboard.tsx +436 -380
- package/src/chessboard/ChessboardImpl.tsx +557 -557
- package/src/chessboard/Draggable.tsx +185 -185
- package/src/chessboard/Motion.tsx +67 -67
- package/src/chessboard/colorsets.ts +66 -66
- package/src/chessboard/piecesets.ts +84 -84
- package/src/decs.d.ts +2 -2
- package/src/errorbox/ErrorBox.css +18 -18
- package/src/errorbox/ErrorBox.tsx +75 -75
- package/src/errorbox/parsing.tsx +95 -95
- package/src/exception.ts +17 -17
- package/src/i18n.ts +1 -0
- package/src/icons/AnnotationSymbolShape.css +6 -6
- package/src/icons/AnnotationSymbolShape.tsx +31 -31
- package/src/icons/ArrowMarkerIcon.tsx +34 -34
- package/src/icons/ArrowTip.tsx +14 -14
- package/src/icons/ChessPieceIcon.tsx +45 -45
- package/src/icons/SquareMarkerIcon.tsx +20 -20
- package/src/icons/TextMarkerIcon.tsx +29 -29
- package/src/icons/arrow.css +1 -1
- package/src/index.ts +3 -2
- package/src/movetext/Movetext.css +27 -27
- package/src/movetext/Movetext.tsx +158 -158
- package/src/movetext/MovetextImpl.tsx +345 -345
- package/src/movetext/fonts.css +7 -7
- package/src/movetext/htmlFilter.tsx +129 -129
- package/src/movetext/moveFormatter.tsx +37 -37
- package/src/navigationboard/NavigationBoard.tsx +386 -180
- package/src/navigationboard/NavigationButton.ts +114 -0
- package/src/navigationboard/NavigationField.css +7 -7
- package/src/navigationboard/NavigationField.tsx +90 -90
- package/src/navigationboard/NavigationToolbar.css +16 -13
- package/src/navigationboard/NavigationToolbar.tsx +98 -112
- package/src/navigationboard/iconPaths.ts +98 -0
- package/src/sanitization.ts +17 -17
- package/src/types.ts +116 -116
- package/src/util.ts +11 -11
- package/test/01_types.js +167 -167
- package/test/02_chessboard_util.js +191 -115
- package/test/03_error_box_graphic.js +16 -16
- package/test/04_icons_graphic.js +32 -32
- package/test/05_chessboard_graphic.js +60 -60
- package/test/06_chessboard_animation.js +36 -36
- package/test/07_chessboard_interaction.js +101 -101
- package/test/08_chessboard_play_moves.js +62 -62
- package/test/09_chessboard_small_screens.js +32 -32
- package/test/10_movetext_graphic.js +32 -32
- package/test/11_movetext_interaction.js +100 -100
- package/test/12_navigation_board_base.js +151 -0
- package/test/13_navigation_board_graphic.js +68 -0
- package/test/14_navigation_board_autoplay.js +100 -0
- package/test/common/graphic.js +106 -97
- package/test/graphic_references/12_navigation_board_base/controlled/default.png +0 -0
- package/test/graphic_references/{12_navigation_board/controlled/forbidden_navigation_1.png → 12_navigation_board_base/controlled/forbidden_navigation_0.png} +0 -0
- package/test/graphic_references/{12_navigation_board/controlled/invalid_node_id.png → 12_navigation_board_base/controlled/forbidden_navigation_1.png} +0 -0
- package/test/graphic_references/{12_navigation_board/controlled/forbidden_navigation_0.png → 12_navigation_board_base/controlled/invalid_node_id.png} +0 -0
- package/test/graphic_references/12_navigation_board_base/controlled/no_callback_defined_0.png +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/controlled/no_callback_defined_1.png +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/controlled/overriding_initial_node_id.png +0 -0
- package/test/graphic_references/{12_navigation_board/controlled/regular_navigation_1.png → 12_navigation_board_base/controlled/regular_navigation_0.png} +0 -0
- package/test/graphic_references/{12_navigation_board/uncontrolled/initial_state_at_specific_id.png → 12_navigation_board_base/controlled/regular_navigation_1.png} +0 -0
- package/test/graphic_references/{12_navigation_board/controlled/regular_navigation_3.png → 12_navigation_board_base/controlled/regular_navigation_2.png} +0 -0
- package/test/graphic_references/{12_navigation_board/controlled/regular_navigation_0.png → 12_navigation_board_base/controlled/regular_navigation_3.png} +0 -0
- package/test/graphic_references/{12_navigation_board/uncontrolled/forbidden_navigation_at_beginning_2.png → 12_navigation_board_base/uncontrolled/forbidden_navigation_at_beginning_0.png} +0 -0
- package/test/graphic_references/{12_navigation_board/uncontrolled/forbidden_navigation_at_beginning_0.png → 12_navigation_board_base/uncontrolled/forbidden_navigation_at_beginning_1.png} +0 -0
- package/test/graphic_references/{12_navigation_board/uncontrolled/forbidden_navigation_at_beginning_1.png → 12_navigation_board_base/uncontrolled/forbidden_navigation_at_beginning_2.png} +0 -0
- package/test/graphic_references/{12_navigation_board/controlled/no_callback_defined_0.png → 12_navigation_board_base/uncontrolled/forbidden_navigation_at_end_0.png} +0 -0
- package/test/graphic_references/12_navigation_board_base/uncontrolled/forbidden_navigation_at_end_1.png +0 -0
- package/test/graphic_references/12_navigation_board_base/uncontrolled/forbidden_navigation_at_end_2.png +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/initial_state_at_end.png +0 -0
- package/test/graphic_references/12_navigation_board_base/uncontrolled/initial_state_at_specific_id.png +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/initial_state_default.png +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/initial_state_default_with_game_index.png +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/initial_state_on_null-move.png +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/navigation_with_keys_0.png +0 -0
- package/test/graphic_references/12_navigation_board_base/uncontrolled/navigation_with_keys_1.png +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/navigation_with_keys_2.png +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/navigation_with_keys_3.png +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/navigation_with_keys_4.png +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_flipping_0.png +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_flipping_1.png +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_navigation_0.png +0 -0
- package/test/graphic_references/{12_navigation_board/controlled/default.png → 12_navigation_board_base/uncontrolled/regular_navigation_1.png} +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_navigation_2.png +0 -0
- package/test/graphic_references/12_navigation_board_base/uncontrolled/regular_navigation_3.png +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_navigation_4.png +0 -0
- package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_navigation_5.png +0 -0
- package/test/graphic_references/13_navigation_board_graphic/additional_buttons/error_1.png +0 -0
- package/test/graphic_references/13_navigation_board_graphic/additional_buttons/error_2.png +0 -0
- package/test/graphic_references/13_navigation_board_graphic/additional_buttons/multiple_buttons.png +0 -0
- package/test/graphic_references/{12_navigation_board/uncontrolled/regular_navigation_3.png → 13_navigation_board_graphic/additional_buttons/single_button.png} +0 -0
- package/test/graphic_references/{12_navigation_board → 13_navigation_board_graphic}/theme/custom_1.png +0 -0
- package/test/graphic_references/{12_navigation_board → 13_navigation_board_graphic}/theme/custom_2.png +0 -0
- package/test/graphic_references/{12_navigation_board → 13_navigation_board_graphic}/theme/large.png +0 -0
- package/test/graphic_references/13_navigation_board_graphic/theme/small.png +0 -0
- package/test/graphic_references/14_navigation_board_autoplay/controlled/after_1_move_acknowledging_is-playing_changes.png +0 -0
- package/test/graphic_references/14_navigation_board_autoplay/controlled/after_1_move_not_acknowledging_is-playing_changes.png +0 -0
- package/test/graphic_references/14_navigation_board_autoplay/controlled/after_2_moves_acknowledging_node_changes.png +0 -0
- package/test/graphic_references/14_navigation_board_autoplay/controlled/after_2_moves_not_acknowledging_node_changes.png +0 -0
- package/test/graphic_references/{12_navigation_board/uncontrolled/forbidden_navigation_at_end_1.png → 14_navigation_board_autoplay/controlled/after_reaching_the_end.png} +0 -0
- package/test/graphic_references/{12_navigation_board/uncontrolled/forbidden_navigation_at_end_2.png → 14_navigation_board_autoplay/controlled/already_at_the_end.png} +0 -0
- package/test/graphic_references/14_navigation_board_autoplay/controlled/initial_state_acknowledging_is-playing_changes.png +0 -0
- package/test/graphic_references/14_navigation_board_autoplay/controlled/initial_state_acknowledging_node_changes.png +0 -0
- package/test/graphic_references/{12_navigation_board/uncontrolled/forbidden_navigation_at_end_0.png → 14_navigation_board_autoplay/controlled/initial_state_at_the_end.png} +0 -0
- package/test/graphic_references/14_navigation_board_autoplay/controlled/initial_state_close_to_end.png +0 -0
- package/test/graphic_references/14_navigation_board_autoplay/controlled/initial_state_not_acknowledging_is-playing_changes.png +0 -0
- package/test/graphic_references/14_navigation_board_autoplay/controlled/initial_state_not_acknowledging_node_changes.png +0 -0
- package/test/graphic_references/14_navigation_board_autoplay/uncontrolled/after_2_moves_from_beginning_after_stop.png +0 -0
- package/test/graphic_references/14_navigation_board_autoplay/uncontrolled/after_2_moves_from_beginning_before_stop.png +0 -0
- package/test/graphic_references/14_navigation_board_autoplay/uncontrolled/after_reaching_the_end_after_stop.png +0 -0
- package/test/graphic_references/14_navigation_board_autoplay/uncontrolled/after_reaching_the_end_before_stop.png +0 -0
- package/test/graphic_references/14_navigation_board_autoplay/uncontrolled/initial_state_close_to_end.png +0 -0
- package/test/graphic_references/{12_navigation_board/uncontrolled/navigation_with_keys_1.png → 14_navigation_board_autoplay/uncontrolled/initial_state_default.png} +0 -0
- package/test/graphic_test_app/03_error_box_graphic/base.tsx +14 -14
- package/test/graphic_test_app/03_error_box_graphic/localization.tsx +1 -1
- package/test/graphic_test_app/04_icons_graphic/chess_piece.tsx +7 -7
- package/test/graphic_test_app/04_icons_graphic/marker.tsx +15 -15
- package/test/graphic_test_app/05_chessboard_graphic/annotations.tsx +7 -7
- package/test/graphic_test_app/05_chessboard_graphic/base.tsx +6 -6
- package/test/graphic_test_app/05_chessboard_graphic/chess_variants.tsx +7 -7
- package/test/graphic_test_app/05_chessboard_graphic/flipped.tsx +5 -5
- package/test/graphic_test_app/05_chessboard_graphic/move.tsx +12 -12
- package/test/graphic_test_app/05_chessboard_graphic/theme.tsx +12 -12
- package/test/graphic_test_app/06_chessboard_animation/base_1.tsx +6 -6
- package/test/graphic_test_app/06_chessboard_animation/base_2.tsx +6 -6
- package/test/graphic_test_app/06_chessboard_animation/base_3.tsx +6 -6
- package/test/graphic_test_app/06_chessboard_animation/on_redraw.tsx +16 -16
- package/test/graphic_test_app/07_chessboard_interaction/click_squares.tsx +5 -5
- package/test/graphic_test_app/07_chessboard_interaction/edit_arrows.tsx +4 -4
- package/test/graphic_test_app/07_chessboard_interaction/error.tsx +2 -2
- package/test/graphic_test_app/07_chessboard_interaction/move_pieces.tsx +5 -5
- package/test/graphic_test_app/08_chessboard_play_moves/base.tsx +8 -8
- package/test/graphic_test_app/08_chessboard_play_moves/promotions.tsx +4 -4
- package/test/graphic_test_app/09_chessboard_small_screens/base.tsx +9 -9
- package/test/graphic_test_app/09_chessboard_small_screens/top_bottom_components.tsx +9 -9
- package/test/graphic_test_app/10_movetext_graphic/base.tsx +4 -4
- package/test/graphic_test_app/10_movetext_graphic/error.tsx +6 -6
- package/test/graphic_test_app/10_movetext_graphic/format_move.tsx +1 -1
- package/test/graphic_test_app/10_movetext_graphic/html.tsx +5 -5
- package/test/graphic_test_app/10_movetext_graphic/options.tsx +10 -10
- package/test/graphic_test_app/11_movetext_interaction/error.tsx +1 -1
- package/test/graphic_test_app/11_movetext_interaction/select_moves.tsx +11 -11
- package/test/graphic_test_app/{12_navigation_board → 12_navigation_board_base}/controlled.tsx +5 -5
- package/test/graphic_test_app/{12_navigation_board → 12_navigation_board_base}/uncontrolled.tsx +7 -7
- package/test/graphic_test_app/13_navigation_board_graphic/additional_buttons.tsx +49 -0
- package/test/graphic_test_app/{12_navigation_board → 13_navigation_board_graphic}/error.tsx +2 -2
- package/test/graphic_test_app/{12_navigation_board → 13_navigation_board_graphic}/theme.tsx +4 -4
- package/test/graphic_test_app/14_navigation_board_autoplay/controlled.tsx +73 -0
- package/test/graphic_test_app/14_navigation_board_autoplay/uncontrolled.tsx +34 -0
- package/test/graphic_test_app/common/decs.d.ts +2 -2
- package/test/graphic_test_app/common/test_app.css +15 -15
- package/test/graphic_test_app/common/test_app.tsx +48 -48
- package/tsconfig.json +13 -13
- package/test/12_navigation_board.js +0 -168
- package/test/graphic_references/12_navigation_board/controlled/regular_navigation_2.png +0 -0
- package/test/graphic_references/12_navigation_board/theme/small.png +0 -0
- package/test/graphic_references/12_navigation_board/uncontrolled/regular_navigation_1.png +0 -0
- /package/test/graphic_references/{12_navigation_board → 13_navigation_board_graphic}/error/pgn_parsing_error.png +0 -0
- /package/test/graphic_references/{12_navigation_board → 13_navigation_board_graphic}/error/wrong_game_type.png +0 -0
|
@@ -26,82 +26,146 @@ import * as React from 'react';
|
|
|
26
26
|
|
|
27
27
|
import { Database, Game, Node as GameNode, Variation } from 'kokopu';
|
|
28
28
|
|
|
29
|
-
import {
|
|
29
|
+
import { IllegalArgument } from '../exception';
|
|
30
|
+
import { i18n } from '../i18n';
|
|
31
|
+
import { sanitizeBoolean, sanitizeOptional, sanitizeString, sanitizePartialObject } from '../sanitization';
|
|
30
32
|
|
|
31
33
|
import { DynamicBoardGraphicProps, defaultDynamicBoardProps } from '../chessboard/BoardProperties';
|
|
32
34
|
import { Chessboard } from '../chessboard/Chessboard';
|
|
33
35
|
import { parseGame } from '../errorbox/parsing';
|
|
34
36
|
import { NavigationField, firstNodeId, previousNodeId, nextNodeId, lastNodeId } from '../navigationboard/NavigationField';
|
|
35
|
-
import {
|
|
37
|
+
import { GO_FIRST_ICON_PATH, GO_PREVIOUS_ICON_PATH, GO_NEXT_ICON_PATH, GO_LAST_ICON_PATH, PLAY_ICON_PATH, STOP_ICON_PATH, FLIP_ICON_PATH } from './iconPaths';
|
|
38
|
+
import { NavigationBar, NavigationBarScheme, isNavigationBar, isNavigationBarScheme } from './NavigationButton';
|
|
39
|
+
import { NavigationToolbar, navigationToolbarSize } from './NavigationToolbar';
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
const INTER_MOVE_DURATION = 1000;
|
|
36
43
|
|
|
37
44
|
|
|
38
45
|
export interface NavigationBoardProps extends DynamicBoardGraphicProps {
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Displayed game. Can be a [kokopu.Game](https://kokopu.yo35.org/docs/current/classes/Game.html) object,
|
|
49
|
+
* a [kokopu.Database](https://kokopu.yo35.org/docs/current/classes/Database.html) object,
|
|
50
|
+
* or a [PGN string](https://en.wikipedia.org/wiki/Portable_Game_Notation).
|
|
51
|
+
*/
|
|
52
|
+
game: Game | Database | string;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Index of the game to display (only if attribute `game` is a [kokopu.Database](https://kokopu.yo35.org/docs/current/classes/Database.html)
|
|
56
|
+
* or a [PGN string](https://en.wikipedia.org/wiki/Portable_Game_Notation)): `0` for the first game of the database/PGN, `1` for the second one, etc.
|
|
57
|
+
* If omitted, the first game of the database/PGN is displayed.
|
|
58
|
+
*/
|
|
59
|
+
gameIndex: number;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* ID of the move initially selected (or `'start'`/`'end'` for the beginning/end of the main variation) when the component is uncontrolled.
|
|
63
|
+
* Use [kokopu.Node#id](https://kokopu.yo35.org/docs/current/classes/Node.html#id) to get the ID of a game move.
|
|
64
|
+
* Ignored if the `nodeId` attribute is provided.
|
|
65
|
+
*/
|
|
66
|
+
initialNodeId: string;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* ID of the selected move (or `'start'`/`'end'` for the beginning/end of the main variation).
|
|
70
|
+
* Use [kokopu.Node#id](https://kokopu.yo35.org/docs/current/classes/Node.html#id) to get the ID of a game move.
|
|
71
|
+
* If provided (i.e. if the component is controlled), the attribute `onNodeIdChanged` must be provided as well.
|
|
72
|
+
*/
|
|
73
|
+
nodeId?: string;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Callback invoked in controlled-component mode, when the user changes the selected move.
|
|
77
|
+
*
|
|
78
|
+
* @param nodeId - ID of the selected move (as returned by [kokopu.Node#id](https://kokopu.yo35.org/docs/current/classes/Node.html#id)),
|
|
79
|
+
* or `'start'` for the beginning of the main variation.
|
|
80
|
+
*/
|
|
81
|
+
onNodeIdChanged?: (nodeId: string) => void;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Whether auto-play is initially enabled or not.
|
|
85
|
+
* Ignored if the `isPlaying` attribute is provided.
|
|
86
|
+
*/
|
|
87
|
+
initialIsPlaying: boolean;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Whether auto-play is enabled or not.
|
|
91
|
+
* If provided (i.e. if the is-playing state is controlled), the attribute `onIsPlayingChanged` must be provided as well.
|
|
92
|
+
*/
|
|
93
|
+
isPlaying?: boolean;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Callback invoked in controlled-is-playing-state mode, when the user clicks on the play/stop button.
|
|
97
|
+
*
|
|
98
|
+
* @param isPlaying - New is-playing state.
|
|
99
|
+
*/
|
|
100
|
+
onIsPlayingChanged?: (isPlaying: boolean) => void;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Whether the board is initially flipped (i.e. seen from Black's point of view) or not, when the flip state is uncontrolled.
|
|
104
|
+
* Ignored if the `flipped` attribute is provided.
|
|
105
|
+
*/
|
|
106
|
+
initialFlipped: boolean;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Whether the board is flipped (i.e. seen from Black's point of view) or not.
|
|
110
|
+
* If provided (i.e. if the flip state is controlled), the attribute `onFlippedChanged` must be provided as well.
|
|
111
|
+
*/
|
|
112
|
+
flipped?: boolean;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Callback invoked in controlled-flip-state mode, when the user flips the board.
|
|
116
|
+
*
|
|
117
|
+
* @param flipped - New flip state.
|
|
118
|
+
*/
|
|
119
|
+
onFlippedChanged?: (flipped: boolean) => void;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Whether the play/stop button is visible or not in the toolbar.
|
|
123
|
+
*/
|
|
124
|
+
playButtonVisible: boolean;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Whether the flip button is visible or not in the toolbar.
|
|
128
|
+
*/
|
|
129
|
+
flipButtonVisible: boolean;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Additional buttons to be added to the toolbar.
|
|
133
|
+
*/
|
|
134
|
+
additionalButtons: NavigationBar;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Attributes for method `NavigationBoard.size()`.
|
|
140
|
+
*/
|
|
141
|
+
interface NavigationBoardSizeAttr {
|
|
142
|
+
squareSize?: NavigationBoardProps['squareSize'];
|
|
143
|
+
coordinateVisible?: NavigationBoardProps['coordinateVisible'];
|
|
144
|
+
turnVisible?: NavigationBoardProps['turnVisible'];
|
|
145
|
+
smallScreenLimits?: NavigationBoardProps['smallScreenLimits'];
|
|
146
|
+
playButtonVisible?: NavigationBoardProps['playButtonVisible'];
|
|
147
|
+
flipButtonVisible?: NavigationBoardProps['flipButtonVisible'];
|
|
148
|
+
additionalButtons?: NavigationBarScheme;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Attributes for method `NavigationBoard.adaptSquareSize()`.
|
|
154
|
+
*/
|
|
155
|
+
interface NavigationBoardAdaptSquareSizeAttr {
|
|
156
|
+
coordinateVisible?: NavigationBoardProps['coordinateVisible'];
|
|
157
|
+
turnVisible?: NavigationBoardProps['turnVisible'];
|
|
158
|
+
smallScreenLimits?: NavigationBoardProps['smallScreenLimits'];
|
|
159
|
+
playButtonVisible?: NavigationBoardProps['playButtonVisible'];
|
|
160
|
+
flipButtonVisible?: NavigationBoardProps['flipButtonVisible'];
|
|
161
|
+
additionalButtons?: NavigationBarScheme;
|
|
99
162
|
}
|
|
100
163
|
|
|
101
164
|
|
|
102
165
|
interface NavigationBoardState {
|
|
103
|
-
|
|
104
|
-
|
|
166
|
+
nodeIdAsUncontrolled: string;
|
|
167
|
+
isPlayingAsUncontrolled: boolean;
|
|
168
|
+
flippedAsUncontrolled: boolean;
|
|
105
169
|
}
|
|
106
170
|
|
|
107
171
|
|
|
@@ -110,122 +174,264 @@ interface NavigationBoardState {
|
|
|
110
174
|
*/
|
|
111
175
|
export class NavigationBoard extends React.Component<NavigationBoardProps, NavigationBoardState> {
|
|
112
176
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
177
|
+
static defaultProps = {
|
|
178
|
+
...defaultDynamicBoardProps(),
|
|
179
|
+
game: new Game(),
|
|
180
|
+
gameIndex: 0,
|
|
181
|
+
initialNodeId: 'start',
|
|
182
|
+
initialIsPlaying: false,
|
|
183
|
+
initialFlipped: false,
|
|
184
|
+
playButtonVisible: false,
|
|
185
|
+
flipButtonVisible: true,
|
|
186
|
+
additionalButtons: [],
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
private navigationFieldRef: React.RefObject<NavigationField> = React.createRef();
|
|
190
|
+
private timeoutId?: number;
|
|
191
|
+
|
|
192
|
+
constructor(props: NavigationBoardProps) {
|
|
193
|
+
super(props);
|
|
194
|
+
this.state = {
|
|
195
|
+
nodeIdAsUncontrolled: sanitizeString(props.initialNodeId),
|
|
196
|
+
isPlayingAsUncontrolled: sanitizeBoolean(props.initialIsPlaying),
|
|
197
|
+
flippedAsUncontrolled: sanitizeBoolean(props.initialFlipped),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
componentWillUnmount() {
|
|
202
|
+
this.cancelCurrentTimeout();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
render() {
|
|
206
|
+
this.cancelCurrentTimeout();
|
|
207
|
+
|
|
208
|
+
// Validate the game and game-index attributes.
|
|
209
|
+
const info = parseGame(this.props.game, this.props.gameIndex, 'NavigationBoard');
|
|
210
|
+
if (info.error) {
|
|
211
|
+
return info.errorBox;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Fetch the current node/variation.
|
|
215
|
+
const currentNodeId = sanitizeOptional(this.props.nodeId, sanitizeString) ?? this.state.nodeIdAsUncontrolled;
|
|
216
|
+
const currentNode = info.game.findById(currentNodeId) ?? info.game.mainVariation();
|
|
217
|
+
|
|
218
|
+
// State flags.
|
|
219
|
+
const isPlaying = sanitizeOptional(this.props.isPlaying, sanitizeBoolean) ?? this.state.isPlayingAsUncontrolled;
|
|
220
|
+
const flipped = sanitizeOptional(this.props.flipped, sanitizeBoolean) ?? this.state.flippedAsUncontrolled;
|
|
221
|
+
|
|
222
|
+
return (
|
|
223
|
+
<div className="kokopu-navigationBoard">
|
|
224
|
+
{this.renderBoard(info.game, currentNode, isPlaying, flipped)}
|
|
225
|
+
{this.renderNavigationField(info.game, currentNode.id())}
|
|
226
|
+
</div>
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
private renderBoard(game: Game, node: GameNode | Variation, isPlaying: boolean, flipped: boolean) {
|
|
231
|
+
const position = node instanceof GameNode ? node.positionBefore() : node.initialPosition();
|
|
232
|
+
const move = node instanceof GameNode ? node.notation() : undefined;
|
|
233
|
+
return <Chessboard
|
|
234
|
+
position={position} move={move} flipped={flipped}
|
|
235
|
+
squareMarkers={node.tag('csl')} arrowMarkers={node.tag('cal')} textMarkers={node.tag('ctl')}
|
|
236
|
+
squareSize={this.props.squareSize}
|
|
237
|
+
coordinateVisible={this.props.coordinateVisible}
|
|
238
|
+
turnVisible={this.props.turnVisible}
|
|
239
|
+
colorset={this.props.colorset}
|
|
240
|
+
pieceset={this.props.pieceset}
|
|
241
|
+
smallScreenLimits={this.props.smallScreenLimits}
|
|
242
|
+
moveArrowVisible={this.props.moveArrowVisible}
|
|
243
|
+
moveArrowColor={this.props.moveArrowColor}
|
|
244
|
+
animated={this.props.animated}
|
|
245
|
+
bottomComponent={({ squareSize }) => this.renderToolbar(game, node, squareSize, isPlaying)}
|
|
246
|
+
/>;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private renderNavigationField(game: Game, currentNodeId: string) {
|
|
250
|
+
return <NavigationField ref={this.navigationFieldRef}
|
|
251
|
+
onFirstPressed={() => this.handleNavClicked(firstNodeId(game, currentNodeId))}
|
|
252
|
+
onPreviousPressed={() => this.handleNavClicked(previousNodeId(game, currentNodeId))}
|
|
253
|
+
onNextPressed={() => this.handleNavClicked(nextNodeId(game, currentNodeId))}
|
|
254
|
+
onLastPressed={() => this.handleNavClicked(lastNodeId(game, currentNodeId))}
|
|
255
|
+
/>;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private renderToolbar(game: Game, node: GameNode | Variation, squareSize: number, isPlaying: boolean) {
|
|
259
|
+
|
|
260
|
+
// WARNING: the logic here must be the same as the one in `computeBarScheme()`.
|
|
261
|
+
const buttons: NavigationBar = [];
|
|
262
|
+
|
|
263
|
+
// Core navigation buttons
|
|
264
|
+
const currentNodeId = node.id();
|
|
265
|
+
const hasPrevious = currentNodeId !== 'start';
|
|
266
|
+
const hasNext = (node instanceof Variation ? node.first() : node.next()) !== undefined;
|
|
267
|
+
buttons.push({ iconPath: GO_FIRST_ICON_PATH, tooltip: i18n.TOOLTIP_GO_FIRST, enabled: hasPrevious, onClick: () => this.handleNavClicked(firstNodeId(game, currentNodeId)) });
|
|
268
|
+
buttons.push({ iconPath: GO_PREVIOUS_ICON_PATH, tooltip: i18n.TOOLTIP_GO_PREVIOUS, enabled: hasPrevious, onClick: () => this.handleNavClicked(previousNodeId(game, currentNodeId)) });
|
|
269
|
+
if (sanitizeBoolean(this.props.playButtonVisible)) {
|
|
270
|
+
buttons.push({ iconPath: isPlaying ? STOP_ICON_PATH : PLAY_ICON_PATH, tooltip: i18n.TOOLTIP_PLAY_STOP, enabled: hasNext, onClick: () => this.handlePlayStopClicked(!isPlaying) });
|
|
271
|
+
}
|
|
272
|
+
buttons.push({ iconPath: GO_NEXT_ICON_PATH, tooltip: i18n.TOOLTIP_GO_NEXT, enabled: hasNext, onClick: () => this.handleNavClicked(nextNodeId(game, currentNodeId)) });
|
|
273
|
+
buttons.push({ iconPath: GO_LAST_ICON_PATH, tooltip: i18n.TOOLTIP_GO_LAST, enabled: hasNext, onClick: () => this.handleNavClicked(lastNodeId(game, currentNodeId)) });
|
|
274
|
+
buttons.push('spacer');
|
|
275
|
+
if (sanitizeBoolean(this.props.flipButtonVisible)) {
|
|
276
|
+
buttons.push({ iconPath: FLIP_ICON_PATH, tooltip: i18n.TOOLTIP_FLIP, onClick: () => this.handleFlipButtonClicked() });
|
|
277
|
+
}
|
|
278
|
+
buttons.push('spacer');
|
|
279
|
+
|
|
280
|
+
// Schedule the next transition if auto-play is enabled.
|
|
281
|
+
if (isPlaying) {
|
|
282
|
+
if (hasNext) {
|
|
283
|
+
this.timeoutId = window.setTimeout(() => this.handleNavClicked(nextNodeId(game, currentNodeId), false), INTER_MOVE_DURATION);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
// ... or stop the auto-play if at the end of the game.
|
|
287
|
+
this.timeoutId = window.setTimeout(() => this.handlePlayStopClicked(false, false), 0);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Additional buttons.
|
|
292
|
+
if (!isNavigationBar(this.props.additionalButtons)) {
|
|
293
|
+
throw new IllegalArgument('NavigationBoard', 'additionalButtons');
|
|
294
|
+
}
|
|
295
|
+
for (const button of this.props.additionalButtons) {
|
|
296
|
+
buttons.push(button);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return <NavigationToolbar squareSize={squareSize} buttons={buttons} />;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
private handleNavClicked(targetNodeId: string | undefined, forceFocus = true) {
|
|
303
|
+
if (forceFocus) {
|
|
304
|
+
this.focus();
|
|
305
|
+
}
|
|
306
|
+
if (targetNodeId === undefined) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (this.props.nodeId === undefined) { // uncontrolled-component behavior
|
|
311
|
+
this.setState({ nodeIdAsUncontrolled: targetNodeId });
|
|
312
|
+
}
|
|
313
|
+
else if (this.props.onNodeIdChanged) { // controlled-component behavior
|
|
314
|
+
this.props.onNodeIdChanged(targetNodeId);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
private handlePlayStopClicked(targetIsPlaying: boolean, forceFocus = true) {
|
|
319
|
+
if (forceFocus) {
|
|
320
|
+
this.focus();
|
|
321
|
+
}
|
|
322
|
+
if (this.props.isPlaying === undefined) { // uncontrolled is-playing state
|
|
323
|
+
this.setState({ isPlayingAsUncontrolled: targetIsPlaying });
|
|
324
|
+
}
|
|
325
|
+
else if (this.props.onIsPlayingChanged) { // controlled is-playing state
|
|
326
|
+
this.props.onIsPlayingChanged(targetIsPlaying);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
private handleFlipButtonClicked() {
|
|
331
|
+
this.focus();
|
|
332
|
+
if (this.props.flipped === undefined) { // uncontrolled flip state
|
|
333
|
+
this.setState({ flippedAsUncontrolled: !this.state.flippedAsUncontrolled });
|
|
334
|
+
}
|
|
335
|
+
else if (this.props.onFlippedChanged) { // controlled flip state
|
|
336
|
+
this.props.onFlippedChanged(!this.props.flipped);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
private cancelCurrentTimeout() {
|
|
341
|
+
if (this.timeoutId !== undefined) {
|
|
342
|
+
window.clearTimeout(this.timeoutId);
|
|
343
|
+
this.timeoutId = undefined;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Set the focus to the current component.
|
|
349
|
+
*
|
|
350
|
+
* @public
|
|
351
|
+
*/
|
|
352
|
+
focus(): void {
|
|
353
|
+
const target = this.navigationFieldRef.current;
|
|
354
|
+
// istanbul ignore else
|
|
355
|
+
if (target) {
|
|
356
|
+
target.focus();
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Return the size of the {@link NavigationBoard}, assuming it is built with the given attributes.
|
|
362
|
+
*/
|
|
363
|
+
static size(attr?: NavigationBoardSizeAttr): { width: number, height: number } {
|
|
364
|
+
const { squareSize, coordinateVisible, turnVisible, smallScreenLimits, playButtonVisible, flipButtonVisible, additionalButtons } =
|
|
365
|
+
sanitizePartialObject(attr, () => new IllegalArgument('NavigationBoard.size()', 'attr'));
|
|
366
|
+
|
|
367
|
+
// Sanitization
|
|
368
|
+
const actualPlayButtonVisible = sanitizeOptional(playButtonVisible, sanitizeBoolean);
|
|
369
|
+
const actualFlipButtonVisible = sanitizeOptional(flipButtonVisible, sanitizeBoolean);
|
|
370
|
+
if (additionalButtons !== undefined && !isNavigationBarScheme(additionalButtons)) {
|
|
371
|
+
throw new IllegalArgument('NavigationBoard.size()', 'additionalButtons');
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const buttons = computeBarScheme(actualPlayButtonVisible, actualFlipButtonVisible, additionalButtons);
|
|
375
|
+
return Chessboard.size({
|
|
376
|
+
squareSize: squareSize,
|
|
377
|
+
coordinateVisible: coordinateVisible,
|
|
378
|
+
turnVisible: turnVisible,
|
|
379
|
+
smallScreenLimits: smallScreenLimits,
|
|
380
|
+
bottomComponent: ({ squareSize: sz }) => navigationToolbarSize(sz, buttons),
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Return the maximum square size that would allow the {@link NavigationBoard} to fit in a rectangle of size `width x height`.
|
|
386
|
+
*/
|
|
387
|
+
static adaptSquareSize(width: number, height: number, attr?: NavigationBoardAdaptSquareSizeAttr): number {
|
|
388
|
+
|
|
389
|
+
const { coordinateVisible, turnVisible, smallScreenLimits, playButtonVisible, flipButtonVisible, additionalButtons } =
|
|
390
|
+
sanitizePartialObject(attr, () => new IllegalArgument('NavigationBoard.adaptSquareSize()', 'attr'));
|
|
391
|
+
|
|
392
|
+
// Sanitization
|
|
393
|
+
const actualPlayButtonVisible = sanitizeOptional(playButtonVisible, sanitizeBoolean);
|
|
394
|
+
const actualFlipButtonVisible = sanitizeOptional(flipButtonVisible, sanitizeBoolean);
|
|
395
|
+
if (additionalButtons !== undefined && !isNavigationBarScheme(additionalButtons)) {
|
|
396
|
+
throw new IllegalArgument('NavigationBoard.adaptSquareSize()', 'additionalButtons');
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
const buttons = computeBarScheme(actualPlayButtonVisible, actualFlipButtonVisible, additionalButtons);
|
|
400
|
+
return Chessboard.adaptSquareSize(width, height, {
|
|
401
|
+
coordinateVisible: coordinateVisible,
|
|
402
|
+
turnVisible: turnVisible,
|
|
403
|
+
smallScreenLimits: smallScreenLimits,
|
|
404
|
+
bottomComponent: ({ squareSize: sz }) => navigationToolbarSize(sz, buttons),
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
}
|
|
409
|
+
|
|
230
410
|
|
|
411
|
+
function computeBarScheme(playButtonVisible: boolean | undefined, flipButtonVisible: boolean | undefined,
|
|
412
|
+
additionalButtons: NavigationBarScheme | undefined): NavigationBarScheme {
|
|
413
|
+
|
|
414
|
+
// WARNING: the logic here must be the same as the one in `renderToolbar()`.
|
|
415
|
+
const buttons: NavigationBarScheme = [];
|
|
416
|
+
|
|
417
|
+
buttons.push('button'); // go-first
|
|
418
|
+
buttons.push('button'); // go-previous
|
|
419
|
+
if (playButtonVisible ?? NavigationBoard.defaultProps.playButtonVisible) {
|
|
420
|
+
buttons.push('button');
|
|
421
|
+
}
|
|
422
|
+
buttons.push('button'); // go-next
|
|
423
|
+
buttons.push('button'); // go-last
|
|
424
|
+
buttons.push('spacer');
|
|
425
|
+
if (flipButtonVisible ?? NavigationBoard.defaultProps.flipButtonVisible) {
|
|
426
|
+
buttons.push('button');
|
|
427
|
+
}
|
|
428
|
+
buttons.push('spacer');
|
|
429
|
+
|
|
430
|
+
if (additionalButtons !== undefined) {
|
|
431
|
+
for (const button of additionalButtons) {
|
|
432
|
+
buttons.push(button);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
return buttons;
|
|
231
437
|
}
|