@scrabble-solver/scrabble-solver 2.15.10 → 2.15.12

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 (297) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +15 -15
  3. package/.next/cache/.rscinfo +1 -1
  4. package/.next/cache/.tsbuildinfo +1 -1
  5. package/.next/cache/webpack/client-production/0.pack +0 -0
  6. package/.next/cache/webpack/client-production/index.pack +0 -0
  7. package/.next/cache/webpack/client-production/index.pack.old +0 -0
  8. package/.next/cache/webpack/edge-server-production/0.pack +0 -0
  9. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  10. package/.next/cache/webpack/edge-server-production/index.pack.old +0 -0
  11. package/.next/cache/webpack/server-production/0.pack +0 -0
  12. package/.next/cache/webpack/server-production/index.pack +0 -0
  13. package/.next/cache/webpack/server-production/index.pack.old +0 -0
  14. package/.next/diagnostics/framework.json +1 -1
  15. package/.next/next-minimal-server.js.nft.json +1 -1
  16. package/.next/next-server.js.nft.json +1 -1
  17. package/.next/prerender-manifest.json +4 -4
  18. package/.next/required-server-files.json +7 -6
  19. package/.next/routes-manifest.json +1 -1
  20. package/.next/server/chunks/30.js +3 -3
  21. package/.next/server/chunks/318.js +1 -0
  22. package/.next/server/chunks/60.js +1 -1
  23. package/.next/server/chunks/812.js +1 -1
  24. package/.next/server/chunks/974.js +1 -1
  25. package/.next/server/middleware-build-manifest.js +1 -1
  26. package/.next/server/pages/404.html +1 -1
  27. package/.next/server/pages/404.js.nft.json +1 -1
  28. package/.next/server/pages/500.html +1 -1
  29. package/.next/server/pages/_app.js +1 -1
  30. package/.next/server/pages/_app.js.nft.json +1 -1
  31. package/.next/server/pages/_error.js +1 -1
  32. package/.next/server/pages/_error.js.nft.json +1 -1
  33. package/.next/server/pages/api/dictionary/[locale]/[word].js.nft.json +1 -1
  34. package/.next/server/pages/api/dictionary/[locale].js.nft.json +1 -1
  35. package/.next/server/pages/api/solve.js +1 -1
  36. package/.next/server/pages/api/solve.js.nft.json +1 -1
  37. package/.next/server/pages/api/verify.js.nft.json +1 -1
  38. package/.next/server/pages/index.html +1 -1
  39. package/.next/server/pages/index.js +1 -1
  40. package/.next/server/pages/index.js.nft.json +1 -1
  41. package/.next/server/pages/index.json +1 -1
  42. package/.next/server/pages-manifest.json +1 -1
  43. package/.next/static/{ylO_ttKeJTuoqDYywao5A → X6ny8arpUxpRCZ4OMm7Vo}/_buildManifest.js +1 -1
  44. package/.next/static/chunks/framework-57125a0cc6749ff9.js +1 -0
  45. package/.next/static/chunks/main-03618e8bd3cd04dd.js +1 -0
  46. package/.next/static/chunks/pages/{404-590e2a3839c1d9e0.js → 404-18b9f6f5faa91442.js} +1 -1
  47. package/.next/static/chunks/pages/_app-2378fe90e1762e8c.js +1 -0
  48. package/.next/static/chunks/pages/index-bfc599d9351773ae.js +1 -0
  49. package/.next/static/css/{6682db14f926d4c7.css → 04a3767982ec10e8.css} +1 -1
  50. package/.next/static/css/{d875648f38121a28.css → 1fae874a25934f54.css} +1 -1
  51. package/.next/trace +23 -23
  52. package/coverage/clover.xml +6 -0
  53. package/coverage/coverage-final.json +1 -0
  54. package/coverage/lcov-report/base.css +224 -0
  55. package/coverage/lcov-report/block-navigation.js +87 -0
  56. package/coverage/lcov-report/favicon.png +0 -0
  57. package/coverage/lcov-report/index.html +101 -0
  58. package/coverage/lcov-report/prettify.css +1 -0
  59. package/coverage/lcov-report/prettify.js +2 -0
  60. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  61. package/coverage/lcov-report/sorter.js +196 -0
  62. package/coverage/lcov.info +0 -0
  63. package/package.json +19 -18
  64. package/src/api/getServerLoggingData.ts +1 -1
  65. package/src/api/isBoardValid.ts +1 -1
  66. package/src/api/isCellValid.ts +1 -1
  67. package/src/api/isRowValid.ts +1 -1
  68. package/src/components/Alert/Alert.tsx +1 -1
  69. package/src/components/Badge/Badge.tsx +1 -1
  70. package/src/components/Board/Board.tsx +8 -8
  71. package/src/components/Board/BoardPure.tsx +12 -12
  72. package/src/components/Board/components/Actions/Actions.tsx +3 -3
  73. package/src/components/Board/components/Actions/lib.ts +3 -3
  74. package/src/components/Board/components/Cell/Cell.tsx +7 -7
  75. package/src/components/Board/components/InputPrompt/InputPrompt.tsx +2 -2
  76. package/src/components/Board/components/ToggleDirectionButton/ToggleDirectionButton.tsx +2 -2
  77. package/src/components/Board/hooks/useBackgroundImage.tsx +1 -1
  78. package/src/components/Board/hooks/useBoardStyle.ts +1 -1
  79. package/src/components/Board/hooks/useGrid.ts +13 -13
  80. package/src/components/Board/lib.ts +37 -0
  81. package/src/components/Board/selectors.ts +8 -0
  82. package/src/components/Button/Button.tsx +1 -1
  83. package/src/components/Button/Link.tsx +1 -1
  84. package/src/components/Dictionary/Dictionary.tsx +10 -3
  85. package/src/components/DictionaryInput/DictionaryInput.tsx +1 -1
  86. package/src/components/EmptyState/EmptyState.tsx +3 -3
  87. package/src/components/IconButton/IconButton.tsx +1 -1
  88. package/src/components/IconButton/Link.tsx +1 -1
  89. package/src/components/Key/Key.tsx +1 -1
  90. package/src/components/Keys/Arrows/Arrows.tsx +1 -1
  91. package/src/components/Keys/index.tsx +1 -1
  92. package/src/components/Loading/Loading.tsx +6 -8
  93. package/src/components/Logo/LogoBlueprint.tsx +1 -1
  94. package/src/components/Modal/Modal.tsx +4 -2
  95. package/src/components/Modal/components/Section/Section.tsx +1 -1
  96. package/src/components/NavButtons/NavButtons.tsx +16 -12
  97. package/src/components/NavButtons/selectors.ts +11 -0
  98. package/src/components/NotFound/NotFound.tsx +1 -1
  99. package/src/components/PlainTiles/PlainTiles.tsx +1 -1
  100. package/src/components/PlainTiles/Tile.tsx +1 -1
  101. package/src/components/PlainTiles/lib.ts +90 -0
  102. package/src/components/Progress/Progress.tsx +1 -1
  103. package/src/components/Rack/Rack.tsx +10 -26
  104. package/src/components/Rack/components/InputPrompt/InputPrompt.tsx +5 -8
  105. package/src/components/Rack/components/InputPrompt/lib.test.ts +27 -0
  106. package/src/components/Rack/components/InputPrompt/lib.ts +19 -0
  107. package/src/components/Rack/components/RackTile/RackTile.tsx +9 -9
  108. package/src/components/Rack/selectors.ts +9 -0
  109. package/src/components/Radio/Radio.tsx +1 -1
  110. package/src/components/Results/Cell.tsx +2 -2
  111. package/src/components/Results/Header.tsx +1 -1
  112. package/src/components/Results/HeaderButton.tsx +2 -2
  113. package/src/components/Results/Result.tsx +5 -6
  114. package/src/components/Results/Results.tsx +6 -6
  115. package/src/components/Results/SolveButton.tsx +3 -3
  116. package/src/components/Results/types.ts +2 -2
  117. package/src/components/ResultsInput/ResultsInput.tsx +1 -1
  118. package/src/components/SeoMessage/SeoMessage.tsx +5 -4
  119. package/src/components/Solver/Solver.tsx +4 -4
  120. package/src/components/Solver/components/InsertButton/InsertButton.tsx +1 -1
  121. package/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.tsx +5 -5
  122. package/src/components/Spinner/Spinner.tsx +1 -1
  123. package/src/components/Tile/Tile.tsx +7 -7
  124. package/src/components/Tile/TilePure.tsx +8 -8
  125. package/src/components/Tooltip/Tooltip.tsx +1 -1
  126. package/src/components/Tooltip/TooltipContent.tsx +1 -1
  127. package/src/components/Tooltip/TooltipTrigger.tsx +1 -1
  128. package/src/components/Tooltip/context.ts +1 -1
  129. package/src/components/Tooltip/useTooltip.ts +1 -1
  130. package/src/hooks/useAppLayout.ts +1 -1
  131. package/src/hooks/useColumns.ts +28 -1
  132. package/src/hooks/useEffectOnce.ts +1 -1
  133. package/src/hooks/useLocalStorage.ts +8 -0
  134. package/src/i18n/constants.ts +1 -1
  135. package/src/i18n/i18n.ts +1 -1
  136. package/src/i18n/languages/english.json +3 -0
  137. package/src/i18n/languages/french.json +3 -0
  138. package/src/i18n/languages/german.json +3 -0
  139. package/src/i18n/languages/persian.json +3 -0
  140. package/src/i18n/languages/polish.json +3 -0
  141. package/src/i18n/languages/romanian.json +3 -0
  142. package/src/i18n/languages/spanish.json +3 -0
  143. package/src/i18n/languages/turkish.json +3 -0
  144. package/src/lib/createComparator.ts +1 -1
  145. package/src/lib/createKeyComparator.ts +1 -1
  146. package/src/lib/createKeyboardNavigation.ts +1 -1
  147. package/src/lib/createStringComparator.ts +1 -1
  148. package/src/lib/extractCharacters.test.ts +42 -15
  149. package/src/lib/extractCharacters.ts +27 -25
  150. package/src/lib/findCell.ts +1 -1
  151. package/src/lib/getCoordinate.test.ts +22 -0
  152. package/src/lib/getCoordinate.ts +9 -1
  153. package/src/lib/index.ts +2 -17
  154. package/src/lib/isCtrl.ts +1 -1
  155. package/src/lib/localeTransliterate.test.ts +14 -0
  156. package/src/lib/localeTransliterate.ts +18 -0
  157. package/src/lib/numberComparator.ts +1 -1
  158. package/src/lib/reverseComparator.ts +1 -1
  159. package/src/lib/zipCharactersAndTiles.ts +2 -2
  160. package/src/modals/DictionaryModal/DictionaryModal.tsx +1 -1
  161. package/src/modals/KeyMapModal/KeyMapModal.tsx +1 -1
  162. package/src/modals/KeyMapModal/components/Mapping/Mapping.tsx +1 -1
  163. package/src/modals/MenuModal/MenuModal.tsx +1 -1
  164. package/src/modals/RemainingTilesModal/RemainingTilesModal.tsx +3 -2
  165. package/src/modals/RemainingTilesModal/components/Character/Character.tsx +7 -2
  166. package/src/{lib/getRemainingTilesGroups.ts → modals/RemainingTilesModal/lib.ts} +26 -9
  167. package/src/modals/RemainingTilesModal/selectors.ts +7 -0
  168. package/src/modals/ResultsModal/ResultsModal.tsx +4 -4
  169. package/src/modals/SettingsModal/SettingsModal.tsx +6 -1
  170. package/src/modals/SettingsModal/components/AutoGroupTilesSetting/AutoGroupTilesSetting.tsx +1 -1
  171. package/src/modals/SettingsModal/components/AutoGroupTilesSetting/lib.ts +1 -1
  172. package/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.tsx +1 -1
  173. package/src/modals/SettingsModal/components/ConfigSetting/lib.ts +1 -1
  174. package/src/modals/SettingsModal/components/InputModeSetting/InputModeSetting.tsx +1 -1
  175. package/src/modals/SettingsModal/components/InputModeSetting/lib.ts +1 -1
  176. package/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.tsx +2 -2
  177. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/RemoveCellFiltersSetting.module.scss +12 -0
  178. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/RemoveCellFiltersSetting.tsx +53 -0
  179. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/index.ts +1 -0
  180. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/lib.ts +13 -0
  181. package/src/modals/SettingsModal/components/ShowCoordinatesSetting/ShowCoordinatesSetting.tsx +2 -2
  182. package/src/modals/SettingsModal/components/index.ts +1 -0
  183. package/src/modals/WordsModal/WordsModal.tsx +4 -3
  184. package/src/pages/_app.tsx +4 -3
  185. package/src/pages/_document.tsx +1 -1
  186. package/src/pages/api/dictionary/[locale]/[word].ts +2 -2
  187. package/src/pages/api/dictionary/[locale]/index.ts +2 -2
  188. package/src/pages/api/solve.ts +11 -2
  189. package/src/pages/api/verify.ts +2 -2
  190. package/src/pages/api/visit.ts +1 -1
  191. package/src/pages/index.tsx +38 -44
  192. package/src/parameters/index.ts +1 -0
  193. package/src/sdk/findWordDefinitions.ts +1 -1
  194. package/src/sdk/getDictionary.ts +1 -1
  195. package/src/sdk/solve.ts +1 -1
  196. package/src/sdk/verify.ts +1 -1
  197. package/src/service-worker/dictionaries/getDictionary.ts +1 -1
  198. package/src/service-worker/dictionaries/getDictionaryUrl.ts +1 -1
  199. package/src/service-worker/dictionaries/revalidateDictionary.ts +1 -1
  200. package/src/service-worker/getTrie.ts +1 -1
  201. package/src/service-worker/routeSolveRequests.ts +2 -2
  202. package/src/service-worker/routeVerifyRequests.ts +1 -1
  203. package/src/state/board/index.ts +4 -0
  204. package/src/state/{slices/boardInitialState.ts → board/initialState.ts} +3 -6
  205. package/src/state/board/selectors.ts +3 -0
  206. package/src/state/{slices/boardSlice.ts → board/slice.ts} +5 -4
  207. package/src/state/board/types.ts +3 -0
  208. package/src/state/cellFilters/index.ts +4 -0
  209. package/src/state/cellFilters/initialState.ts +3 -0
  210. package/src/state/cellFilters/lib.ts +8 -0
  211. package/src/state/cellFilters/selectors.ts +13 -0
  212. package/src/state/{slices/cellFilterSlice.ts → cellFilters/slice.ts} +15 -14
  213. package/src/state/cellFilters/types.ts +3 -0
  214. package/src/state/dictionary/index.ts +4 -0
  215. package/src/state/dictionary/initialState.ts +8 -0
  216. package/src/state/dictionary/selectors.ts +16 -0
  217. package/src/state/{slices/dictionarySlice.ts → dictionary/slice.ts} +3 -3
  218. package/src/state/dictionary/types.ts +8 -0
  219. package/src/state/index.ts +12 -5
  220. package/src/{lib/getRemainingTiles.ts → state/lib.ts} +3 -4
  221. package/src/state/localStorage.ts +11 -2
  222. package/src/state/rack/index.ts +4 -0
  223. package/src/state/rack/initialState.ts +12 -0
  224. package/src/state/rack/selectors.ts +7 -0
  225. package/src/state/{slices/rackSlice.ts → rack/slice.ts} +4 -4
  226. package/src/state/rack/types.ts +3 -0
  227. package/src/state/results/index.ts +4 -0
  228. package/src/state/results/initialState.ts +13 -0
  229. package/src/state/results/lib.ts +96 -0
  230. package/src/state/results/selectors.ts +75 -0
  231. package/src/state/{slices/resultsSlice.ts → results/slice.ts} +4 -4
  232. package/src/state/results/types.ts +10 -0
  233. package/src/state/sagas.ts +22 -23
  234. package/src/state/selectors.ts +15 -235
  235. package/src/state/settings/index.ts +4 -0
  236. package/src/state/{slices/settingsInitialState.ts → settings/initialState.ts} +4 -11
  237. package/src/state/settings/lib.ts +42 -0
  238. package/src/state/settings/selectors.ts +69 -0
  239. package/src/state/{slices/settingsSlice.ts → settings/slice.ts} +9 -4
  240. package/src/state/settings/types.ts +12 -0
  241. package/src/state/solve/index.ts +4 -0
  242. package/src/state/solve/initialState.ts +12 -0
  243. package/src/state/solve/selectors.ts +14 -0
  244. package/src/state/{slices/solveSlice.ts → solve/slice.ts} +3 -3
  245. package/src/state/solve/types.ts +10 -0
  246. package/src/state/store.ts +9 -11
  247. package/src/state/types.ts +16 -18
  248. package/src/state/useTranslate.ts +2 -2
  249. package/src/state/useTypedSelector.ts +2 -2
  250. package/src/state/verify/index.ts +4 -0
  251. package/src/state/verify/initialState.ts +12 -0
  252. package/src/state/verify/selectors.ts +9 -0
  253. package/src/state/{slices/verifySlice.ts → verify/slice.ts} +3 -3
  254. package/src/state/verify/types.ts +10 -0
  255. package/src/styles/global.scss +5 -0
  256. package/src/types/api.ts +1 -1
  257. package/src/types/index.ts +9 -4
  258. package/tsconfig.tsbuildinfo +1 -0
  259. package/.eslintrc.js +0 -10
  260. package/.next/server/chunks/968.js +0 -1
  261. package/.next/static/chunks/framework-288d1abd95de88d9.js +0 -1
  262. package/.next/static/chunks/main-016492249b3393e2.js +0 -1
  263. package/.next/static/chunks/pages/_app-ac93a74c390f2ab8.js +0 -1
  264. package/.next/static/chunks/pages/index-e5f1caa581e6d3b8.js +0 -1
  265. package/src/components/Board/lib/getBonusColor.ts +0 -16
  266. package/src/components/Board/lib/getPositionInGrid.ts +0 -13
  267. package/src/components/Board/lib/index.ts +0 -2
  268. package/src/components/PlainTiles/lib/createPlainTile.ts +0 -41
  269. package/src/components/PlainTiles/lib/createPlainTiles.ts +0 -25
  270. package/src/components/PlainTiles/lib/getViewbox.ts +0 -17
  271. package/src/components/PlainTiles/lib/getX.ts +0 -5
  272. package/src/components/PlainTiles/lib/getY.ts +0 -5
  273. package/src/components/PlainTiles/lib/index.ts +0 -6
  274. package/src/components/PlainTiles/lib/randomize.ts +0 -1
  275. package/src/lib/createArray.ts +0 -1
  276. package/src/lib/createGridOf.ts +0 -9
  277. package/src/lib/detectLocale.ts +0 -27
  278. package/src/lib/extractCharactersByCase.test.ts +0 -29
  279. package/src/lib/extractCharactersByCase.ts +0 -29
  280. package/src/lib/getCellSize.ts +0 -10
  281. package/src/lib/getCoordinates.ts +0 -16
  282. package/src/lib/getRemainingTilesCount.ts +0 -5
  283. package/src/lib/getTotalRemainingTilesCount.ts +0 -5
  284. package/src/lib/groupResults.ts +0 -35
  285. package/src/lib/guessLocale.ts +0 -20
  286. package/src/lib/isUpperCase.ts +0 -5
  287. package/src/lib/resultMatchesCellFilter.ts +0 -21
  288. package/src/lib/sortGroupedResults.ts +0 -21
  289. package/src/lib/sortResults.ts +0 -41
  290. package/src/state/slices/cellFilterInitialState.ts +0 -5
  291. package/src/state/slices/dictionaryInitialState.ts +0 -15
  292. package/src/state/slices/index.ts +0 -16
  293. package/src/state/slices/rackInitialState.ts +0 -9
  294. package/src/state/slices/resultsInitialState.ts +0 -20
  295. package/src/state/slices/solveInitialState.ts +0 -21
  296. package/src/state/slices/verifyInitialState.ts +0 -19
  297. /package/.next/static/{ylO_ttKeJTuoqDYywao5A → X6ny8arpUxpRCZ4OMm7Vo}/_ssgManifest.js +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrabble-solver/scrabble-solver",
