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.
Files changed (236) hide show
  1. package/.eslintrc.yml +1 -1
  2. package/CHANGELOG.md +10 -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.d.ts +27 -2
  6. package/dist/lib/chessboard/Chessboard.js +36 -17
  7. package/dist/lib/chessboard/Chessboard.js.map +1 -1
  8. package/dist/lib/chessboard/ChessboardImpl.js.map +1 -1
  9. package/dist/lib/chessboard/Draggable.js.map +1 -1
  10. package/dist/lib/chessboard/Motion.js.map +1 -1
  11. package/dist/lib/chessboard/colorsets.js.map +1 -1
  12. package/dist/lib/chessboard/piecesets.js.map +1 -1
  13. package/dist/lib/errorbox/ErrorBox.css +18 -18
  14. package/dist/lib/errorbox/ErrorBox.js.map +1 -1
  15. package/dist/lib/errorbox/parsing.js.map +1 -1
  16. package/dist/lib/exception.js.map +1 -1
  17. package/dist/lib/i18n.d.ts +1 -0
  18. package/dist/lib/i18n.js +1 -0
  19. package/dist/lib/i18n.js.map +1 -1
  20. package/dist/lib/icons/AnnotationSymbolShape.css +6 -6
  21. package/dist/lib/icons/AnnotationSymbolShape.js.map +1 -1
  22. package/dist/lib/icons/ArrowMarkerIcon.js.map +1 -1
  23. package/dist/lib/icons/ArrowTip.js.map +1 -1
  24. package/dist/lib/icons/ChessPieceIcon.js.map +1 -1
  25. package/dist/lib/icons/SquareMarkerIcon.js.map +1 -1
  26. package/dist/lib/icons/TextMarkerIcon.js.map +1 -1
  27. package/dist/lib/icons/arrow.css +1 -1
  28. package/dist/lib/index.d.ts +1 -0
  29. package/dist/lib/index.js +1 -0
  30. package/dist/lib/index.js.map +1 -1
  31. package/dist/lib/movetext/Movetext.css +27 -27
  32. package/dist/lib/movetext/Movetext.js.map +1 -1
  33. package/dist/lib/movetext/MovetextImpl.js.map +1 -1
  34. package/dist/lib/movetext/fonts.css +7 -7
  35. package/dist/lib/movetext/htmlFilter.js.map +1 -1
  36. package/dist/lib/movetext/moveFormatter.js.map +1 -1
  37. package/dist/lib/navigationboard/NavigationBoard.d.ts +68 -1
  38. package/dist/lib/navigationboard/NavigationBoard.js +141 -13
  39. package/dist/lib/navigationboard/NavigationBoard.js.map +1 -1
  40. package/dist/lib/navigationboard/NavigationButton.d.ts +66 -0
  41. package/dist/lib/navigationboard/NavigationButton.js +67 -0
  42. package/dist/lib/navigationboard/NavigationButton.js.map +1 -0
  43. package/dist/lib/navigationboard/NavigationField.css +7 -7
  44. package/dist/lib/navigationboard/NavigationField.js.map +1 -1
  45. package/dist/lib/navigationboard/NavigationToolbar.css +16 -13
  46. package/dist/lib/navigationboard/NavigationToolbar.d.ts +10 -10
  47. package/dist/lib/navigationboard/NavigationToolbar.js +61 -79
  48. package/dist/lib/navigationboard/NavigationToolbar.js.map +1 -1
  49. package/dist/lib/navigationboard/iconPaths.d.ts +29 -0
  50. package/dist/lib/navigationboard/iconPaths.js +91 -0
  51. package/dist/lib/navigationboard/iconPaths.js.map +1 -0
  52. package/dist/lib/sanitization.js.map +1 -1
  53. package/dist/lib/types.js.map +1 -1
  54. package/dist/lib/util.js.map +1 -1
  55. package/doc_src/demo/PageChessboardBase.tsx +115 -115
  56. package/doc_src/demo/PageChessboardInteraction.tsx +303 -303
  57. package/doc_src/demo/PageChessboardMove.tsx +173 -173
  58. package/doc_src/demo/PageChessboardSmallScreens.tsx +94 -94
  59. package/doc_src/demo/PageMovetextBase.tsx +180 -180
  60. package/doc_src/demo/PageMovetextInteraction.tsx +123 -123
  61. package/doc_src/demo/PageNavigationBoardBase.tsx +144 -137
  62. package/doc_src/demo/PageNavigationBoardUncontrolledVsControlled.tsx +69 -69
  63. package/doc_src/demo/decs.d.ts +4 -4
  64. package/doc_src/demo/demo.css +12 -12
  65. package/doc_src/demo/util.ts +1 -1
  66. package/doc_src/examples/NavigationBoard.md +1 -1
  67. package/doc_src/theming/LogoRenderer.js +13 -13
  68. package/doc_src/theming/theming.css +5 -5
  69. package/package.json +95 -95
  70. package/scripts/doc.styleguide.config.js +131 -131
  71. package/scripts/doc.tsconfig.json +5 -5
  72. package/scripts/docker-compose.yml +1 -1
  73. package/scripts/test-graphic.tsconfig.json +5 -5
  74. package/scripts/test-graphic.webpack.config.js +57 -57
  75. package/scripts/test-headless.webpack.config.js +29 -29
  76. package/src/chessboard/BoardProperties.ts +68 -68
  77. package/src/chessboard/Chessboard.css +13 -13
  78. package/src/chessboard/Chessboard.tsx +436 -380
  79. package/src/chessboard/ChessboardImpl.tsx +557 -557
  80. package/src/chessboard/Draggable.tsx +185 -185
  81. package/src/chessboard/Motion.tsx +67 -67
  82. package/src/chessboard/colorsets.ts +66 -66
  83. package/src/chessboard/piecesets.ts +84 -84
  84. package/src/decs.d.ts +2 -2
  85. package/src/errorbox/ErrorBox.css +18 -18
  86. package/src/errorbox/ErrorBox.tsx +75 -75
  87. package/src/errorbox/parsing.tsx +95 -95
  88. package/src/exception.ts +17 -17
  89. package/src/i18n.ts +1 -0
  90. package/src/icons/AnnotationSymbolShape.css +6 -6
  91. package/src/icons/AnnotationSymbolShape.tsx +31 -31
  92. package/src/icons/ArrowMarkerIcon.tsx +34 -34
  93. package/src/icons/ArrowTip.tsx +14 -14
  94. package/src/icons/ChessPieceIcon.tsx +45 -45
  95. package/src/icons/SquareMarkerIcon.tsx +20 -20
  96. package/src/icons/TextMarkerIcon.tsx +29 -29
  97. package/src/icons/arrow.css +1 -1
  98. package/src/index.ts +3 -2
  99. package/src/movetext/Movetext.css +27 -27
  100. package/src/movetext/Movetext.tsx +158 -158
  101. package/src/movetext/MovetextImpl.tsx +345 -345
  102. package/src/movetext/fonts.css +7 -7
  103. package/src/movetext/htmlFilter.tsx +129 -129
  104. package/src/movetext/moveFormatter.tsx +37 -37
  105. package/src/navigationboard/NavigationBoard.tsx +386 -180
  106. package/src/navigationboard/NavigationButton.ts +114 -0
  107. package/src/navigationboard/NavigationField.css +7 -7
  108. package/src/navigationboard/NavigationField.tsx +90 -90
  109. package/src/navigationboard/NavigationToolbar.css +16 -13
  110. package/src/navigationboard/NavigationToolbar.tsx +98 -112
  111. package/src/navigationboard/iconPaths.ts +98 -0
  112. package/src/sanitization.ts +17 -17
  113. package/src/types.ts +116 -116
  114. package/src/util.ts +11 -11
  115. package/test/01_types.js +167 -167
  116. package/test/02_chessboard_util.js +191 -115
  117. package/test/03_error_box_graphic.js +16 -16
  118. package/test/04_icons_graphic.js +32 -32
  119. package/test/05_chessboard_graphic.js +60 -60
  120. package/test/06_chessboard_animation.js +36 -36
  121. package/test/07_chessboard_interaction.js +101 -101
  122. package/test/08_chessboard_play_moves.js +62 -62
  123. package/test/09_chessboard_small_screens.js +32 -32
  124. package/test/10_movetext_graphic.js +32 -32
  125. package/test/11_movetext_interaction.js +100 -100
  126. package/test/12_navigation_board_base.js +151 -0
  127. package/test/13_navigation_board_graphic.js +68 -0
  128. package/test/14_navigation_board_autoplay.js +100 -0
  129. package/test/common/graphic.js +106 -97
  130. package/test/graphic_references/12_navigation_board_base/controlled/default.png +0 -0
  131. package/test/graphic_references/{12_navigation_board/controlled/forbidden_navigation_1.png → 12_navigation_board_base/controlled/forbidden_navigation_0.png} +0 -0
  132. package/test/graphic_references/{12_navigation_board/controlled/invalid_node_id.png → 12_navigation_board_base/controlled/forbidden_navigation_1.png} +0 -0
  133. package/test/graphic_references/{12_navigation_board/controlled/forbidden_navigation_0.png → 12_navigation_board_base/controlled/invalid_node_id.png} +0 -0
  134. package/test/graphic_references/12_navigation_board_base/controlled/no_callback_defined_0.png +0 -0
  135. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/controlled/no_callback_defined_1.png +0 -0
  136. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/controlled/overriding_initial_node_id.png +0 -0
  137. package/test/graphic_references/{12_navigation_board/controlled/regular_navigation_1.png → 12_navigation_board_base/controlled/regular_navigation_0.png} +0 -0
  138. 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
  139. package/test/graphic_references/{12_navigation_board/controlled/regular_navigation_3.png → 12_navigation_board_base/controlled/regular_navigation_2.png} +0 -0
  140. package/test/graphic_references/{12_navigation_board/controlled/regular_navigation_0.png → 12_navigation_board_base/controlled/regular_navigation_3.png} +0 -0
  141. 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
  142. 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
  143. 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
  144. 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
  145. package/test/graphic_references/12_navigation_board_base/uncontrolled/forbidden_navigation_at_end_1.png +0 -0
  146. package/test/graphic_references/12_navigation_board_base/uncontrolled/forbidden_navigation_at_end_2.png +0 -0
  147. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/initial_state_at_end.png +0 -0
  148. package/test/graphic_references/12_navigation_board_base/uncontrolled/initial_state_at_specific_id.png +0 -0
  149. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/initial_state_default.png +0 -0
  150. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/initial_state_default_with_game_index.png +0 -0
  151. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/initial_state_on_null-move.png +0 -0
  152. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/navigation_with_keys_0.png +0 -0
  153. package/test/graphic_references/12_navigation_board_base/uncontrolled/navigation_with_keys_1.png +0 -0
  154. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/navigation_with_keys_2.png +0 -0
  155. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/navigation_with_keys_3.png +0 -0
  156. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/navigation_with_keys_4.png +0 -0
  157. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_flipping_0.png +0 -0
  158. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_flipping_1.png +0 -0
  159. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_navigation_0.png +0 -0
  160. package/test/graphic_references/{12_navigation_board/controlled/default.png → 12_navigation_board_base/uncontrolled/regular_navigation_1.png} +0 -0
  161. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_navigation_2.png +0 -0
  162. package/test/graphic_references/12_navigation_board_base/uncontrolled/regular_navigation_3.png +0 -0
  163. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_navigation_4.png +0 -0
  164. package/test/graphic_references/{12_navigation_board → 12_navigation_board_base}/uncontrolled/regular_navigation_5.png +0 -0
  165. package/test/graphic_references/13_navigation_board_graphic/additional_buttons/error_1.png +0 -0
  166. package/test/graphic_references/13_navigation_board_graphic/additional_buttons/error_2.png +0 -0
  167. package/test/graphic_references/13_navigation_board_graphic/additional_buttons/multiple_buttons.png +0 -0
  168. package/test/graphic_references/{12_navigation_board/uncontrolled/regular_navigation_3.png → 13_navigation_board_graphic/additional_buttons/single_button.png} +0 -0
  169. package/test/graphic_references/{12_navigation_board → 13_navigation_board_graphic}/theme/custom_1.png +0 -0
  170. package/test/graphic_references/{12_navigation_board → 13_navigation_board_graphic}/theme/custom_2.png +0 -0
  171. package/test/graphic_references/{12_navigation_board → 13_navigation_board_graphic}/theme/large.png +0 -0
  172. package/test/graphic_references/13_navigation_board_graphic/theme/small.png +0 -0
  173. package/test/graphic_references/14_navigation_board_autoplay/controlled/after_1_move_acknowledging_is-playing_changes.png +0 -0
  174. package/test/graphic_references/14_navigation_board_autoplay/controlled/after_1_move_not_acknowledging_is-playing_changes.png +0 -0
  175. package/test/graphic_references/14_navigation_board_autoplay/controlled/after_2_moves_acknowledging_node_changes.png +0 -0
  176. package/test/graphic_references/14_navigation_board_autoplay/controlled/after_2_moves_not_acknowledging_node_changes.png +0 -0
  177. 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
  178. 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
  179. package/test/graphic_references/14_navigation_board_autoplay/controlled/initial_state_acknowledging_is-playing_changes.png +0 -0
  180. package/test/graphic_references/14_navigation_board_autoplay/controlled/initial_state_acknowledging_node_changes.png +0 -0
  181. 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
  182. package/test/graphic_references/14_navigation_board_autoplay/controlled/initial_state_close_to_end.png +0 -0
  183. package/test/graphic_references/14_navigation_board_autoplay/controlled/initial_state_not_acknowledging_is-playing_changes.png +0 -0
  184. package/test/graphic_references/14_navigation_board_autoplay/controlled/initial_state_not_acknowledging_node_changes.png +0 -0
  185. package/test/graphic_references/14_navigation_board_autoplay/uncontrolled/after_2_moves_from_beginning_after_stop.png +0 -0
  186. package/test/graphic_references/14_navigation_board_autoplay/uncontrolled/after_2_moves_from_beginning_before_stop.png +0 -0
  187. package/test/graphic_references/14_navigation_board_autoplay/uncontrolled/after_reaching_the_end_after_stop.png +0 -0
  188. package/test/graphic_references/14_navigation_board_autoplay/uncontrolled/after_reaching_the_end_before_stop.png +0 -0
  189. package/test/graphic_references/14_navigation_board_autoplay/uncontrolled/initial_state_close_to_end.png +0 -0
  190. package/test/graphic_references/{12_navigation_board/uncontrolled/navigation_with_keys_1.png → 14_navigation_board_autoplay/uncontrolled/initial_state_default.png} +0 -0
  191. package/test/graphic_test_app/03_error_box_graphic/base.tsx +14 -14
  192. package/test/graphic_test_app/03_error_box_graphic/localization.tsx +1 -1
  193. package/test/graphic_test_app/04_icons_graphic/chess_piece.tsx +7 -7
  194. package/test/graphic_test_app/04_icons_graphic/marker.tsx +15 -15
  195. package/test/graphic_test_app/05_chessboard_graphic/annotations.tsx +7 -7
  196. package/test/graphic_test_app/05_chessboard_graphic/base.tsx +6 -6
  197. package/test/graphic_test_app/05_chessboard_graphic/chess_variants.tsx +7 -7
  198. package/test/graphic_test_app/05_chessboard_graphic/flipped.tsx +5 -5
  199. package/test/graphic_test_app/05_chessboard_graphic/move.tsx +12 -12
  200. package/test/graphic_test_app/05_chessboard_graphic/theme.tsx +12 -12
  201. package/test/graphic_test_app/06_chessboard_animation/base_1.tsx +6 -6
  202. package/test/graphic_test_app/06_chessboard_animation/base_2.tsx +6 -6
  203. package/test/graphic_test_app/06_chessboard_animation/base_3.tsx +6 -6
  204. package/test/graphic_test_app/06_chessboard_animation/on_redraw.tsx +16 -16
  205. package/test/graphic_test_app/07_chessboard_interaction/click_squares.tsx +5 -5
  206. package/test/graphic_test_app/07_chessboard_interaction/edit_arrows.tsx +4 -4
  207. package/test/graphic_test_app/07_chessboard_interaction/error.tsx +2 -2
  208. package/test/graphic_test_app/07_chessboard_interaction/move_pieces.tsx +5 -5
  209. package/test/graphic_test_app/08_chessboard_play_moves/base.tsx +8 -8
  210. package/test/graphic_test_app/08_chessboard_play_moves/promotions.tsx +4 -4
  211. package/test/graphic_test_app/09_chessboard_small_screens/base.tsx +9 -9
  212. package/test/graphic_test_app/09_chessboard_small_screens/top_bottom_components.tsx +9 -9
  213. package/test/graphic_test_app/10_movetext_graphic/base.tsx +4 -4
  214. package/test/graphic_test_app/10_movetext_graphic/error.tsx +6 -6
  215. package/test/graphic_test_app/10_movetext_graphic/format_move.tsx +1 -1
  216. package/test/graphic_test_app/10_movetext_graphic/html.tsx +5 -5
  217. package/test/graphic_test_app/10_movetext_graphic/options.tsx +10 -10
  218. package/test/graphic_test_app/11_movetext_interaction/error.tsx +1 -1
  219. package/test/graphic_test_app/11_movetext_interaction/select_moves.tsx +11 -11
  220. package/test/graphic_test_app/{12_navigation_board → 12_navigation_board_base}/controlled.tsx +5 -5
  221. package/test/graphic_test_app/{12_navigation_board → 12_navigation_board_base}/uncontrolled.tsx +7 -7
  222. package/test/graphic_test_app/13_navigation_board_graphic/additional_buttons.tsx +49 -0
  223. package/test/graphic_test_app/{12_navigation_board → 13_navigation_board_graphic}/error.tsx +2 -2
  224. package/test/graphic_test_app/{12_navigation_board → 13_navigation_board_graphic}/theme.tsx +4 -4
  225. package/test/graphic_test_app/14_navigation_board_autoplay/controlled.tsx +73 -0
  226. package/test/graphic_test_app/14_navigation_board_autoplay/uncontrolled.tsx +34 -0
  227. package/test/graphic_test_app/common/decs.d.ts +2 -2
  228. package/test/graphic_test_app/common/test_app.css +15 -15
  229. package/test/graphic_test_app/common/test_app.tsx +48 -48
  230. package/tsconfig.json +13 -13
  231. package/test/12_navigation_board.js +0 -168
  232. package/test/graphic_references/12_navigation_board/controlled/regular_navigation_2.png +0 -0
  233. package/test/graphic_references/12_navigation_board/theme/small.png +0 -0
  234. package/test/graphic_references/12_navigation_board/uncontrolled/regular_navigation_1.png +0 -0
  235. /package/test/graphic_references/{12_navigation_board → 13_navigation_board_graphic}/error/pgn_parsing_error.png +0 -0
  236. /package/test/graphic_references/{12_navigation_board → 13_navigation_board_graphic}/error/wrong_game_type.png +0 -0
