kokopu-react 3.1.0 → 3.2.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.
Files changed (234) hide show
  1. package/.eslintrc.yml +1 -1
  2. package/CHANGELOG.md +6 -0
  3. package/dist/lib/chessboard/BoardProperties.js.map +1 -1
  4. package/dist/lib/chessboard/Chessboard.css +13 -13
  5. package/dist/lib/chessboard/Chessboard.js.map +1 -1
  6. package/dist/lib/chessboard/ChessboardImpl.js.map +1 -1
  7. package/dist/lib/chessboard/Draggable.js.map +1 -1
  8. package/dist/lib/chessboard/Motion.js.map +1 -1
  9. package/dist/lib/chessboard/colorsets.js.map +1 -1
  10. package/dist/lib/chessboard/piecesets.js.map +1 -1
  11. package/dist/lib/errorbox/ErrorBox.css +18 -18
  12. package/dist/lib/errorbox/ErrorBox.js.map +1 -1
  13. package/dist/lib/errorbox/parsing.js.map +1 -1
  14. package/dist/lib/exception.js.map +1 -1
  15. package/dist/lib/i18n.d.ts +1 -0
  16. package/dist/lib/i18n.js +1 -0
  17. package/dist/lib/i18n.js.map +1 -1
  18. package/dist/lib/icons/AnnotationSymbolShape.css +6 -6
  19. package/dist/lib/icons/AnnotationSymbolShape.js.map +1 -1
  20. package/dist/lib/icons/ArrowMarkerIcon.js.map +1 -1
  21. package/dist/lib/icons/ArrowTip.js.map +1 -1
  22. package/dist/lib/icons/ChessPieceIcon.js.map +1 -1
  23. package/dist/lib/icons/SquareMarkerIcon.js.map +1 -1
  24. package/dist/lib/icons/TextMarkerIcon.js.map +1 -1
  25. package/dist/lib/icons/arrow.css +1 -1
  26. package/dist/lib/index.d.ts +1 -0
  27. package/dist/lib/index.js +1 -0
  28. package/dist/lib/index.js.map +1 -1
  29. package/dist/lib/movetext/Movetext.css +27 -27
  30. package/dist/lib/movetext/Movetext.js.map +1 -1
  31. package/dist/lib/movetext/MovetextImpl.js.map +1 -1
  32. package/dist/lib/movetext/fonts.css +7 -7
  33. package/dist/lib/movetext/htmlFilter.js.map +1 -1
  34. package/dist/lib/movetext/moveFormatter.js.map +1 -1
  35. package/dist/lib/navigationboard/NavigationBoard.d.ts +39 -1
  36. package/dist/lib/navigationboard/NavigationBoard.js +94 -11
  37. package/dist/lib/navigationboard/NavigationBoard.js.map +1 -1
  38. package/dist/lib/navigationboard/NavigationButton.d.ts +54 -0
  39. package/dist/lib/navigationboard/NavigationButton.js +35 -0
  40. package/dist/lib/navigationboard/NavigationButton.js.map +1 -0
  41. package/dist/lib/navigationboard/NavigationField.css +7 -7
  42. package/dist/lib/navigationboard/NavigationField.js.map +1 -1
  43. package/dist/lib/navigationboard/NavigationToolbar.css +16 -13
  44. package/dist/lib/navigationboard/NavigationToolbar.d.ts +3 -10
  45. package/dist/lib/navigationboard/NavigationToolbar.js +31 -82
  46. package/dist/lib/navigationboard/NavigationToolbar.js.map +1 -1
  47. package/dist/lib/navigationboard/iconPaths.d.ts +29 -0
  48. package/dist/lib/navigationboard/iconPaths.js +91 -0
  49. package/dist/lib/navigationboard/iconPaths.js.map +1 -0
  50. package/dist/lib/sanitization.js.map +1 -1
  51. package/dist/lib/types.js.map +1 -1
  52. package/dist/lib/util.js.map +1 -1
  53. package/doc_src/demo/PageChessboardBase.tsx +115 -115
  54. package/doc_src/demo/PageChessboardInteraction.tsx +303 -303
  55. package/doc_src/demo/PageChessboardMove.tsx +173 -173
  56. package/doc_src/demo/PageChessboardSmallScreens.tsx +94 -94
  57. package/doc_src/demo/PageMovetextBase.tsx +180 -180
  58. package/doc_src/demo/PageMovetextInteraction.tsx +123 -123
  59. package/doc_src/demo/PageNavigationBoardBase.tsx +144 -137
  60. package/doc_src/demo/PageNavigationBoardUncontrolledVsControlled.tsx +69 -69
  61. package/doc_src/demo/decs.d.ts +4 -4
  62. package/doc_src/demo/demo.css +12 -12
  63. package/doc_src/demo/util.ts +1 -1
  64. package/doc_src/examples/NavigationBoard.md +1 -1
  65. package/doc_src/theming/LogoRenderer.js +13 -13
  66. package/doc_src/theming/theming.css +5 -5
  67. package/package.json +95 -95
  68. package/scripts/doc.styleguide.config.js +131 -131
  69. package/scripts/doc.tsconfig.json +5 -5
  70. package/scripts/docker-compose.yml +1 -1
  71. package/scripts/test-graphic.tsconfig.json +5 -5
  72. package/scripts/test-graphic.webpack.config.js +57 -57
  73. package/scripts/test-headless.webpack.config.js +29 -29
  74. package/src/chessboard/BoardProperties.ts +68 -68
  75. package/src/chessboard/Chessboard.css +13 -13
  76. package/src/chessboard/Chessboard.tsx +380 -380
  77. package/src/chessboard/ChessboardImpl.tsx +557 -557
  78. package/src/chessboard/Draggable.tsx +185 -185
  79. package/src/chessboard/Motion.tsx +67 -67
  80. package/src/chessboard/colorsets.ts +66 -66
  81. package/src/chessboard/piecesets.ts +84 -84
  82. package/src/decs.d.ts +2 -2
  83. package/src/errorbox/ErrorBox.css +18 -18
  84. package/src/errorbox/ErrorBox.tsx +75 -75
  85. package/src/errorbox/parsing.tsx +95 -95
  86. package/src/exception.ts +17 -17
  87. package/src/i18n.ts +1 -0
  88. package/src/icons/AnnotationSymbolShape.css +6 -6
  89. package/src/icons/AnnotationSymbolShape.tsx +31 -31
  90. package/src/icons/ArrowMarkerIcon.tsx +34 -34
  91. package/src/icons/ArrowTip.tsx +14 -14
  92. package/src/icons/ChessPieceIcon.tsx +45 -45
  93. package/src/icons/SquareMarkerIcon.tsx +20 -20
  94. package/src/icons/TextMarkerIcon.tsx +29 -29
  95. package/src/icons/arrow.css +1 -1
  96. package/src/index.ts +3 -2
  97. package/src/movetext/Movetext.css +27 -27
  98. package/src/movetext/Movetext.tsx +158 -158
  99. package/src/movetext/MovetextImpl.tsx +345 -345
  100. package/src/movetext/fonts.css +7 -7
  101. package/src/movetext/htmlFilter.tsx +129 -129
  102. package/src/movetext/moveFormatter.tsx +37 -37
  103. package/src/navigationboard/NavigationBoard.tsx +297 -178
  104. package/src/navigationboard/NavigationButton.ts +72 -0
  105. package/src/navigationboard/NavigationField.css +7 -7
  106. package/src/navigationboard/NavigationField.tsx +90 -90
  107. package/src/navigationboard/NavigationToolbar.css +16 -13
  108. package/src/navigationboard/NavigationToolbar.tsx +60 -117
  109. package/src/navigationboard/iconPaths.ts +98 -0
  110. package/src/sanitization.ts +17 -17
  111. package/src/types.ts +116 -116
  112. package/src/util.ts +11 -11
  113. package/test/01_types.js +167 -167
  114. package/test/02_chessboard_util.js +114 -114
  115. package/test/03_error_box_graphic.js +16 -16
  116. package/test/04_icons_graphic.js +32 -32
  117. package/test/05_chessboard_graphic.js +60 -60
  118. package/test/06_chessboard_animation.js +36 -36
  119. package/test/07_chessboard_interaction.js +101 -101
  120. package/test/08_chessboard_play_moves.js +62 -62
  121. package/test/09_chessboard_small_screens.js +32 -32
  122. package/test/10_movetext_graphic.js +32 -32
  123. package/test/11_movetext_interaction.js +100 -100
  124. package/test/12_navigation_board_base.js +151 -0
  125. package/test/13_navigation_board_graphic.js +68 -0
  126. package/test/14_navigation_board_autoplay.js +100 -0
  127. package/test/common/graphic.js +106 -97
  128. package/test/graphic_references/12_navigation_board_base/controlled/default.png +0 -0
  129. package/test/graphic_references/{12_navigation_board/controlled/forbidden_navigation_1.png → 12_navigation_board_base/controlled/forbidden_navigation_0.png} +0 -0
  130. package/test/graphic_references/{12_navigation_board/controlled/invalid_node_id.png → 12_navigation_board_base/controlled/forbidden_navigation_1.png} +0 -0
  131. package/test/graphic_references/{12_navigation_board/controlled/forbidden_navigation_0.png → 12_navigation_board_base/controlled/invalid_node_id.png} +0 -0
  132. package/test/graphic_references/12_navigation_board_base/controlled/no_callback_defined_0.png +0 -0
  133. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/controlled/no_callback_defined_1.png +0 -0
  134. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/controlled/overriding_initial_node_id.png +0 -0
  135. package/test/graphic_references/{12_navigation_board/controlled/regular_navigation_1.png → 12_navigation_board_base/controlled/regular_navigation_0.png} +0 -0
  136. 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
  137. package/test/graphic_references/{12_navigation_board/controlled/regular_navigation_3.png → 12_navigation_board_base/controlled/regular_navigation_2.png} +0 -0
  138. package/test/graphic_references/{12_navigation_board/controlled/regular_navigation_0.png → 12_navigation_board_base/controlled/regular_navigation_3.png} +0 -0
  139. 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
  140. 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
  141. 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
  142. 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
  143. package/test/graphic_references/12_navigation_board_base/uncontrolled/forbidden_navigation_at_end_1.png +0 -0
  144. package/test/graphic_references/12_navigation_board_base/uncontrolled/forbidden_navigation_at_end_2.png +0 -0
  145. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/initial_state_at_end.png +0 -0
  146. package/test/graphic_references/12_navigation_board_base/uncontrolled/initial_state_at_specific_id.png +0 -0
  147. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/initial_state_default.png +0 -0
  148. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/initial_state_default_with_game_index.png +0 -0
  149. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/initial_state_on_null-move.png +0 -0
  150. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/navigation_with_keys_0.png +0 -0
  151. package/test/graphic_references/12_navigation_board_base/uncontrolled/navigation_with_keys_1.png +0 -0
  152. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/navigation_with_keys_2.png +0 -0
  153. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/navigation_with_keys_3.png +0 -0
  154. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/navigation_with_keys_4.png +0 -0
  155. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_flipping_0.png +0 -0
  156. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_flipping_1.png +0 -0
  157. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_navigation_0.png +0 -0
  158. package/test/graphic_references/{12_navigation_board/controlled/default.png → 12_navigation_board_base/uncontrolled/regular_navigation_1.png} +0 -0
  159. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_navigation_2.png +0 -0
  160. package/test/graphic_references/12_navigation_board_base/uncontrolled/regular_navigation_3.png +0 -0
  161. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_navigation_4.png +0 -0
  162. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_navigation_5.png +0 -0
  163. package/test/graphic_references/13_navigation_board_graphic/additional_buttons/error_1.png +0 -0
  164. package/test/graphic_references/13_navigation_board_graphic/additional_buttons/error_2.png +0 -0
  165. package/test/graphic_references/13_navigation_board_graphic/additional_buttons/multiple_buttons.png +0 -0
  166. package/test/graphic_references/{12_navigation_board/uncontrolled/regular_navigation_3.png → 13_navigation_board_graphic/additional_buttons/single_button.png} +0 -0
  167. package/test/graphic_references/{12_navigation_board → 13_navigation_board_graphic}/theme/custom_1.png +0 -0
  168. package/test/graphic_references/{12_navigation_board → 13_navigation_board_graphic}/theme/custom_2.png +0 -0
  169. package/test/graphic_references/{12_navigation_board → 13_navigation_board_graphic}/theme/large.png +0 -0
  170. package/test/graphic_references/13_navigation_board_graphic/theme/small.png +0 -0
  171. package/test/graphic_references/14_navigation_board_autoplay/controlled/after_1_move_acknowledging_is-playing_changes.png +0 -0
  172. package/test/graphic_references/14_navigation_board_autoplay/controlled/after_1_move_not_acknowledging_is-playing_changes.png +0 -0
  173. package/test/graphic_references/14_navigation_board_autoplay/controlled/after_2_moves_acknowledging_node_changes.png +0 -0
  174. package/test/graphic_references/14_navigation_board_autoplay/controlled/after_2_moves_not_acknowledging_node_changes.png +0 -0
  175. 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
  176. 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
  177. package/test/graphic_references/14_navigation_board_autoplay/controlled/initial_state_acknowledging_is-playing_changes.png +0 -0
  178. package/test/graphic_references/14_navigation_board_autoplay/controlled/initial_state_acknowledging_node_changes.png +0 -0
  179. 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
  180. package/test/graphic_references/14_navigation_board_autoplay/controlled/initial_state_close_to_end.png +0 -0
  181. package/test/graphic_references/14_navigation_board_autoplay/controlled/initial_state_not_acknowledging_is-playing_changes.png +0 -0
  182. package/test/graphic_references/14_navigation_board_autoplay/controlled/initial_state_not_acknowledging_node_changes.png +0 -0
  183. package/test/graphic_references/14_navigation_board_autoplay/uncontrolled/after_2_moves_from_beginning_after_stop.png +0 -0
  184. package/test/graphic_references/14_navigation_board_autoplay/uncontrolled/after_2_moves_from_beginning_before_stop.png +0 -0
  185. package/test/graphic_references/14_navigation_board_autoplay/uncontrolled/after_reaching_the_end_after_stop.png +0 -0
  186. package/test/graphic_references/14_navigation_board_autoplay/uncontrolled/after_reaching_the_end_before_stop.png +0 -0
  187. package/test/graphic_references/14_navigation_board_autoplay/uncontrolled/initial_state_close_to_end.png +0 -0
  188. package/test/graphic_references/{12_navigation_board/uncontrolled/navigation_with_keys_1.png → 14_navigation_board_autoplay/uncontrolled/initial_state_default.png} +0 -0
  189. package/test/graphic_test_app/03_error_box_graphic/base.tsx +14 -14
  190. package/test/graphic_test_app/03_error_box_graphic/localization.tsx +1 -1
  191. package/test/graphic_test_app/04_icons_graphic/chess_piece.tsx +7 -7
  192. package/test/graphic_test_app/04_icons_graphic/marker.tsx +15 -15
  193. package/test/graphic_test_app/05_chessboard_graphic/annotations.tsx +7 -7
  194. package/test/graphic_test_app/05_chessboard_graphic/base.tsx +6 -6
  195. package/test/graphic_test_app/05_chessboard_graphic/chess_variants.tsx +7 -7
  196. package/test/graphic_test_app/05_chessboard_graphic/flipped.tsx +5 -5
  197. package/test/graphic_test_app/05_chessboard_graphic/move.tsx +12 -12
  198. package/test/graphic_test_app/05_chessboard_graphic/theme.tsx +12 -12
  199. package/test/graphic_test_app/06_chessboard_animation/base_1.tsx +6 -6
  200. package/test/graphic_test_app/06_chessboard_animation/base_2.tsx +6 -6
  201. package/test/graphic_test_app/06_chessboard_animation/base_3.tsx +6 -6
  202. package/test/graphic_test_app/06_chessboard_animation/on_redraw.tsx +16 -16
  203. package/test/graphic_test_app/07_chessboard_interaction/click_squares.tsx +5 -5
  204. package/test/graphic_test_app/07_chessboard_interaction/edit_arrows.tsx +4 -4
  205. package/test/graphic_test_app/07_chessboard_interaction/error.tsx +2 -2
  206. package/test/graphic_test_app/07_chessboard_interaction/move_pieces.tsx +5 -5
  207. package/test/graphic_test_app/08_chessboard_play_moves/base.tsx +8 -8
  208. package/test/graphic_test_app/08_chessboard_play_moves/promotions.tsx +4 -4
  209. package/test/graphic_test_app/09_chessboard_small_screens/base.tsx +9 -9
  210. package/test/graphic_test_app/09_chessboard_small_screens/top_bottom_components.tsx +9 -9
  211. package/test/graphic_test_app/10_movetext_graphic/base.tsx +4 -4
  212. package/test/graphic_test_app/10_movetext_graphic/error.tsx +6 -6
  213. package/test/graphic_test_app/10_movetext_graphic/format_move.tsx +1 -1
  214. package/test/graphic_test_app/10_movetext_graphic/html.tsx +5 -5
  215. package/test/graphic_test_app/10_movetext_graphic/options.tsx +10 -10
  216. package/test/graphic_test_app/11_movetext_interaction/error.tsx +1 -1
  217. package/test/graphic_test_app/11_movetext_interaction/select_moves.tsx +11 -11
  218. package/test/graphic_test_app/{12_navigation_board → 12_navigation_board_base}/controlled.tsx +5 -5
  219. package/test/graphic_test_app/{12_navigation_board → 12_navigation_board_base}/uncontrolled.tsx +7 -7
  220. package/test/graphic_test_app/13_navigation_board_graphic/additional_buttons.tsx +49 -0
  221. package/test/graphic_test_app/{12_navigation_board → 13_navigation_board_graphic}/error.tsx +2 -2
  222. package/test/graphic_test_app/{12_navigation_board → 13_navigation_board_graphic}/theme.tsx +4 -4
  223. package/test/graphic_test_app/14_navigation_board_autoplay/controlled.tsx +73 -0
  224. package/test/graphic_test_app/14_navigation_board_autoplay/uncontrolled.tsx +34 -0
  225. package/test/graphic_test_app/common/decs.d.ts +2 -2
  226. package/test/graphic_test_app/common/test_app.css +15 -15
  227. package/test/graphic_test_app/common/test_app.tsx +48 -48
  228. package/tsconfig.json +13 -13
  229. package/test/12_navigation_board.js +0 -168
  230. package/test/graphic_references/12_navigation_board/controlled/regular_navigation_2.png +0 -0
  231. package/test/graphic_references/12_navigation_board/theme/small.png +0 -0
  232. package/test/graphic_references/12_navigation_board/uncontrolled/regular_navigation_1.png +0 -0
  233. /package/test/graphic_references/{12_navigation_board → 13_navigation_board_graphic}/error/pgn_parsing_error.png +0 -0
  234. /package/test/graphic_references/{12_navigation_board → 13_navigation_board_graphic}/error/wrong_game_type.png +0 -0