3
- "version": "2.15.10",
3
+ "version": "2.15.12",
4
4
  "description": "Scrabble Solver 2 - App",
5
5
  "repository": {
6
6
  "type": "git",
@@ -21,28 +21,29 @@
21
21
  "clean": "rimraf .next/",
22
22
  "debug": "NODE_OPTIONS='--inspect' next dev",
23
23
  "dev": "env-cmd next dev",
24
- "start": "env-cmd next start -p 3333"
24
+ "start": "env-cmd next start -p 3333",
25
+ "type-check": "tsc --noEmit"
25
26
  },
26
27
  "dependencies": {
27
- "@floating-ui/react": "^0.27.5",
28
+ "@floating-ui/react": "^0.27.9",
28
29
  "@kamilmielnik/trie": "^4.0.0",
29
- "@reduxjs/toolkit": "^2.6.1",
30
- "@scrabble-solver/configs": "^2.15.10",
31
- "@scrabble-solver/constants": "^2.15.10",
32
- "@scrabble-solver/dictionaries": "^2.15.10",
33
- "@scrabble-solver/logger": "^2.15.10",
34
- "@scrabble-solver/solver": "^2.15.10",
35
- "@scrabble-solver/types": "^2.15.10",
36
- "@scrabble-solver/word-definitions": "^2.15.10",
30
+ "@reduxjs/toolkit": "^2.8.2",
31
+ "@scrabble-solver/configs": "^2.15.12",
32
+ "@scrabble-solver/constants": "^2.15.12",
33
+ "@scrabble-solver/dictionaries": "^2.15.12",
34
+ "@scrabble-solver/logger": "^2.15.12",
35
+ "@scrabble-solver/solver": "^2.15.12",
36
+ "@scrabble-solver/types": "^2.15.12",
37
+ "@scrabble-solver/word-definitions": "^2.15.12",
37
38
  "classnames": "^2.5.1",
38
39
  "env-cmd": "^10.1.0",
39
40
  "include-media": "^2.0.0",
40
41
  "include-media-query-builder": "^1.1.0",
41
- "next": "^15.2.4",
42
+ "next": "^15.3.2",
42
43
  "normalize.css": "^8.0.1",
43
- "react": "^19.0.0",
44
+ "react": "^19.1.0",
44
45
  "react-cool-onclickoutside": "^1.7.0",
45
- "react-dom": "^19.0.0",
46
+ "react-dom": "^19.1.0",
46
47
  "react-highlight-words": "^0.21.0",
47
48
  "react-modal": "^3.16.3",
48
49
  "react-redux": "^9.2.0",
@@ -60,8 +61,8 @@
60
61
  "devDependencies": {
61
62
  "@svgr/webpack": "^8.1.0",
62
63
  "@types/classnames": "^2.3.4",
63
- "@types/react": "^19.0.12",
64
- "@types/react-dom": "^19.0.4",
64
+ "@types/react": "^19.1.5",
65
+ "@types/react-dom": "^19.1.5",
65
66
  "@types/react-highlight-words": "^0.20.0",
66
67
  "@types/react-modal": "^3.16.3",
67
68
  "@types/react-portal": "^4.0.7",
@@ -69,7 +70,7 @@
69
70
  "@types/react-window": "^1.8.8",
70
71
  "@types/redux": "^3.6.31",
71
72
  "@types/redux-saga": "^0.10.5",
72
- "sass": "^1.86.0"
73
+ "sass": "^1.89.0"
73
74
  },
74
- "gitHead": "dab5a817c1bde1a3ebf8e8907215adf12af5cb27"
75
+ "gitHead": "1eeef2b2975e63b195885dd2636c53624d300c6b"
75
76
  }