@@ -0,0 +1,98 @@
1
+ /*!
2
+ * -------------------------------------------------------------------------- *
3
+ * *
4
+ * Kokopu-React - A React-based library of chess-related components. *
5
+ * <https://www.npmjs.com/package/kokopu-react> *
6
+ * Copyright (C) 2021-2024 Yoann Le Montagner <yo35 -at- melix.net> *
7
+ * *
8
+ * Kokopu-React is free software: you can redistribute it and/or *
9
+ * modify it under the terms of the GNU Lesser General Public License *
10
+ * as published by the Free Software Foundation, either version 3 of *
11
+ * the License, or (at your option) any later version. *
12
+ * *
13
+ * Kokopu-React is distributed in the hope that it will be useful, *
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16
+ * GNU Lesser General Public License for more details. *
17
+ * *
18
+ * You should have received a copy of the GNU Lesser General *
19
+ * Public License along with this program. If not, see *
20
+ * <http://www.gnu.org/licenses/>. *
21
+ * *
22
+ * -------------------------------------------------------------------------- */
23
+
24
+
25
+ const THICKNESS = 2;
26
+ const CHEVRON_SIZE = 7;
27
+ const ARROW_SIZE = 5;
28
+ const ARROW_LENGTH = 16;
29
+
30
+
31
+ /**
32
+ * * C
33
+ * / \
34
+ * B * \
35
+ * \ \
36
+ * \ \
37
+ * A * * D
38
+ * / /
39
+ * / /
40
+ * F * /
41
+ * \ /
42
+ * * E
43
+ *
44
+ * (x,y) = middle of [AD]
45
+ */
46
+ function chevronPath(x: number, y: number, direction: 1 | -1) {
47
+ const xA = x - direction * THICKNESS * Math.sqrt(2) / 2;
48
+ const xB = x - direction * (CHEVRON_SIZE + THICKNESS / Math.sqrt(2) / 2);
49
+ const xC = x - direction * (CHEVRON_SIZE - THICKNESS / Math.sqrt(2) / 2);
50
+ const xD = x + direction * THICKNESS * Math.sqrt(2) / 2;
51
+ const yB = y - direction * (CHEVRON_SIZE - THICKNESS / Math.sqrt(2) / 2);
52
+ const yC = y - direction * (CHEVRON_SIZE + THICKNESS / Math.sqrt(2) / 2);
53
+ const yE = y + direction * (CHEVRON_SIZE + THICKNESS / Math.sqrt(2) / 2);
54
+ const yF = y + direction * (CHEVRON_SIZE - THICKNESS / Math.sqrt(2) / 2);
55
+ return `M ${xA} ${y} L ${xB} ${yB} L ${xC} ${yC} L ${xD} ${y} L ${xC} ${yE} L ${xB} ${yF} Z`;
56
+ }
57
+
58
+
59
+ /**
60
+ * D +---+ E
61
+ * | |
62
+ * | |
63
+ * | |
64
+ * B * | | * G
65
+ * / \ | | / \
66
+ * A * \| |/ * H
67
+ * \ * * /
68
+ * \ C F /
69
+ * \ O /
70
+ * \ * /
71
+ * \ /
72
+ * \ /
73
+ * *
74
+ * (x,y)
75
+ */
76
+ function arrowPath(x: number, y: number, direction: 1 | -1) {
77
+ const xA = x - direction * (ARROW_SIZE + THICKNESS / Math.sqrt(2) / 2);
78
+ const xB = x - direction * (ARROW_SIZE - THICKNESS / Math.sqrt(2) / 2);
79
+ const xC = x - direction * THICKNESS / 2;
80
+ const xF = x + direction * THICKNESS / 2;
81
+ const xG = x + direction * (ARROW_SIZE - THICKNESS / Math.sqrt(2) / 2);
82
+ const xH = x + direction * (ARROW_SIZE + THICKNESS / Math.sqrt(2) / 2);
83
+ const y0 = y - direction * THICKNESS * Math.sqrt(2) / 2;
84
+ const yA = y0 - direction * (ARROW_SIZE - THICKNESS / Math.sqrt(2) / 2);
85
+ const yB = y0 - direction * (ARROW_SIZE + THICKNESS / Math.sqrt(2) / 2);
86
+ const yC = yB + (xC - xB);
87
+ const yD = y - direction * ARROW_LENGTH;
88
+ return `M ${x} ${y} L ${xA} ${yA} L ${xB} ${yB} L ${xC} ${yC} V ${yD} H ${xF} V ${yC} L ${xG} ${yB} L ${xH} ${yA} Z`;
89
+ }
90
+
91
+
92
+ export const GO_FIRST_ICON_PATH = chevronPath(14, 16, -1) + ' ' + chevronPath(10, 16, -1);
93
+ export const GO_PREVIOUS_ICON_PATH = chevronPath(12, 16, -1);
94
+ export const GO_NEXT_ICON_PATH = chevronPath(20, 16, 1);
95
+ export const GO_LAST_ICON_PATH = chevronPath(18, 16, 1) + ' ' + chevronPath(22, 16, 1);
96
+ export const PLAY_ICON_PATH = 'M 23 16 L 12 23 V 9 Z';
97
+ export const STOP_ICON_PATH = 'M 11 11 H 21 V 21 H 11 Z';
98
+ export const FLIP_ICON_PATH = arrowPath(11, 25, 1) + ' ' + arrowPath(21, 7, -1);
@@ -26,41 +26,41 @@ import { IllegalArgument } from './exception';
26
26
 