@@ -36,34 +36,34 @@ import { ErrorBox } from './ErrorBox';
36
36
  * Try to interpret the given object as a chess position.
37
37
  */
38
38
  export function parsePosition(position: Position | string, componentName: string):
39
- { error: true, errorBox: JSX.Element } | { error: false, position: Position }
39
+ { error: true, errorBox: JSX.Element } | { error: false, position: Position }
40
40
  {
41
- if (position instanceof Position) {
42
- return { error: false, position: position };
43
- }
44
- else if (position === 'start' || position === 'empty') {
45
- return { error: false, position: new Position(position) };
46
- }
47
- else if (typeof position === 'string') {
48
- try {
49
- const { variant, fen } = splitGameVariantAndFEN(position);
50
- const result = new Position(variant, 'empty');
51
- result.fen(fen);
52
- return { error: false, position: result };
53
- }
54
- catch (e) {
55
- // istanbul ignore else
56
- if (e instanceof kokopuException.InvalidFEN) {
57
- return { error: true, errorBox: <ErrorBox title={i18n.INVALID_FEN_ERROR_TITLE} message={e.message} /> };
58
- }
59
- else {
60
- throw e;
61
- }
62
- }
63
- }
64
- else {
65
- throw new IllegalArgument(componentName, 'position');
66
- }
41
+ if (position instanceof Position) {
42
+ return { error: false, position: position };
43
+ }
44
+ else if (position === 'start' || position === 'empty') {
45
+ return { error: false, position: new Position(position) };
46
+ }
47
+ else if (typeof position === 'string') {
48
+ try {
49
+ const { variant, fen } = splitGameVariantAndFEN(position);
50
+ const result = new Position(variant, 'empty');
51
+ result.fen(fen);
52
+ return { error: false, position: result };
53
+ }
54
+ catch (e) {
55
+ // istanbul ignore else
56
+ if (e instanceof kokopuException.InvalidFEN) {
57
+ return { error: true, errorBox: <ErrorBox title={i18n.INVALID_FEN_ERROR_TITLE} message={e.message} /> };
58
+ }
59
+ else {
60
+ throw e;
61
+ }
62
+ }
63
+ }
64
+ else {
65
+ throw new IllegalArgument(componentName, 'position');
66
+ }
67
67
  }