@@ -1,4 +1,4 @@
1
- import { NextApiRequest } from 'next';
1
+ import { type NextApiRequest } from 'next';
2
2
 
3
3
  interface ServerLoggingData {
4
4
  origin?: string;
@@ -1,4 +1,4 @@
1
- import { BoardJson, CellJson, Config } from '@scrabble-solver/types';
1
+ import { type BoardJson, type CellJson, type Config } from '@scrabble-solver/types';
2
2
 
3
3
  import { isRowValid } from './isRowValid';
4
4
 
@@ -1,4 +1,4 @@
1
- import { CellJson, Config } from '@scrabble-solver/types';
1
+ import { type CellJson, type Config } from '@scrabble-solver/types';
2
2
 
3
3
  import { isCharacterValid } from './isCharacterValid';
4
4
 
@@ -1,4 +1,4 @@
1
- import { CellJson, Config } from '@scrabble-solver/types';
1
+ import { type CellJson, type Config } from '@scrabble-solver/types';
2
2
 
3
3
  import { isCellValid } from './isCellValid';
4
4
 
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { FunctionComponent, HTMLProps, ReactNode, SVGAttributes } from 'react';
2
+ import { type FunctionComponent, type HTMLProps, type ReactNode, type SVGAttributes } from 'react';
3
3
 
4
4
  import { Check, CrossCircleFill, ExclamationTriangleFill, InfoCircleFill } from 'icons';
5
5
 
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { FunctionComponent, ReactNode } from 'react';
2
+ import { type FunctionComponent, type ReactNode } from 'react';
3
3
 
4
4
  import styles from './Badge.module.scss';
5
5
 
@@ -1,9 +1,9 @@
1
1
  /* eslint-disable max-lines, max-statements */
2
2
 
3
- import { FloatingPortal, ReferenceType } from '@floating-ui/react';
3
+ import { FloatingPortal, type ReferenceType } from '@floating-ui/react';
4
4
  import { EMPTY_CELL } from '@scrabble-solver/constants';
5
5
  import classNames from 'classnames';
6
- import { CSSProperties, FocusEventHandler, FunctionComponent, useCallback, useState } from 'react';
6
+ import { type CSSProperties, type FocusEventHandler, type FunctionComponent, useCallback, useState } from 'react';
7
7
  import useOnclickOutside from 'react-cool-onclickoutside';
8
8
  import { useDispatch } from 'react-redux';
9
9
 
@@ -12,11 +12,10 @@ import { LOCALE_FEATURES } from 'i18n';
12
12
  import { TRANSITION } from 'parameters';
13
13
  import {
14
14
  boardSlice,
15
- cellFilterSlice,
16
- selectFilteredCells,
15
+ cellFiltersSlice,
16
+ selectCellFilters,
17
17
  selectInputMode,
18
18
  selectLocale,
19
- selectRowsWithCandidate,
20
19
  selectShowCoordinates,
21
20
  solveSlice,
22
21
  useTypedSelector,
@@ -26,6 +25,7 @@ import styles from './Board.module.scss';
26
25
  import { BoardPure } from './BoardPure';
27
26
  import { Actions, InputPrompt } from './components';
28
27
  import { useBoardStyle, useFloatingActions, useFloatingFocus, useFloatingInputPrompt, useGrid } from './hooks';
28
+ import { selectRowsWithCandidate } from './selectors';
29
29
 
30
30
  interface Props {
31
31
  className?: string;
@@ -36,7 +36,7 @@ export const Board: FunctionComponent<Props> = ({ className }) => {
36
36
  const locale = useTypedSelector(selectLocale);
37
37
  const rows = useTypedSelector(selectRowsWithCandidate);
38
38
  const inputMode = useTypedSelector(selectInputMode);
39
- const filteredCells = useTypedSelector(selectFilteredCells);
39
+ const cellFilters = useTypedSelector(selectCellFilters);
40
40
  const showCoordinates = useTypedSelector(selectShowCoordinates);
41
41
  const { cellSize, coordinatesFontSize, coordinatesSize } = useAppLayout();
42
42
  const [
@@ -140,7 +140,7 @@ export const Board: FunctionComponent<Props> = ({ className }) => {
140
140
  inputRef.current?.focus();
141
141
  }
142
142
 
143
- dispatch(cellFilterSlice.actions.toggle(cell));
143
+ dispatch(cellFiltersSlice.actions.toggle(cell));
144
144
  }, [cell, dispatch, inputMode, inputRef]);
145
145
 
146
146
  const ref = useOnclickOutside(() => setHasFocus(false), {
@@ -151,11 +151,11 @@ export const Board: FunctionComponent<Props> = ({ className }) => {
151
151
  <>
152
152
  <BoardPure
153
153
  className={className}
154
+ cellFilters={cellFilters}
154
155
  cellSize={cellSize}
155
156
  coordinatesFontSize={coordinatesFontSize}
156
157
  coordinatesSize={coordinatesSize}
157
158
  direction={LOCALE_FEATURES[locale].direction}
158
- filteredCells={filteredCells}
159
159
  inputRefs={inputRefs}
160
160
  ref={ref}
161
161
  rows={rows}
@@ -1,13 +1,13 @@
1
- import { Cell as CellModel, ShowCoordinates } from '@scrabble-solver/types';
1
+ import { type Cell as CellModel, type ShowCoordinates } from '@scrabble-solver/types';
2
2
  import classNames from 'classnames';
3
3
  import {
4
- CSSProperties,
5
- ChangeEventHandler,
6
- ClipboardEventHandler,
7
- FocusEventHandler,
4
+ type CSSProperties,
5
+ type ChangeEventHandler,
6
+ type ClipboardEventHandler,
7
+ type FocusEventHandler,
8
8
  Fragment,
9
- KeyboardEventHandler,
10
- RefObject,
9
+ type KeyboardEventHandler,
10
+ type RefObject,
11
11
  forwardRef,
12
12
  memo,
13
13
  } from 'react';
@@ -15,18 +15,18 @@ import {
15
15
  import { Ban, FlagFill } from 'icons';
16
16
  import { getCoordinate } from 'lib';
17
17
  import { BORDER_WIDTH } from 'parameters';
18
- import { CellFilterEntry } from 'types';
18
+ import { type CellFilter } from 'types';
19
19
 
20
20
  import styles from './Board.module.scss';
21
21
  import { Cell } from './components';
22
22
 
23
23
  interface Props {
24
24
  className?: string;
25
+ cellFilters: CellFilter[];
25
26
  cellSize: number;
26
27
  coordinatesFontSize: number;
27
28
  coordinatesSize: number;
28
29
  direction: 'ltr' | 'rtl';
29
- filteredCells: CellFilterEntry[];
30
30
  inputRefs: RefObject<HTMLInputElement | null>[][];
31
31
  rows: CellModel[][];
32
32
  showCoordinates: ShowCoordinates;
@@ -46,7 +46,7 @@ const BoardPureBase = forwardRef<HTMLDivElement, Props>(
46
46
  coordinatesFontSize,
47
47
  coordinatesSize,
48
48
  direction,
49
- filteredCells,
49
+ cellFilters,
50
50
  inputRefs,
51
51
  rows,
52
52
  showCoordinates,
@@ -92,7 +92,7 @@ const BoardPureBase = forwardRef<HTMLDivElement, Props>(
92
92
  to prevent flickering on blob URL change (i.e. when flagging a field,
93
93
  but not when changing game type since user's attention is not on the board
94
94
  when that happens)*/}
95
- {filteredCells.map(({ x, y, type }) => {
95
+ {cellFilters.map(({ x, y, type }) => {
96
96
  const Icon = type === 'exclude' ? Ban : FlagFill;
97
97
 
98
98
  return (
@@ -134,7 +134,7 @@ const BoardPureBase = forwardRef<HTMLDivElement, Props>(
134
134
  cell={cell}
135
135
  cellBottom={y < rows.length - 1 ? rows[y + 1][x] : undefined}
136
136
  cellLeft={x > 0 ? rows[y][x - 1] : undefined}
137
- cellRight={x < rows.length - 1 ? rows[y][x + 1] : undefined}
137
+ cellRight={x < rows[y].length - 1 ? rows[y][x + 1] : undefined}
138
138
  cellTop={y > 0 ? rows[y - 1][x] : undefined}
139
139
  inputRef={inputRefs[y][x]}
140
140
  key={x}
@@ -1,13 +1,13 @@
1
1
  import { EMPTY_CELL } from '@scrabble-solver/constants';
2
- import { Cell } from '@scrabble-solver/types';
2
+ import { type Cell } from '@scrabble-solver/types';
3
3
  import classNames from 'classnames';
4
- import { forwardRef, HTMLProps, MouseEventHandler } from 'react';
4
+ import { forwardRef, type HTMLProps, type MouseEventHandler } from 'react';
5
5
 
6
6
  import { useIsTouchDevice } from 'hooks';
7
7
  import { Keyboard, Square, SquareFill } from 'icons';
8
8
  import { findCell, isMac } from 'lib';
9
9
  import { selectCellFilter, selectInputMode, selectResultCandidateCells, useTranslate, useTypedSelector } from 'state';
10
- import { Direction } from 'types';
10
+ import { type Direction } from 'types';
11
11
 
12
12
  import { Button } from '../../../Button';
13
13
  import { ToggleDirectionButton } from '../ToggleDirectionButton';
@@ -1,10 +1,10 @@
1
- import { FunctionComponent, SVGAttributes } from 'react';
1
+ import { type FunctionComponent, type SVGAttributes } from 'react';
2
2
 
3
3
  import { Ban, Eraser, FlagFill } from 'icons';
4
- import { CellFilterEntry, TranslationKey } from 'types';
4
+ import { type CellFilter, type TranslationKey } from 'types';
5
5
 
6
6
  export const getNextCellFilter = (
7
- filter: CellFilterEntry | undefined,
7
+ filter: CellFilter | undefined,
8
8
  ): {
9
9
  Icon: FunctionComponent<SVGAttributes<SVGElement>>;
10
10
  labelTranslationKey: TranslationKey;
@@ -1,13 +1,13 @@
1
1
  import { EMPTY_CELL } from '@scrabble-solver/constants';
2
- import { Cell as CellModel } from '@scrabble-solver/types';
2
+ import { type Cell as CellModel } from '@scrabble-solver/types';
3
3
  import classNames from 'classnames';
4
4
  import {
5
- ChangeEventHandler,
6
- FocusEventHandler,
7
- FunctionComponent,
8
- MouseEventHandler,
9
- RefObject,
10
- TouchEventHandler,
5
+ type ChangeEventHandler,
6
+ type FocusEventHandler,
7
+ type FunctionComponent,
8
+ type MouseEventHandler,
9
+ type RefObject,
10
+ type TouchEventHandler,
11
11
  useCallback,
12
12
  } from 'react';
13
13
 
@@ -1,9 +1,9 @@
1
1
  import classNames from 'classnames';
2
- import { FormEventHandler, forwardRef, HTMLProps, MouseEventHandler, useEffect, useState } from 'react';
2
+ import { type FormEventHandler, forwardRef, type HTMLProps, type MouseEventHandler, useEffect, useState } from 'react';
3
3
 
4
4
  import { Check } from 'icons';
5
5
  import { useTranslate } from 'state';
6
- import { Direction } from 'types';
6
+ import { type Direction } from 'types';
7
7
 
8
8
  import { Button } from '../../../Button';
9
9
  import { ToggleDirectionButton } from '../ToggleDirectionButton';
@@ -1,10 +1,10 @@
1
1
  import classNames from 'classnames';
2
- import { ButtonHTMLAttributes, FunctionComponent } from 'react';
2
+ import { type ButtonHTMLAttributes, type FunctionComponent } from 'react';
3
3
 
4
4
  import { useIsTouchDevice } from 'hooks';
5
5
  import { ArrowDown } from 'icons';
6
6
  import { useTranslate } from 'state';
7
- import { Direction } from 'types';
7
+ import { type Direction } from 'types';
8
8
 
9
9
  import { Button } from '../../../Button';
10
10
 
@@ -11,7 +11,7 @@ import { Star } from 'icons';
11
11
  import { getTileSizes } from 'lib';
12
12
  import { BORDER_COLOR_LIGHT, BORDER_RADIUS, BORDER_WIDTH, COLOR_BACKGROUND, COLOR_BONUS_START } from 'parameters';
13
13
  import { selectConfig, selectLocale, selectShowCoordinates, store, useTypedSelector } from 'state';
14
- import { Point } from 'types';
14
+ import { type Point } from 'types';
15
15
 
16
16
  import { getBonusColor } from '../lib';
17
17
 
@@ -1,4 +1,4 @@
1
- import { CSSProperties, useMemo } from 'react';
1
+ import { type CSSProperties, useMemo } from 'react';
2
2
 
3
3
  import { useAppLayout } from 'hooks';
4
4
  import { getTileSizes } from 'lib';
@@ -1,13 +1,13 @@
1
1
  /* eslint-disable max-lines, max-statements */
2
- import { PayloadAction } from '@reduxjs/toolkit';
2
+ import { type PayloadAction } from '@reduxjs/toolkit';
3
3
  import { BLANK, EMPTY_CELL } from '@scrabble-solver/constants';
4
- import { Board, Cell } from '@scrabble-solver/types';
4
+ import { Board, type Cell } from '@scrabble-solver/types';
5
5
  import {
6
- ChangeEvent,
7
- ChangeEventHandler,
8
- ClipboardEventHandler,
9
- KeyboardEventHandler,
10
- RefObject,
6
+ type ChangeEvent,
7
+ type ChangeEventHandler,
8
+ type ClipboardEventHandler,
9
+ type KeyboardEventHandler,
10
+ type RefObject,
11
11
  createRef,
12
12
  useCallback,
13
13
  useMemo,
@@ -17,11 +17,11 @@ import { useDispatch } from 'react-redux';
17
17
 
18
18
  import { useLatest } from 'hooks';
19
19
  import { LOCALE_FEATURES } from 'i18n';
20
- import { createGridOf, createKeyboardNavigation, extractCharacters, extractInputValue, isCtrl } from 'lib';
21
- import { boardSlice, cellFilterSlice, selectConfig, selectLocale, useTypedSelector } from 'state';
22
- import { Direction, Point } from 'types';
20
+ import { createKeyboardNavigation, extractCharacters, extractInputValue, isCtrl } from 'lib';
21
+ import { boardSlice, cellFiltersSlice, selectConfig, selectLocale, useTypedSelector } from 'state';
22
+ import { type Direction, type Point } from 'types';
23
23
 
24
- import { getPositionInGrid } from '../lib';
24
+ import { createGrid, getPositionInGrid } from '../lib';
25
25
 
26
26
  const toggleDirection = (direction: Direction) => (direction === 'vertical' ? 'horizontal' : 'vertical');
27
27
 
@@ -47,7 +47,7 @@ export const useGrid = (rows: Cell[][]): [State, Actions] => {
47
47
  const config = useTypedSelector(selectConfig);
48
48
  const locale = useTypedSelector(selectLocale);
49
49
  const inputRefs = useMemo(
50
- () => createGridOf<RefObject<HTMLInputElement | null>>(width, height, () => createRef()),
50
+ () => createGrid<RefObject<HTMLInputElement | null>>(width, height, () => createRef()),
51
51
  [width, height],
52
52
  );
53
53
  const [activeIndex, setActiveIndex] = useState<Point>({ x: 0, y: 0 });
@@ -314,7 +314,7 @@ export const useGrid = (rows: Cell[][]): [State, Actions] => {
314
314
  event.preventDefault();
315
315
 
316
316
  if (!cell.hasTile()) {
317
- dispatch(cellFilterSlice.actions.toggle(position));
317
+ dispatch(cellFiltersSlice.actions.toggle(position));
318
318
  }
319
319
 
320
320
  return;
@@ -0,0 +1,37 @@
1
+ import { BONUS_WORD } from '@scrabble-solver/constants';
2
+ import { type Bonus } from '@scrabble-solver/types';
3
+
4
+ import { COLOR_BONUS_CHARACTER, COLOR_BONUS_CHARACTER_MULTIPLIER, COLOR_BONUS_WORD } from 'parameters';
5
+ import { type Point } from 'types';
6
+
7
+ export const createGrid = <T>(width: number, height: number, getInitialValue: (x: number, y: number) => T): T[][] => {
8
+ return Array.from({ length: height }).map((_row, y) => {
9
+ return Array.from({ length: width }).map((_cell, x) => {
10
+ return getInitialValue(x, y);
11
+ });
12
+ });
13
+ };
14
+
15
+ export const getBonusColor = (bonus: Bonus): string => {
16
+ if (bonus.type === BONUS_WORD) {
17
+ return COLOR_BONUS_WORD[bonus.multiplier];
18
+ }
19
+
20
+ if (bonus.score) {
21
+ return COLOR_BONUS_CHARACTER[bonus.score];
22
+ }
23
+
24
+ return COLOR_BONUS_CHARACTER_MULTIPLIER[bonus.multiplier];
25
+ };
26
+
27
+ export const getPositionInGrid = <T>(grid: T[][], constraint: (value: T) => boolean): Point | undefined => {
28
+ for (let y = 0; y < grid.length; ++y) {
29
+ for (let x = 0; x < grid[0].length; ++x) {
30
+ if (constraint(grid[y][x])) {
31
+ return { x, y };
32
+ }
33
+ }
34
+ }
35
+
36
+ return undefined;
37
+ };
@@ -0,0 +1,8 @@
1
+ import { createSelector } from '@reduxjs/toolkit';
2
+
3
+ import { findCell } from 'lib';
4
+ import { selectBoard, selectResultCandidateCells } from 'state';
5
+
6
+ export const selectRowsWithCandidate = createSelector([selectBoard, selectResultCandidateCells], (board, cells) => {
7
+ return board.rows.map((row, y) => row.map((cell, x) => findCell(cells, x, y) || cell));
8
+ });
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { ButtonHTMLAttributes, FunctionComponent, ReactNode, SVGAttributes } from 'react';
2
+ import { type ButtonHTMLAttributes, type FunctionComponent, type ReactNode, type SVGAttributes } from 'react';
3
3
 
4
4
  import { Tooltip } from '../Tooltip';
5
5
 
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { AnchorHTMLAttributes, FunctionComponent, ReactNode, SVGAttributes } from 'react';
2
+ import { type AnchorHTMLAttributes, type FunctionComponent, type ReactNode, type SVGAttributes } from 'react';
3
3
 
4
4
  import { Tooltip } from '../Tooltip';
5
5
 
@@ -1,8 +1,14 @@
1
1
  import classNames from 'classnames';
2
- import { FunctionComponent } from 'react';
2
+ import { type FunctionComponent } from 'react';
3
3
 
4
4
  import { useAppLayout } from 'hooks';
5
- import { selectDictionary, selectDictionaryError, useTranslate, useTypedSelector } from 'state';
5
+ import {
6
+ selectDictionaryError,
7
+ selectDictionaryIsLoading,
8
+ selectDictionaryResults,
9
+ useTranslate,
10
+ useTypedSelector,
11
+ } from 'state';
6
12
 
7
13
  import { EmptyState } from '../EmptyState';
8
14
  import { Loading } from '../Loading';
@@ -16,7 +22,8 @@ interface Props {
16
22
  export const Dictionary: FunctionComponent<Props> = ({ className }) => {
17
23
  const translate = useTranslate();
18
24
  const { dictionaryResultsHeight } = useAppLayout();
19
- const { results, isLoading } = useTypedSelector(selectDictionary);
25
+ const results = useTypedSelector(selectDictionaryResults);
26
+ const isLoading = useTypedSelector(selectDictionaryIsLoading);
20
27
  const error = useTypedSelector(selectDictionaryError);
21
28
  const isLastAllowed = results.at(-1)?.isAllowed;
22
29
 
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { ChangeEvent, FormEvent, FunctionComponent } from 'react';
2
+ import { type ChangeEvent, type FormEvent, type FunctionComponent } from 'react';
3
3
  import { useDispatch } from 'react-redux';
4
4
 
5
5
  import { LOCALE_FEATURES } from 'i18n';
@@ -1,10 +1,10 @@
1
1
  import classNames from 'classnames';
2
- import { FunctionComponent, ReactNode, useMemo } from 'react';
2
+ import { type FunctionComponent, type ReactNode, useMemo } from 'react';
3
3
 
4
4
  import { LOCALE_FEATURES } from 'i18n';
5
5
  import { COLOR_BLUE, COLOR_GREEN, COLOR_RED, COLOR_YELLOW } from 'parameters';
6
6
  import { selectLocale, useTranslate, useTypedSelector } from 'state';
7
- import { Translations } from 'types';
7
+ import { type Translations } from 'types';
8
8
 
9
9
  import { PlainTiles } from '../PlainTiles';
10
10
 
@@ -34,7 +34,7 @@ export const EmptyState: FunctionComponent<Props> = ({ children, className, vari
34
34
  const translate = useTranslate();
35
35
  const locale = useTypedSelector(selectLocale);
36
36
  const { direction } = LOCALE_FEATURES[locale];
37
- const title = useMemo(() => translate(TITLE_KEY_PER_TYPE[variant]), [translate, variant]);
37
+ const title = translate(TITLE_KEY_PER_TYPE[variant]);
38
38
  const message = direction === 'ltr' ? title : title.split('').reverse().join('');
39
39
  const content = useMemo(() => [message.toUpperCase().split(' ')], [message]);
40
40
 
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { ButtonHTMLAttributes, FunctionComponent, MouseEventHandler, SVGAttributes } from 'react';
2
+ import { type ButtonHTMLAttributes, type FunctionComponent, type MouseEventHandler, type SVGAttributes } from 'react';
3
3
 
4
4
  import { Tooltip } from '../Tooltip';
5
5
 
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { AnchorHTMLAttributes, FunctionComponent, SVGAttributes } from 'react';
2
+ import { type AnchorHTMLAttributes, type FunctionComponent, type SVGAttributes } from 'react';
3
3
 
4
4
  import { Tooltip } from '../Tooltip';
5
5
 
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { FunctionComponent, ReactNode } from 'react';
2
+ import { type FunctionComponent, type ReactNode } from 'react';
3
3
 
4
4
  import styles from './Key.module.scss';
5
5
 
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { FunctionComponent } from 'react';
2
+ import { type FunctionComponent } from 'react';
3
3
 
4
4
  import { ArrowDown, ArrowLeft, ArrowRight, ArrowUp } from 'icons';
5
5
 
@@ -1,4 +1,4 @@
1
- import { FunctionComponent } from 'react';
1
+ import { type FunctionComponent } from 'react';
2
2
 
3
3
  import { isMac } from 'lib';
4
4
  import { useTranslate } from 'state';
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { FunctionComponent, useMemo } from 'react';
2
+ import { type FunctionComponent, useMemo } from 'react';
3
3
 
4
4
  import { LOCALE_FEATURES } from 'i18n';
5
5
  import { selectLocale, useTranslate, useTypedSelector } from 'state';
@@ -14,19 +14,17 @@ interface Props {
14
14
  wave?: boolean;
15
15
  }
16
16
 
17
- const prepareContent = (message: string): string[][] => {
18
- const uppercased = message.toLocaleUpperCase();
19
- const parts = uppercased.split(' ');
20
- return [parts];
21
- };
22
-
23
17
  export const Loading: FunctionComponent<Props> = ({ className, wave = true }) => {
24
18
  const translate = useTranslate();
25
19
  const locale = useTypedSelector(selectLocale);
26
20
  const { direction } = LOCALE_FEATURES[locale];
27
21
  const translation = translate('common.loading');
28
22
  const message = direction === 'ltr' ? translation : translation.split('').reverse().join('');
29
- const content = useMemo(() => prepareContent(message), [message]);
23
+ const content = useMemo(() => {
24
+ const uppercased = message.toLocaleUpperCase();
25
+ const parts = uppercased.split(' ');
26
+ return [parts];
27
+ }, [message]);
30
28
 
31
29
  return (
32
30
  <div aria-label={translation} className={classNames(styles.loading, className)} data-testid="loading" role="status">
@@ -5,7 +5,7 @@
5
5
  * - transformed into paths (manually with Inkscape)
6
6
  * - arranged (centered vertically against respective rows)
7
7
  */
8
- import { CSSProperties, FunctionComponent } from 'react';
8
+ import { type CSSProperties, type FunctionComponent } from 'react';
9
9
 
10
10
  import { PlainTiles } from '../PlainTiles';
11
11
 
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { FunctionComponent, ReactNode, useCallback, useEffect, useState } from 'react';
2
+ import { type FunctionComponent, type ReactNode, useCallback, useEffect, useState } from 'react';
3
3
  import ReactModal from 'react-modal';
4
4
 
5
5
  import { CrossSquareFill } from 'icons';
@@ -28,7 +28,9 @@ const ModalBase: FunctionComponent<Props> = ({ children, className, footer, isOp
28
28
  (event: KeyboardEvent) => {
29
29
  if (event.key === 'Escape') {
30
30
  setShouldReturnFocusAfterClose(false);
31
- onClose();
31
+ setTimeout(() => {
32
+ onClose();
33
+ }, 0);
32
34
  }
33
35
  },
34
36
  [onClose],
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { FunctionComponent, ReactNode } from 'react';
2
+ import { type FunctionComponent, type ReactNode } from 'react';
3
3
 
4
4
  import styles from './Section.module.scss';
5
5