27
27
 
28
28
  export function sanitizeString(input: string): string {
29
- return String(input);
29
+ return String(input);
30
30
  }
31
31
 
32
32
 
33
33
  export function sanitizeBoolean(input: boolean): boolean {
34
- return Boolean(input);
34
+ return Boolean(input);
35
35
  }
36
36
 
37
37
 
38
38
  export function sanitizePartialObject<T>(input: Partial<T> | undefined, exceptionBuilder: () => IllegalArgument): Partial<T> {
39
- if (input === undefined || input === null) {
40
- return {};
41
- }
42
- else if (typeof input !== 'object') {
43
- throw exceptionBuilder();
44
- }
45
- else {
46
- return input;
47
- }
39
+ if (input === undefined || input === null) {
40
+ return {};
41
+ }
42
+ else if (typeof input !== 'object') {
43
+ throw exceptionBuilder();
44
+ }
45
+ else {
46
+ return input;
47
+ }
48
48
  }
49
49
 
50
50
 
51
51
  export function sanitizeInteger(input: number, exceptionBuilder: () => IllegalArgument): number {
52
- if (typeof input !== 'number' || !Number.isFinite(input)) {
53
- throw exceptionBuilder();
54
- }
55
- return Math.round(input);
52
+ if (typeof input !== 'number' || !Number.isFinite(input)) {
53
+ throw exceptionBuilder();
54
+ }
55
+ return Math.round(input);
56
56
  }