68
68
 
69
69
 
@@ -71,12 +71,12 @@ export function parsePosition(position: Position | string, componentName: string
71
71
  * Look for an optional 'chess-variant:' prefix in the position attribute.
72
72
  */
73
73
  function splitGameVariantAndFEN(position: string): { variant: GameVariant, fen: string } {
74
- const separatorIndex = position.indexOf(':');
75
- if (separatorIndex < 0) {
76
- return { variant: 'regular', fen: position };
77
- }
78
- const variant = position.substring(0, separatorIndex);
79
- return isGameVariant(variant) ? { variant: variant, fen: position.substring(separatorIndex + 1) } : { variant: 'regular', fen: position };
74
+ const separatorIndex = position.indexOf(':');
75
+ if (separatorIndex < 0) {
76
+ return { variant: 'regular', fen: position };
77
+ }
78
+ const variant = position.substring(0, separatorIndex);
79
+ return isGameVariant(variant) ? { variant: variant, fen: position.substring(separatorIndex + 1) } : { variant: 'regular', fen: position };
80
80
  }
81
81
 
82
82
 
@@ -84,41 +84,41 @@ function splitGameVariantAndFEN(position: string): { variant: GameVariant, fen:
84
84
  * Try to interpret the given object `move` as a move descriptor based on the given position.
85
85
  */
86
86
  export function parseMove(position: Position, move: MoveDescriptor | string | undefined, componentName: string):
87
- { error: true, errorBox: JSX.Element } | { error: false, type: 'none' | 'null-move' } | { error: false, type: 'regular', move: MoveDescriptor }
87
+ { error: true, errorBox: JSX.Element } | { error: false, type: 'none' | 'null-move' } | { error: false, type: 'regular', move: MoveDescriptor }
88
88
  {
89
- if (move === undefined || move === null) {
90
- return { error: false, type: 'none' };
91
- }
92
- else if (move instanceof MoveDescriptor) {
93
- return { error: false, type: 'regular', move: move };
94
- }
95
- else if (typeof move === 'string') {
96
- if (move === '--') {
97
- if (position.isNullMoveLegal()) {
98
- return { error: false, type: 'null-move' };
99
- }
100
- else {
101
- return { error: true, errorBox: <ErrorBox title={i18n.INVALID_NOTATION_ERROR_TITLE} message={kokopuI18n.ILLEGAL_NULL_MOVE} /> };
102
- }
103
- }
104
- else {
105
- try {
106
- return { error: false, type: 'regular', move: position.notation(move) };
107
- }
108
- catch (e) {
109
- // istanbul ignore else
110
- if (e instanceof kokopuException.InvalidNotation) {
111
- return { error: true, errorBox: <ErrorBox title={i18n.INVALID_NOTATION_ERROR_TITLE} message={e.message} /> };
112
- }
113
- else {
114
- throw e;
115
- }
116
- }
117
- }
118
- }
119
- else {
120
- throw new IllegalArgument(componentName, 'move');
121
- }
89
+ if (move === undefined || move === null) {
90
+ return { error: false, type: 'none' };
91
+ }
92
+ else if (move instanceof MoveDescriptor) {
93
+ return { error: false, type: 'regular', move: move };
94
+ }
95
+ else if (typeof move === 'string') {
96
+ if (move === '--') {
97
+ if (position.isNullMoveLegal()) {
98
+ return { error: false, type: 'null-move' };
99
+ }
100
+ else {
101
+ return { error: true, errorBox: <ErrorBox title={i18n.INVALID_NOTATION_ERROR_TITLE} message={kokopuI18n.ILLEGAL_NULL_MOVE} /> };
102
+ }
103
+ }
104
+ else {
105
+ try {
106
+ return { error: false, type: 'regular', move: position.notation(move) };
107
+ }
108
+ catch (e) {
109
+ // istanbul ignore else
110
+ if (e instanceof kokopuException.InvalidNotation) {
111
+ return { error: true, errorBox: <ErrorBox title={i18n.INVALID_NOTATION_ERROR_TITLE} message={e.message} /> };
112
+ }
113
+ else {
114
+ throw e;
115
+ }
116
+ }
117
+ }
118
+ }
119
+ else {
120
+ throw new IllegalArgument(componentName, 'move');
121
+ }
122
122
  }
123
123
 
124
124
 
@@ -126,33 +126,33 @@ export function parseMove(position: Position, move: MoveDescriptor | string | un
126
126
  * Try to interpret the given object as a chess game.
127
127
  */
128
128
  export function parseGame(game: Game | Database | string, gameIndex: number, componentName: string):
129
- { error: true, errorBox: JSX.Element } | { error: false, game: Game }
129
+ { error: true, errorBox: JSX.Element } | { error: false, game: Game }
130
130
  {
131
- if (game instanceof Game) {
132
- return { error: false, game: game };
133
- }
134
- else if (game instanceof Database || typeof game === 'string') {
135
- if (!Number.isInteger(gameIndex) || gameIndex < 0) {
136
- throw new IllegalArgument(componentName, 'gameIndex');
137
- }
138
- try {
139
- const result = game instanceof Database ? game.game(gameIndex) : pgnRead(game, gameIndex);
140
- return { error: false, game: result };
141
- }
142
- catch (e) {
143
- // istanbul ignore else
144
- if (e instanceof kokopuException.InvalidPGN) {
145
- return {
146
- error: true,
147
- errorBox: <ErrorBox title={i18n.INVALID_PGN_ERROR_TITLE} message={e.message} text={e.pgn} errorIndex={e.index} lineNumber={e.lineNumber} />,
148
- };
149
- }
150
- else {
151
- throw e;
152
- }
153
- }
154
- }
155
- else {
156
- throw new IllegalArgument(componentName, 'game');
157
- }
131
+ if (game instanceof Game) {
132
+ return { error: false, game: game };
133
+ }
134
+ else if (game instanceof Database || typeof game === 'string') {
135
+ if (!Number.isInteger(gameIndex) || gameIndex < 0) {
136
+ throw new IllegalArgument(componentName, 'gameIndex');
137
+ }
138
+ try {
139
+ const result = game instanceof Database ? game.game(gameIndex) : pgnRead(game, gameIndex);
140
+ return { error: false, game: result };
141
+ }
142
+ catch (e) {
143
+ // istanbul ignore else
144
+ if (e instanceof kokopuException.InvalidPGN) {
145
+ return {
146
+ error: true,
147
+ errorBox: <ErrorBox title={i18n.INVALID_PGN_ERROR_TITLE} message={e.message} text={e.pgn} errorIndex={e.index} lineNumber={e.lineNumber} />,
148
+ };
149
+ }
150
+ else {
151
+ throw e;
152
+ }
153
+ }
154
+ }
155
+ else {
156
+ throw new IllegalArgument(componentName, 'game');
157
+ }
158
158
  }
package/src/exception.ts CHANGED
@@ -33,21 +33,21 @@
33
33
  */
34
34
  export class IllegalArgument {
35
35
 
36
- /** Name of the function or component that raises the exception. */
37
- functionOrComponentName: string;
38
-
39
- /** Name of the argument that causes the error. */
40
- argumentName: string;
41
-
42
- constructor(functionOrComponentName: string, argumentName: string) {
43
- this.functionOrComponentName = functionOrComponentName;
44
- this.argumentName = argumentName;
45
- }
46
-
47
- /**
48
- * @ignore
49
- */
50
- toString(): string {
51
- return `Illegal argument '${this.argumentName}' in function or component ${this.functionOrComponentName}`;
52
- }
36
+ /** Name of the function or component that raises the exception. */
37
+ functionOrComponentName: string;
38
+
39
+ /** Name of the argument that causes the error. */
40
+ argumentName: string;
41
+
42
+ constructor(functionOrComponentName: string, argumentName: string) {
43
+ this.functionOrComponentName = functionOrComponentName;
44
+ this.argumentName = argumentName;
45
+ }
46
+
47
+ /**
48
+ * @ignore
49
+ */
50
+ toString(): string {
51
+ return `Illegal argument '${this.argumentName}' in function or component ${this.functionOrComponentName}`;
52
+ }
53
53
  }
package/src/i18n.ts CHANGED
@@ -42,6 +42,7 @@ export let TOOLTIP_GO_FIRST = 'Go to the beginning of the game';
42
42
  export let TOOLTIP_GO_PREVIOUS = 'Go to the previous move';
43
43
  export let TOOLTIP_GO_NEXT = 'Go to the next move';
44
44
  export let TOOLTIP_GO_LAST = 'Go to the end of the game';
45
+ export let TOOLTIP_PLAY_STOP = 'Play/stop the game';
45
46
  export let TOOLTIP_FLIP = 'Flip the board';
46
47
 
47
48
  // Movetext
@@ -23,13 +23,13 @@
23
23
 
24
24
 
25
25
  .kokopu-symbolCircle {
26
- fill: transparent;
26
+ fill: transparent;
27
27
  }
28
28
 
29
29
  .kokopu-symbolText {
30
- font-style: normal;
31
- font-family: sans-serif;
32
- text-anchor: middle;
33
- dominant-baseline: central;
34
- letter-spacing: 0px;
30
+ font-style: normal;
31
+ font-family: sans-serif;
32
+ text-anchor: middle;
33
+ dominant-baseline: central;
34
+ letter-spacing: 0px;
35
35
  }
@@ -35,30 +35,30 @@ const CIRCLE_RADIUS_FACTOR = 0.425;
35
35
 
36
36
  interface AnnotationSymbolShapeProps {
37
37
 
38
- /**
39
- * X-coordinate of the center of the symbol.
40
- */
41
- x: number;
38
+ /**
39
+ * X-coordinate of the center of the symbol.
40
+ */
41
+ x: number;
42
42
 
43
- /**
44
- * Y-coordinate of the center of the symbol.
45
- */
46
- y: number;
43
+ /**
44
+ * Y-coordinate of the center of the symbol.
45
+ */
46
+ y: number;
47
47
 
48
- /**
49
- * Size of the symbol (i.e. size of square in which the symbol is rendered).
50
- */
51
- size: number;
48
+ /**
49
+ * Size of the symbol (i.e. size of square in which the symbol is rendered).
50
+ */
51
+ size: number;
52
52
 
53
- /**
54
- * Symbol code.
55
- */
56
- symbol: AnnotationSymbol;
53
+ /**
54
+ * Symbol code.
55
+ */
56
+ symbol: AnnotationSymbol;
57
57
 
58
- /**
59
- * [CSS color](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value) to use to colorize the shape (for example: `'green'`, `'#ff0000'`...).
60
- */
61
- color: string;
58
+ /**
59
+ * [CSS color](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value) to use to colorize the shape (for example: `'green'`, `'#ff0000'`...).
60
+ */
61
+ color: string;
62
62
  }
63
63
 
64
64
 
@@ -66,15 +66,15 @@ interface AnnotationSymbolShapeProps {
66
66
  * Symbol of a text marker.
67
67
  */
68
68
  export function AnnotationSymbolShape({ x, y, size, symbol, color }: AnnotationSymbolShapeProps) {
69
- if (symbol === 'dot') {
70
- return <circle cx={x} cy={y} r={size * DOT_RADIUS_FACTOR} fill={color} />;
71
- }
72
- else if (symbol === 'circle') {
73
- const thickness = size * SHAPE_THICKNESS_FACTOR;
74
- return <circle className="kokopu-symbolCircle" cx={x} cy={y} r={size * CIRCLE_RADIUS_FACTOR} stroke={color} strokeWidth={thickness} />;
75
- }
76
- else {
77
- const text = symbol === 'plus' ? '+' : symbol === 'times' ? '\u00d7' : symbol;
78
- return <text className="kokopu-symbolText" x={x} y={y} fill={color} fontSize={size}>{text}</text>;
79
- }
69
+ if (symbol === 'dot') {
70
+ return <circle cx={x} cy={y} r={size * DOT_RADIUS_FACTOR} fill={color} />;
71
+ }
72
+ else if (symbol === 'circle') {
73
+ const thickness = size * SHAPE_THICKNESS_FACTOR;
74
+ return <circle className="kokopu-symbolCircle" cx={x} cy={y} r={size * CIRCLE_RADIUS_FACTOR} stroke={color} strokeWidth={thickness} />;
75
+ }
76
+ else {
77
+ const text = symbol === 'plus' ? '+' : symbol === 'times' ? '\u00d7' : symbol;
78
+ return <text className="kokopu-symbolText" x={x} y={y} fill={color} fontSize={size}>{text}</text>;
79
+ }
80
80
  }
@@ -38,15 +38,15 @@ const ARROW_THICKNESS_FACTOR = 0.2;
38
38
 
39
39
  export interface ArrowMarkerIconProps {
40
40
 
41
- /**
42
- * Width and height (in pixels) of the icon.
43
- */
44
- size: number;
45
-
46
- /**
47
- * [CSS color](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value) to use to colorize the icon (for example: `'green'`, `'#ff0000'`...).
48
- */
49
- color: string;
41
+ /**
42
+ * Width and height (in pixels) of the icon.
43
+ */
44
+ size: number;
45
+
46
+ /**
47
+ * [CSS color](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value) to use to colorize the icon (for example: `'green'`, `'#ff0000'`...).
48
+ */
49
+ color: string;
50
50
  }
51
51
 
52
52
 
@@ -55,29 +55,29 @@ export interface ArrowMarkerIconProps {
55
55
  */
56
56
  export class ArrowMarkerIcon extends React.Component<ArrowMarkerIconProps> {
57
57
 
58
- static defaultProps: Partial<ArrowMarkerIconProps> = {
59
- color: 'currentcolor',
60
- };
61
-
62
- private arrowTipId = generateRandomId();
63
-
64
- render() {
65
-
66
- // Sanitize the inputs.
67
- const size = sanitizeBoundedInteger(this.props.size, MIN_SQUARE_SIZE, MAX_SQUARE_SIZE, () => new IllegalArgument('ArrowMarkerIcon', 'size'));
68
- const color = sanitizeString(this.props.color);
69
-
70
- // Render the component.
71
- const halfThickness = size * ARROW_THICKNESS_FACTOR / 2;
72
- const viewBox = `0 0 ${size} ${size}`;
73
- return (
74
- <svg className="kokopu-arrowMarkerIcon" viewBox={viewBox} width={size} height={size}>
75
- <defs>
76
- <ArrowTip id={this.arrowTipId} color={this.props.color} />
77
- </defs>
78
- <line className="kokopu-arrow" x1={halfThickness} y1={size / 2} x2={size - halfThickness * 3} y2={size / 2} stroke={color}
79
- strokeWidth={halfThickness * 2} markerEnd={`url(#${this.arrowTipId})`} />
80
- </svg>
81
- );
82
- }
58
+ static defaultProps: Partial<ArrowMarkerIconProps> = {
59
+ color: 'currentcolor',
60
+ };
61
+
62
+ private arrowTipId = generateRandomId();
63
+
64
+ render() {
65
+
66
+ // Sanitize the inputs.
67
+ const size = sanitizeBoundedInteger(this.props.size, MIN_SQUARE_SIZE, MAX_SQUARE_SIZE, () => new IllegalArgument('ArrowMarkerIcon', 'size'));
68
+ const color = sanitizeString(this.props.color);
69
+
70
+ // Render the component.
71
+ const halfThickness = size * ARROW_THICKNESS_FACTOR / 2;
72
+ const viewBox = `0 0 ${size} ${size}`;
73
+ return (
74
+ <svg className="kokopu-arrowMarkerIcon" viewBox={viewBox} width={size} height={size}>
75
+ <defs>
76
+ <ArrowTip id={this.arrowTipId} color={this.props.color} />
77
+ </defs>
78
+ <line className="kokopu-arrow" x1={halfThickness} y1={size / 2} x2={size - halfThickness * 3} y2={size / 2} stroke={color}
79
+ strokeWidth={halfThickness * 2} markerEnd={`url(#${this.arrowTipId})`} />
80
+ </svg>
81
+ );
82
+ }
83
83
  }
@@ -27,15 +27,15 @@ import * as React from 'react';
27
27
 
28
28
  interface ArrowTipProps {
29
29
 
30
- /**
31
- * ID of the element.
32
- */
33
- id: string;
34
-
35
- /**
36
- * [CSS color](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value) to use to colorize the shape (for example: `'green'`, `'#ff0000'`...).
37
- */
38
- color: string;
30
+ /**
31
+ * ID of the element.
32
+ */
33
+ id: string;
34
+
35
+ /**
36
+ * [CSS color](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value) to use to colorize the shape (for example: `'green'`, `'#ff0000'`...).
37
+ */
38
+ color: string;
39
39
  }
40
40
 
41
41
 
@@ -43,9 +43,9 @@ interface ArrowTipProps {
43
43
  * Tip of the arrow markers.
44
44
  */
45
45
  export function ArrowTip({ id, color }: ArrowTipProps) {
46
- return (
47
- <marker id={id} markerWidth={4} markerHeight={4} refX={2.5} refY={2} orient="auto">
48
- <path fill={color} d="M 4,2 L 0,4 L 1,2 L 0,0 Z" />
49
- </marker>
50
- );
46
+ return (
47
+ <marker id={id} markerWidth={4} markerHeight={4} refX={2.5} refY={2} orient="auto">
48
+ <path fill={color} d="M 4,2 L 0,4 L 1,2 L 0,0 Z" />
49
+ </marker>
50
+ );
51
51
  }
@@ -32,25 +32,25 @@ import { piecesets, DEFAULT_PIECESET } from '../chessboard/piecesets';
32
32
 
33
33
  export interface ChessPieceIconProps {
34
34
 
35
- /**
36
- * Width and height (in pixels) of each chess piece icon.
37
- */
38
- size: number;
39
-
40
- /**
41
- * Chess piece(s) to display.
42
- */
43
- type: ChessPieceIconType | ChessPieceIconType[];
44
-
45
- /**
46
- * Piece theme ID. Must be a property of `Chessboard.piecesets()`.
47
- */
48
- pieceset: string;
35
+ /**
36
+ * Width and height (in pixels) of each chess piece icon.
37
+ */
38
+ size: number;
39
+
40
+ /**
41
+ * Chess piece(s) to display.
42
+ */
43
+ type: ChessPieceIconType | ChessPieceIconType[];
44
+
45
+ /**
46
+ * Piece theme ID. Must be a property of `Chessboard.piecesets()`.
47
+ */
48
+ pieceset: string;
49
49
  }
50
50
 
51
51
 
52
52
  const defaultProps: Partial<ChessPieceIconProps> = {
53
- pieceset: DEFAULT_PIECESET,
53
+ pieceset: DEFAULT_PIECESET,
54
54
  };
55
55
 
56
56
 
@@ -59,22 +59,22 @@ const defaultProps: Partial<ChessPieceIconProps> = {
59
59
  */
60
60
  export function ChessPieceIcon({ size, type, pieceset }: ChessPieceIconProps) {
61
61
 
62
- // Sanitize the inputs.
63
- size = sanitizeBoundedInteger(size, MIN_SQUARE_SIZE, MAX_SQUARE_SIZE, () => new IllegalArgument('ChessPieceIcon', 'size'));
64
- const types = sanitizeChessPieceIconType(type, () => new IllegalArgument('ChessPieceIcon', 'type'));
65
- const piecesetData = piecesets[pieceset];
66
- if (!piecesetData) {
67
- throw new IllegalArgument('ChessPieceIcon', 'pieceset');
68
- }
69
-
70
- // Render the component.
71
- const width = size * types.length;
72
- const viewBox = `0 0 ${width} ${size}`;
73
- return (
74
- <svg className="kokopu-chessPieceIcon" viewBox={viewBox} width={width} height={size}>
75
- {types.map((t, i) => <image key={i} x={i * size} y={0} width={size} height={size} href={piecesetData[t]} />)}
76
- </svg>
77
- );
62
+ // Sanitize the inputs.
63
+ size = sanitizeBoundedInteger(size, MIN_SQUARE_SIZE, MAX_SQUARE_SIZE, () => new IllegalArgument('ChessPieceIcon', 'size'));
64
+ const types = sanitizeChessPieceIconType(type, () => new IllegalArgument('ChessPieceIcon', 'type'));
65
+ const piecesetData = piecesets[pieceset];
66
+ if (!piecesetData) {
67
+ throw new IllegalArgument('ChessPieceIcon', 'pieceset');
68
+ }
69
+
70
+ // Render the component.
71
+ const width = size * types.length;
72
+ const viewBox = `0 0 ${width} ${size}`;
73
+ return (
74
+ <svg className="kokopu-chessPieceIcon" viewBox={viewBox} width={width} height={size}>
75
+ {types.map((t, i) => <image key={i} x={i * size} y={0} width={size} height={size} href={piecesetData[t]} />)}
76
+ </svg>
77
+ );
78
78
  }
79
79
 
80
80
  ChessPieceIcon.defaultProps = defaultProps;
@@ -84,18 +84,18 @@ ChessPieceIcon.defaultProps = defaultProps;
84
84
  * Sanitization method for the small-screen limits parameter.
85
85
  */
86
86
  function sanitizeChessPieceIconType(type: ChessPieceIconType | ChessPieceIconType[], exceptionBuilder: () => IllegalArgument): ChessPieceIconType[] {
87
- if (Array.isArray(type)) {
88
- return type.map(t => {
89
- if (!isChessPieceIconType(t)) {
90
- throw exceptionBuilder();
91
- }
92
- return t;
93
- });
94
- }
95
- else if (isChessPieceIconType(type)) {
96
- return [ type ];
97
- }
98
- else {
99
- throw exceptionBuilder();
100
- }
87
+ if (Array.isArray(type)) {
88
+ return type.map(t => {
89
+ if (!isChessPieceIconType(t)) {
90
+ throw exceptionBuilder();
91
+ }
92
+ return t;
93
+ });
94
+ }
95
+ else if (isChessPieceIconType(type)) {
96
+ return [ type ];
97
+ }
98
+ else {
99
+ throw exceptionBuilder();
100
+ }
101
101
  }