57
57
 
58
58
 
59
59
  export function sanitizeBoundedInteger(input: number, min: number, max: number, exceptionBuilder: () => IllegalArgument) {
60
- return Math.min(Math.max(sanitizeInteger(input, exceptionBuilder), min), max);
60
+ return Math.min(Math.max(sanitizeInteger(input, exceptionBuilder), min), max);
61
61
  }
62
62
 
63
63
 
64
64
  export function sanitizeOptional<T>(input: T | undefined, sanitizationFunction: (val: T) => T): T | undefined {
65
- return input === undefined || input === null ? undefined : sanitizationFunction(input);
65
+ return input === undefined || input === null ? undefined : sanitizationFunction(input);
66
66
  }
package/src/types.ts CHANGED
@@ -50,7 +50,7 @@ export type ChessPieceIconType = ColoredPiece | 'wx' | 'bx';
50
50
  * Whether the given object is a {@link ChessPieceIconType} or not.
51
51
  */
52
52
  export function isChessPieceIconType(iconType: unknown): iconType is ChessPieceIconType {
53
- return isColoredPiece(iconType) || iconType === 'wx' || iconType === 'bx';
53
+ return isColoredPiece(iconType) || iconType === 'wx' || iconType === 'bx';
54
54
  }
55
55
 
56
56
 
@@ -61,23 +61,23 @@ export function isChessPieceIconType(iconType: unknown): iconType is ChessPieceI
61
61
  */
62
62
  export type Colorset = {
63
63
 
64
- /** Color of the black squares. */
65
- b: string;
64
+ /** Color of the black squares. */
65
+ b: string;
66
66
 
67
- /** Color of the white squares. */
68
- w: string;
67
+ /** Color of the white squares. */
68
+ w: string;
69
69
 
70
- /** Color of the blue markers. */
71
- cb: string;
70
+ /** Color of the blue markers. */
71
+ cb: string;
72
72
 
73
- /** Color of the green markers. */
74
- cg: string;
73
+ /** Color of the green markers. */
74
+ cg: string;
75
75
 
76
- /** Color of the red markers. */
77
- cr: string;
76
+ /** Color of the red markers. */
77
+ cr: string;
78
78
 
79
- /** Color of the yellow markers. */
80
- cy: string;
79
+ /** Color of the yellow markers. */
80
+ cy: string;
81
81
  };
82
82
 
83
83
 
@@ -88,47 +88,47 @@ export type Colorset = {
88
88
  */
89
89
  export type Pieceset = {
90
90
 
91
- /** Image for the black bishops. */
92
- bb: string;
91
+ /** Image for the black bishops. */
92
+ bb: string;
93
93
 
94
- /** Image for the black kings. */
95
- bk: string;
94
+ /** Image for the black kings. */
95
+ bk: string;
96
96
 
97
- /** Image for the black knights. */
98
- bn: string;
97
+ /** Image for the black knights. */
98
+ bn: string;
99
99
 
100
- /** Image for the black pawns. */
101
- bp: string;
100
+ /** Image for the black pawns. */
101
+ bp: string;
102
102
 
103
- /** Image for the black queens. */
104
- bq: string;
103
+ /** Image for the black queens. */
104
+ bq: string;
105
105
 
106
- /** Image for the black rooks. */
107
- br: string;
106
+ /** Image for the black rooks. */
107
+ br: string;
108
108
 
109
- /** Image for the black turn flags. */
110
- bx: string;
109
+ /** Image for the black turn flags. */
110
+ bx: string;
111
111
 
112
- /** Image for the white bishops. */
113
- wb: string;
112
+ /** Image for the white bishops. */
113
+ wb: string;
114
114
 
115
- /** Image for the white kings. */
116
- wk: string;
115
+ /** Image for the white kings. */
116
+ wk: string;
117
117
 
118
- /** Image for the white knights. */
119
- wn: string;
118
+ /** Image for the white knights. */
119
+ wn: string;
120
120
 
121
- /** Image for the white pawns. */
122
- wp: string;
121
+ /** Image for the white pawns. */
122
+ wp: string;
123
123
 
124
- /** Image for the white queens. */
125
- wq: string;
124
+ /** Image for the white queens. */
125
+ wq: string;
126
126
 
127
- /** Image for the white rooks. */
128
- wr: string;
127
+ /** Image for the white rooks. */
128
+ wr: string;
129
129
 
130
- /** Image for the white turn flags. */
131
- wx: string;
130
+ /** Image for the white turn flags. */
131
+ wx: string;
132
132
  };
133
133
 
134
134
 
@@ -136,12 +136,12 @@ export type Pieceset = {
136
136
  * Set of aliases for chess pieces symbols.
137
137
  */
138
138
  export type PieceSymbolMapping = {
139
- K: string;
140
- Q: string;
141
- R: string;
142
- B: string;
143
- N: string;
144
- P: string;
139
+ K: string;
140
+ Q: string;
141
+ R: string;
142
+ B: string;
143
+ N: string;
144
+ P: string;
145
145
  };
146
146
 
147
147
 
@@ -149,15 +149,15 @@ export type PieceSymbolMapping = {
149
149
  * Whether the given object is a {@link PieceSymbolMapping} or not.
150
150
  */
151
151
  export function isPieceSymbolMapping(mapping: unknown): mapping is PieceSymbolMapping {
152
- if (typeof mapping !== 'object' || mapping === null) {
153
- return false;
154
- }
155
- return typeof (mapping as PieceSymbolMapping).K === 'string' &&
156
- typeof (mapping as PieceSymbolMapping).Q === 'string' &&
157
- typeof (mapping as PieceSymbolMapping).R === 'string' &&
158
- typeof (mapping as PieceSymbolMapping).B === 'string' &&
159
- typeof (mapping as PieceSymbolMapping).N === 'string' &&
160
- typeof (mapping as PieceSymbolMapping).P === 'string';
152
+ if (typeof mapping !== 'object' || mapping === null) {
153
+ return false;
154
+ }
155
+ return typeof (mapping as PieceSymbolMapping).K === 'string' &&
156
+ typeof (mapping as PieceSymbolMapping).Q === 'string' &&
157
+ typeof (mapping as PieceSymbolMapping).R === 'string' &&
158
+ typeof (mapping as PieceSymbolMapping).B === 'string' &&
159
+ typeof (mapping as PieceSymbolMapping).N === 'string' &&
160
+ typeof (mapping as PieceSymbolMapping).P === 'string';
161
161
  }
162
162
 
163
163
 
@@ -165,16 +165,16 @@ export function isPieceSymbolMapping(mapping: unknown): mapping is PieceSymbolMa
165
165
  * Symbol that can be chosen to decorate a square in a {@link Chessboard}.
166
166
  */
167
167
  export type AnnotationSymbol = 'plus' | 'times' | 'dot' | 'circle' |
168
- 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' |
169
- 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' |
170
- '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
168
+ 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' |
169
+ 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' |
170
+ '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
171
171
 
172
172
 
173
173
  /**
174
174
  * Whether the given object is a {@link AnnotationSymbol} or not.
175
175
  */
176
176
  export function isAnnotationSymbol(symbol: unknown): symbol is AnnotationSymbol {
177
- return typeof symbol === 'string' && /^(?:[A-Za-z0-9]|plus|times|dot|circle)$/.test(symbol);
177
+ return typeof symbol === 'string' && /^(?:[A-Za-z0-9]|plus|times|dot|circle)$/.test(symbol);
178
178
  }
179
179
 
180
180
 
@@ -188,7 +188,7 @@ export type AnnotationColor = 'b' | 'g' | 'r' | 'y';
188
188
  * Whether the given object is a {@link AnnotationSymbol} or not.
189
189
  */
190
190
  export function isAnnotationColor(color: unknown): color is AnnotationColor {
191
- return color === 'b' || color === 'g' || color === 'r' || color === 'y';
191
+ return color === 'b' || color === 'g' || color === 'r' || color === 'y';
192
192
  }
193
193
 
194
194
 
@@ -217,14 +217,14 @@ export type ArrowMarkerSet = Partial<Record<SquareCouple, AnnotationColor>>;
217
217
  * @returns For example: `'Gd5,Ge4'`
218
218
  */
219
219
  export function flattenSquareMarkers(markers: SquareMarkerSet): string {
220
- if (typeof markers !== 'object' || markers === null) {
221
- throw new IllegalArgument('flattenSquareMarkers()', 'markers');
222
- }
223
- return Object.entries(markers)
224
- .filter(([ sq, color ]) => isSquare(sq) && isAnnotationColor(color))
225
- .sort((a, b) => a[0].localeCompare(b[0]))
226
- .map(([ sq, color ]) => color.toUpperCase() + sq)
227
- .join(',');
220
+ if (typeof markers !== 'object' || markers === null) {
221
+ throw new IllegalArgument('flattenSquareMarkers()', 'markers');
222
+ }
223
+ return Object.entries(markers)
224
+ .filter(([ sq, color ]) => isSquare(sq) && isAnnotationColor(color))
225
+ .sort((a, b) => a[0].localeCompare(b[0]))
226
+ .map(([ sq, color ]) => color.toUpperCase() + sq)
227
+ .join(',');
228
228
  }
229
229
 
230
230
 
@@ -235,14 +235,14 @@ export function flattenSquareMarkers(markers: SquareMarkerSet): string {
235
235
  * @returns For example: `'Rzd5,GAe4,Y(plus)h3'`
236
236
  */
237
237
  export function flattenTextMarkers(markers: TextMarkerSet): string {
238
- if (typeof markers !== 'object' || markers === null) {
239
- throw new IllegalArgument('flattenTextMarkers()', 'markers');
240
- }
241
- return Object.entries(markers)
242
- .filter(([ sq, desc ]) => isSquare(sq) && desc && isAnnotationColor(desc.color) && isAnnotationSymbol(desc.symbol))
243
- .sort((a, b) => a[0].localeCompare(b[0]))
244
- .map(([ sq, desc ]) => desc.color.toUpperCase() + (desc.symbol.length === 1 ? desc.symbol : `(${desc.symbol})`) + sq)
245
- .join(',');
238
+ if (typeof markers !== 'object' || markers === null) {
239
+ throw new IllegalArgument('flattenTextMarkers()', 'markers');
240
+ }
241
+ return Object.entries(markers)
242
+ .filter(([ sq, desc ]) => isSquare(sq) && desc && isAnnotationColor(desc.color) && isAnnotationSymbol(desc.symbol))
243
+ .sort((a, b) => a[0].localeCompare(b[0]))
244
+ .map(([ sq, desc ]) => desc.color.toUpperCase() + (desc.symbol.length === 1 ? desc.symbol : `(${desc.symbol})`) + sq)
245
+ .join(',');
246
246
  }
247
247
 
248
248
 
@@ -253,14 +253,14 @@ export function flattenTextMarkers(markers: TextMarkerSet): string {
253
253
  * @returns For example: `'Ge2e4,Rg8f6,Bg8h6'`
254
254
  */
255
255
  export function flattenArrowMarkers(markers: ArrowMarkerSet): string {
256
- if (typeof markers !== 'object' || markers === null) {
257
- throw new IllegalArgument('flattenArrowMarkers()', 'markers');
258
- }
259
- return Object.entries(markers)
260
- .filter(([ vect, color ]) => isSquareCouple(vect) && isAnnotationColor(color))
261
- .sort((a, b) => a[0].localeCompare(b[0]))
262
- .map(([ vect, color ]) => color.toUpperCase() + vect)
263
- .join(',');
256
+ if (typeof markers !== 'object' || markers === null) {
257
+ throw new IllegalArgument('flattenArrowMarkers()', 'markers');
258
+ }
259
+ return Object.entries(markers)
260
+ .filter(([ vect, color ]) => isSquareCouple(vect) && isAnnotationColor(color))
261
+ .sort((a, b) => a[0].localeCompare(b[0]))
262
+ .map(([ vect, color ]) => color.toUpperCase() + vect)
263
+ .join(',');
264
264
  }
265
265
 
266
266
 
@@ -271,14 +271,14 @@ export function flattenArrowMarkers(markers: ArrowMarkerSet): string {
271
271
  * @returns For example: `{ e4: 'g', d5: 'r' }`
272
272
  */
273
273
  export function parseSquareMarkers(markers: string): SquareMarkerSet {
274
- if (typeof markers !== 'string') {
275
- throw new IllegalArgument('parseSquareMarkers()', 'markers');
276
- }
277
- return parseMarkers<Square, AnnotationColor>(markers, token => {
278
- return /^([BGRY])([a-h][1-8])$/.test(token) ?
279
- { key: RegExp.$2 as Square, value: RegExp.$1.toLowerCase() as AnnotationColor } :
280
- undefined;
281
- });
274
+ if (typeof markers !== 'string') {
275
+ throw new IllegalArgument('parseSquareMarkers()', 'markers');
276
+ }
277
+ return parseMarkers<Square, AnnotationColor>(markers, token => {
278
+ return /^([BGRY])([a-h][1-8])$/.test(token) ?
279
+ { key: RegExp.$2 as Square, value: RegExp.$1.toLowerCase() as AnnotationColor } :
280
+ undefined;
281
+ });
282
282
  }
283
283
 
284
284
 
@@ -289,14 +289,14 @@ export function parseSquareMarkers(markers: string): SquareMarkerSet {
289
289
  * @returns For example: `{ e4: { symbol: 'A', color: 'g' }, d5: { symbol: 'z', color: 'r' }, h3: { symbol: 'plus', color: 'y' } }`
290
290
  */
291
291
  export function parseTextMarkers(markers: string): TextMarkerSet {
292
- if (typeof markers !== 'string') {
293
- throw new IllegalArgument('parseTextMarkers()', 'markers');
294
- }
295
- return parseMarkers<Square, { symbol: AnnotationSymbol, color: AnnotationColor }>(markers, token => {
296
- return /^([BGRY])(?:([A-Za-z0-9])|\((plus|times|dot|circle)\))([a-h][1-8])$/.test(token) ?
297
- { key: RegExp.$4 as Square, value: { symbol: (RegExp.$2 || RegExp.$3) as AnnotationSymbol, color: RegExp.$1.toLowerCase() as AnnotationColor } } :
298
- undefined;
299
- });
292
+ if (typeof markers !== 'string') {
293
+ throw new IllegalArgument('parseTextMarkers()', 'markers');
294
+ }
295
+ return parseMarkers<Square, { symbol: AnnotationSymbol, color: AnnotationColor }>(markers, token => {
296
+ return /^([BGRY])(?:([A-Za-z0-9])|\((plus|times|dot|circle)\))([a-h][1-8])$/.test(token) ?
297
+ { key: RegExp.$4 as Square, value: { symbol: (RegExp.$2 || RegExp.$3) as AnnotationSymbol, color: RegExp.$1.toLowerCase() as AnnotationColor } } :
298
+ undefined;
299
+ });
300
300
  }
301
301
 
302
302
 
@@ -307,23 +307,23 @@ export function parseTextMarkers(markers: string): TextMarkerSet {
307
307
  * @returns For example: `{ e2e4: 'g', g8f6: 'r', g8h6: 'b' }`
308
308
  */
309
309
  export function parseArrowMarkers(markers: string): ArrowMarkerSet {
310
- if (typeof markers !== 'string') {
311
- throw new IllegalArgument('parseArrowMarkers()', 'markers');
312
- }
313
- return parseMarkers<SquareCouple, AnnotationColor>(markers, token => {
314
- return /^([BGRY])([a-h][1-8][a-h][1-8])$/.test(token) ?
315
- { key: RegExp.$2 as SquareCouple, value: RegExp.$1.toLowerCase() as AnnotationColor } :
316
- undefined;
317
- });
310
+ if (typeof markers !== 'string') {
311
+ throw new IllegalArgument('parseArrowMarkers()', 'markers');
312
+ }
313
+ return parseMarkers<SquareCouple, AnnotationColor>(markers, token => {
314
+ return /^([BGRY])([a-h][1-8][a-h][1-8])$/.test(token) ?
315
+ { key: RegExp.$2 as SquareCouple, value: RegExp.$1.toLowerCase() as AnnotationColor } :
316
+ undefined;
317
+ });
318
318
  }
319
319
 
320
320
 
321
321
  function parseMarkers<K extends string, V>(markers: string, tokenParser: (token: string) => { key: K, value: V } | undefined): Partial<Record<K, V>> {
322
- const result: Partial<Record<K, V>> = {};
323
- markers.split(',').map(token => tokenParser(token.trim())).forEach(marker => {
324
- if (marker) {
325
- result[marker.key] = marker.value;
326
- }
327
- });
328
- return result;
322
+ const result: Partial<Record<K, V>> = {};
323
+ markers.split(',').map(token => tokenParser(token.trim())).forEach(marker => {
324
+ if (marker) {
325
+ result[marker.key] = marker.value;
326
+ }
327
+ });
328
+ return result;
329
329
  }
package/src/util.ts CHANGED
@@ -23,19 +23,19 @@
23
23
 
24
24
 
25
25
  export function generateRandomId() {
26
- const buffer = new Uint32Array(8);
27
- crypto.getRandomValues(buffer);
28
- let result = '';
29
- for (let i = 0; i < buffer.length; ++i) {
30
- result += buffer[i].toString(16);
31
- }
32
- return result;
26
+ const buffer = new Uint32Array(8);
27
+ crypto.getRandomValues(buffer);
28
+ let result = '';
29
+ for (let i = 0; i < buffer.length; ++i) {
30
+ result += buffer[i].toString(16);
31
+ }
32
+ return result;
33
33
  }
34
34
 
35
35
 
36
36
  export function fillPlaceholder(message: string, ...placeholderValues: unknown[]) {
37
- return message.replace(/{(\d+)}/g, (match, placeholder) => {
38
- const placeholderIndex = Number(placeholder);
39
- return placeholderIndex < placeholderValues.length ? String(placeholderValues[placeholderIndex]) : match;
40
- });
37
+ return message.replace(/{(\d+)}/g, (match, placeholder) => {
38
+ const placeholderIndex = Number(placeholder);
39
+ return placeholderIndex < placeholderValues.length ? String(placeholderValues[placeholderIndex]) : match;
40
+ });
41
41
  }