@scrabble-solver/scrabble-solver 2.15.11 → 2.15.13

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 (309) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +16 -16
  3. package/.next/cache/.previewinfo +1 -0
  4. package/.next/cache/.rscinfo +1 -1
  5. package/.next/cache/.tsbuildinfo +1 -1
  6. package/.next/cache/webpack/client-production/0.pack +0 -0
  7. package/.next/cache/webpack/client-production/index.pack +0 -0
  8. package/.next/cache/webpack/client-production/index.pack.old +0 -0
  9. package/.next/cache/webpack/edge-server-production/0.pack +0 -0
  10. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  11. package/.next/cache/webpack/edge-server-production/index.pack.old +0 -0
  12. package/.next/cache/webpack/server-production/0.pack +0 -0
  13. package/.next/cache/webpack/server-production/index.pack +0 -0
  14. package/.next/cache/webpack/server-production/index.pack.old +0 -0
  15. package/.next/diagnostics/framework.json +1 -1
  16. package/.next/next-minimal-server.js.nft.json +1 -1
  17. package/.next/next-server.js.nft.json +1 -1
  18. package/.next/prerender-manifest.json +4 -4
  19. package/.next/required-server-files.json +23 -12
  20. package/.next/routes-manifest.json +7 -3
  21. package/.next/server/chunks/106.js +1 -0
  22. package/.next/server/chunks/30.js +4 -4
  23. package/.next/server/chunks/318.js +1 -0
  24. package/.next/server/chunks/50.js +19 -0
  25. package/.next/server/chunks/812.js +1 -1
  26. package/.next/server/chunks/929.js +1 -0
  27. package/.next/server/chunks/974.js +1 -1
  28. package/.next/server/middleware-build-manifest.js +1 -1
  29. package/.next/server/pages/404.html +1 -1
  30. package/.next/server/pages/404.js.nft.json +1 -1
  31. package/.next/server/pages/500.html +1 -1
  32. package/.next/server/pages/_app.js +1 -1
  33. package/.next/server/pages/_app.js.nft.json +1 -1
  34. package/.next/server/pages/_document.js +1 -1
  35. package/.next/server/pages/_document.js.nft.json +1 -1
  36. package/.next/server/pages/_error.js +1 -1
  37. package/.next/server/pages/_error.js.nft.json +1 -1
  38. package/.next/server/pages/api/dictionary/[locale]/[word].js +2 -2
  39. package/.next/server/pages/api/dictionary/[locale]/[word].js.nft.json +1 -1
  40. package/.next/server/pages/api/dictionary/[locale].js +1 -1
  41. package/.next/server/pages/api/dictionary/[locale].js.nft.json +1 -1
  42. package/.next/server/pages/api/solve.js +1 -1
  43. package/.next/server/pages/api/solve.js.nft.json +1 -1
  44. package/.next/server/pages/api/verify.js +1 -1
  45. package/.next/server/pages/api/verify.js.nft.json +1 -1
  46. package/.next/server/pages/api/visit.js +1 -1
  47. package/.next/server/pages/api/visit.js.nft.json +1 -1
  48. package/.next/server/pages/index.html +1 -1
  49. package/.next/server/pages/index.js +1 -1
  50. package/.next/server/pages/index.js.nft.json +1 -1
  51. package/.next/server/pages/index.json +1 -1
  52. package/.next/server/pages-manifest.json +1 -1
  53. package/.next/server/webpack-api-runtime.js +1 -1
  54. package/.next/server/webpack-runtime.js +1 -1
  55. package/.next/static/{47JHul8F9NSWCNSEuahuL → MhrqAqLI9_L8obb7tgjvi}/_buildManifest.js +1 -1
  56. package/.next/static/chunks/framework-aad31c68dd0bb0ea.js +1 -0
  57. package/.next/static/chunks/main-eab5847b41f0af4a.js +1 -0
  58. package/.next/static/chunks/pages/{404-590e2a3839c1d9e0.js → 404-04457ede98c6b53e.js} +1 -1
  59. package/.next/static/chunks/pages/_app-bf81f201c021fdc1.js +1 -0
  60. package/.next/static/chunks/pages/{_error-7ea2d37f66343175.js → _error-a9800cedd835bcad.js} +1 -1
  61. package/.next/static/chunks/pages/index-79a390f3c2a2499f.js +1 -0
  62. package/.next/static/css/{6682db14f926d4c7.css → 04a3767982ec10e8.css} +1 -1
  63. package/.next/static/css/{d875648f38121a28.css → 1fae874a25934f54.css} +1 -1
  64. package/.next/trace +24 -23
  65. package/coverage/clover.xml +6 -0
  66. package/coverage/coverage-final.json +1 -0
  67. package/coverage/lcov-report/base.css +224 -0
  68. package/coverage/lcov-report/block-navigation.js +87 -0
  69. package/coverage/lcov-report/favicon.png +0 -0
  70. package/coverage/lcov-report/index.html +101 -0
  71. package/coverage/lcov-report/prettify.css +1 -0
  72. package/coverage/lcov-report/prettify.js +2 -0
  73. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  74. package/coverage/lcov-report/sorter.js +196 -0
  75. package/coverage/lcov.info +0 -0
  76. package/package.json +18 -18
  77. package/src/api/getServerLoggingData.ts +1 -1
  78. package/src/api/isBoardValid.ts +1 -1
  79. package/src/api/isCellValid.ts +1 -1
  80. package/src/api/isRowValid.ts +1 -1
  81. package/src/components/Alert/Alert.tsx +1 -1
  82. package/src/components/Badge/Badge.tsx +1 -1
  83. package/src/components/Board/Board.tsx +8 -8
  84. package/src/components/Board/BoardPure.tsx +11 -11
  85. package/src/components/Board/components/Actions/Actions.tsx +3 -3
  86. package/src/components/Board/components/Actions/lib.ts +3 -3
  87. package/src/components/Board/components/Cell/Cell.tsx +7 -7
  88. package/src/components/Board/components/InputPrompt/InputPrompt.tsx +2 -2
  89. package/src/components/Board/components/ToggleDirectionButton/ToggleDirectionButton.tsx +2 -2
  90. package/src/components/Board/hooks/useBackgroundImage.tsx +1 -1
  91. package/src/components/Board/hooks/useBoardStyle.ts +1 -1
  92. package/src/components/Board/hooks/useGrid.ts +13 -13
  93. package/src/components/Board/lib.ts +37 -0
  94. package/src/components/Board/selectors.ts +8 -0
  95. package/src/components/Button/Button.tsx +1 -1
  96. package/src/components/Button/Link.tsx +1 -1
  97. package/src/components/Dictionary/Dictionary.tsx +10 -3
  98. package/src/components/DictionaryInput/DictionaryInput.tsx +1 -1
  99. package/src/components/EmptyState/EmptyState.tsx +3 -3
  100. package/src/components/IconButton/IconButton.tsx +1 -1
  101. package/src/components/IconButton/Link.tsx +1 -1
  102. package/src/components/Key/Key.tsx +1 -1
  103. package/src/components/Keys/Arrows/Arrows.tsx +1 -1
  104. package/src/components/Keys/index.tsx +1 -1
  105. package/src/components/Loading/Loading.tsx +6 -8
  106. package/src/components/Logo/LogoBlueprint.tsx +1 -1
  107. package/src/components/Modal/Modal.tsx +4 -2
  108. package/src/components/Modal/components/Section/Section.tsx +1 -1
  109. package/src/components/NavButtons/NavButtons.tsx +4 -3
  110. package/src/components/NavButtons/selectors.ts +11 -0
  111. package/src/components/NotFound/NotFound.tsx +1 -1
  112. package/src/components/PlainTiles/PlainTiles.tsx +1 -1
  113. package/src/components/PlainTiles/Tile.tsx +1 -1
  114. package/src/components/PlainTiles/lib.ts +90 -0
  115. package/src/components/Progress/Progress.tsx +1 -1
  116. package/src/components/Rack/Rack.tsx +10 -26
  117. package/src/components/Rack/components/InputPrompt/InputPrompt.tsx +5 -8
  118. package/src/components/Rack/components/InputPrompt/lib.test.ts +27 -0
  119. package/src/components/Rack/components/InputPrompt/lib.ts +19 -0
  120. package/src/components/Rack/components/RackTile/RackTile.tsx +9 -9
  121. package/src/components/Rack/selectors.ts +9 -0
  122. package/src/components/Radio/Radio.tsx +1 -1
  123. package/src/components/Results/Cell.tsx +2 -2
  124. package/src/components/Results/Header.tsx +1 -1
  125. package/src/components/Results/HeaderButton.tsx +2 -2
  126. package/src/components/Results/Result.tsx +5 -6
  127. package/src/components/Results/Results.tsx +6 -6
  128. package/src/components/Results/SolveButton.tsx +3 -3
  129. package/src/components/Results/types.ts +2 -2
  130. package/src/components/ResultsInput/ResultsInput.tsx +1 -1
  131. package/src/components/SeoMessage/SeoMessage.tsx +1 -1
  132. package/src/components/Solver/Solver.tsx +4 -4
  133. package/src/components/Solver/components/InsertButton/InsertButton.tsx +1 -1
  134. package/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.tsx +5 -5
  135. package/src/components/Spinner/Spinner.tsx +1 -1
  136. package/src/components/Tile/Tile.tsx +7 -7
  137. package/src/components/Tile/TilePure.tsx +8 -8
  138. package/src/components/Tooltip/Tooltip.tsx +1 -1
  139. package/src/components/Tooltip/TooltipContent.tsx +1 -1
  140. package/src/components/Tooltip/TooltipTrigger.tsx +1 -1
  141. package/src/components/Tooltip/context.ts +1 -1
  142. package/src/components/Tooltip/useTooltip.ts +1 -1
  143. package/src/hooks/useAppLayout.ts +1 -1
  144. package/src/hooks/useColumns.ts +28 -1
  145. package/src/hooks/useEffectOnce.ts +1 -1
  146. package/src/hooks/useLocalStorage.ts +8 -0
  147. package/src/i18n/constants.ts +1 -1
  148. package/src/i18n/i18n.ts +1 -1
  149. package/src/i18n/languages/english.json +3 -0
  150. package/src/i18n/languages/french.json +3 -0
  151. package/src/i18n/languages/german.json +3 -0
  152. package/src/i18n/languages/persian.json +3 -0
  153. package/src/i18n/languages/polish.json +3 -0
  154. package/src/i18n/languages/romanian.json +3 -0
  155. package/src/i18n/languages/spanish.json +3 -0
  156. package/src/i18n/languages/turkish.json +3 -0
  157. package/src/lib/createComparator.ts +1 -1
  158. package/src/lib/createKeyComparator.ts +1 -1
  159. package/src/lib/createKeyboardNavigation.ts +1 -1
  160. package/src/lib/createStringComparator.ts +1 -1
  161. package/src/lib/extractCharacters.test.ts +42 -15
  162. package/src/lib/extractCharacters.ts +27 -25
  163. package/src/lib/findCell.ts +1 -1
  164. package/src/lib/index.ts +2 -17
  165. package/src/lib/isCtrl.ts +1 -1
  166. package/src/lib/localeTransliterate.test.ts +14 -0
  167. package/src/lib/localeTransliterate.ts +18 -0
  168. package/src/lib/numberComparator.ts +1 -1
  169. package/src/lib/reverseComparator.ts +1 -1
  170. package/src/lib/zipCharactersAndTiles.ts +2 -2
  171. package/src/modals/DictionaryModal/DictionaryModal.tsx +1 -1
  172. package/src/modals/KeyMapModal/KeyMapModal.tsx +1 -1
  173. package/src/modals/KeyMapModal/components/Mapping/Mapping.tsx +1 -1
  174. package/src/modals/MenuModal/MenuModal.tsx +1 -1
  175. package/src/modals/RemainingTilesModal/RemainingTilesModal.tsx +3 -2
  176. package/src/modals/RemainingTilesModal/components/Character/Character.tsx +2 -2
  177. package/src/{lib/getRemainingTilesGroups.ts → modals/RemainingTilesModal/lib.ts} +26 -9
  178. package/src/modals/RemainingTilesModal/selectors.ts +7 -0
  179. package/src/modals/ResultsModal/ResultsModal.tsx +4 -4
  180. package/src/modals/SettingsModal/SettingsModal.tsx +6 -1
  181. package/src/modals/SettingsModal/components/AutoGroupTilesSetting/AutoGroupTilesSetting.tsx +1 -1
  182. package/src/modals/SettingsModal/components/AutoGroupTilesSetting/lib.ts +1 -1
  183. package/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.tsx +1 -1
  184. package/src/modals/SettingsModal/components/ConfigSetting/lib.ts +1 -1
  185. package/src/modals/SettingsModal/components/InputModeSetting/InputModeSetting.tsx +1 -1
  186. package/src/modals/SettingsModal/components/InputModeSetting/lib.ts +1 -1
  187. package/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.tsx +2 -2
  188. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/RemoveCellFiltersSetting.module.scss +12 -0
  189. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/RemoveCellFiltersSetting.tsx +53 -0
  190. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/index.ts +1 -0
  191. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/lib.ts +13 -0
  192. package/src/modals/SettingsModal/components/ShowCoordinatesSetting/ShowCoordinatesSetting.tsx +2 -2
  193. package/src/modals/SettingsModal/components/index.ts +1 -0
  194. package/src/modals/WordsModal/WordsModal.tsx +4 -3
  195. package/src/pages/_app.tsx +2 -2
  196. package/src/pages/_document.tsx +1 -1
  197. package/src/pages/api/dictionary/[locale]/[word].ts +2 -2
  198. package/src/pages/api/dictionary/[locale]/index.ts +2 -2
  199. package/src/pages/api/solve.ts +11 -2
  200. package/src/pages/api/verify.ts +2 -2
  201. package/src/pages/api/visit.ts +1 -1
  202. package/src/pages/index.tsx +34 -43
  203. package/src/parameters/index.ts +1 -0
  204. package/src/sdk/findWordDefinitions.ts +1 -1
  205. package/src/sdk/getDictionary.ts +1 -1
  206. package/src/sdk/solve.ts +1 -1
  207. package/src/sdk/verify.ts +1 -1
  208. package/src/service-worker/dictionaries/getDictionary.ts +1 -1
  209. package/src/service-worker/dictionaries/getDictionaryUrl.ts +1 -1
  210. package/src/service-worker/dictionaries/revalidateDictionary.ts +1 -1
  211. package/src/service-worker/getTrie.ts +1 -1
  212. package/src/service-worker/routeSolveRequests.ts +2 -2
  213. package/src/service-worker/routeVerifyRequests.ts +1 -1
  214. package/src/state/board/index.ts +4 -0
  215. package/src/state/{slices/boardInitialState.ts → board/initialState.ts} +3 -6
  216. package/src/state/board/selectors.ts +3 -0
  217. package/src/state/{slices/boardSlice.ts → board/slice.ts} +5 -4
  218. package/src/state/board/types.ts +3 -0
  219. package/src/state/cellFilters/index.ts +4 -0
  220. package/src/state/cellFilters/initialState.ts +3 -0
  221. package/src/state/cellFilters/lib.ts +8 -0
  222. package/src/state/cellFilters/selectors.ts +13 -0
  223. package/src/state/{slices/cellFilterSlice.ts → cellFilters/slice.ts} +15 -14
  224. package/src/state/cellFilters/types.ts +3 -0
  225. package/src/state/dictionary/index.ts +4 -0
  226. package/src/state/dictionary/initialState.ts +8 -0
  227. package/src/state/dictionary/selectors.ts +16 -0
  228. package/src/state/{slices/dictionarySlice.ts → dictionary/slice.ts} +3 -3
  229. package/src/state/dictionary/types.ts +8 -0
  230. package/src/state/index.ts +12 -5
  231. package/src/{lib/getRemainingTiles.ts → state/lib.ts} +3 -4
  232. package/src/state/localStorage.ts +11 -2
  233. package/src/state/rack/index.ts +4 -0
  234. package/src/state/rack/initialState.ts +12 -0
  235. package/src/state/rack/selectors.ts +7 -0
  236. package/src/state/{slices/rackSlice.ts → rack/slice.ts} +4 -4
  237. package/src/state/rack/types.ts +3 -0
  238. package/src/state/results/index.ts +4 -0
  239. package/src/state/results/initialState.ts +13 -0
  240. package/src/state/results/lib.ts +96 -0
  241. package/src/state/results/selectors.ts +75 -0
  242. package/src/state/{slices/resultsSlice.ts → results/slice.ts} +4 -4
  243. package/src/state/results/types.ts +10 -0
  244. package/src/state/sagas.ts +22 -23
  245. package/src/state/selectors.ts +15 -235
  246. package/src/state/settings/index.ts +4 -0
  247. package/src/state/{slices/settingsInitialState.ts → settings/initialState.ts} +4 -11
  248. package/src/state/settings/lib.ts +42 -0
  249. package/src/state/settings/selectors.ts +69 -0
  250. package/src/state/{slices/settingsSlice.ts → settings/slice.ts} +9 -4
  251. package/src/state/settings/types.ts +12 -0
  252. package/src/state/solve/index.ts +4 -0
  253. package/src/state/solve/initialState.ts +12 -0
  254. package/src/state/solve/selectors.ts +14 -0
  255. package/src/state/{slices/solveSlice.ts → solve/slice.ts} +3 -3
  256. package/src/state/solve/types.ts +10 -0
  257. package/src/state/store.ts +9 -11
  258. package/src/state/types.ts +16 -18
  259. package/src/state/useTranslate.ts +2 -2
  260. package/src/state/useTypedSelector.ts +2 -2
  261. package/src/state/verify/index.ts +4 -0
  262. package/src/state/verify/initialState.ts +12 -0
  263. package/src/state/verify/selectors.ts +9 -0
  264. package/src/state/{slices/verifySlice.ts → verify/slice.ts} +3 -3
  265. package/src/state/verify/types.ts +10 -0
  266. package/src/styles/global.scss +5 -0
  267. package/src/types/api.ts +1 -1
  268. package/src/types/index.ts +8 -3
  269. package/tsconfig.tsbuildinfo +1 -1
  270. package/.eslintrc.js +0 -10
  271. package/.next/server/chunks/60.js +0 -1
  272. package/.next/server/chunks/968.js +0 -1
  273. package/.next/static/chunks/framework-288d1abd95de88d9.js +0 -1
  274. package/.next/static/chunks/main-016492249b3393e2.js +0 -1
  275. package/.next/static/chunks/pages/_app-0e951de0aebb6505.js +0 -1
  276. package/.next/static/chunks/pages/index-c1d5a66d0f4794a6.js +0 -1
  277. package/src/components/Board/lib/getBonusColor.ts +0 -16
  278. package/src/components/Board/lib/getPositionInGrid.ts +0 -13
  279. package/src/components/Board/lib/index.ts +0 -2
  280. package/src/components/PlainTiles/lib/createPlainTile.ts +0 -41
  281. package/src/components/PlainTiles/lib/createPlainTiles.ts +0 -25
  282. package/src/components/PlainTiles/lib/getViewbox.ts +0 -17
  283. package/src/components/PlainTiles/lib/getX.ts +0 -5
  284. package/src/components/PlainTiles/lib/getY.ts +0 -5
  285. package/src/components/PlainTiles/lib/index.ts +0 -6
  286. package/src/components/PlainTiles/lib/randomize.ts +0 -1
  287. package/src/lib/createArray.ts +0 -1
  288. package/src/lib/createGridOf.ts +0 -9
  289. package/src/lib/detectLocale.ts +0 -27
  290. package/src/lib/extractCharactersByCase.test.ts +0 -29
  291. package/src/lib/extractCharactersByCase.ts +0 -29
  292. package/src/lib/getCellSize.ts +0 -10
  293. package/src/lib/getCoordinates.ts +0 -16
  294. package/src/lib/getRemainingTilesCount.ts +0 -11
  295. package/src/lib/getTotalRemainingTilesCount.ts +0 -11
  296. package/src/lib/groupResults.ts +0 -35
  297. package/src/lib/guessLocale.ts +0 -20
  298. package/src/lib/isUpperCase.ts +0 -5
  299. package/src/lib/resultMatchesCellFilter.ts +0 -21
  300. package/src/lib/sortGroupedResults.ts +0 -21
  301. package/src/lib/sortResults.ts +0 -41
  302. package/src/state/slices/cellFilterInitialState.ts +0 -5
  303. package/src/state/slices/dictionaryInitialState.ts +0 -15
  304. package/src/state/slices/index.ts +0 -16
  305. package/src/state/slices/rackInitialState.ts +0 -9
  306. package/src/state/slices/resultsInitialState.ts +0 -20
  307. package/src/state/slices/solveInitialState.ts +0 -21
  308. package/src/state/slices/verifyInitialState.ts +0 -19
  309. /package/.next/static/{47JHul8F9NSWCNSEuahuL → MhrqAqLI9_L8obb7tgjvi}/_ssgManifest.js +0 -0
@@ -1,14 +1,15 @@
1
1
  import classNames from 'classnames';
2
- import { FunctionComponent, memo } from 'react';
2
+ import { type FunctionComponent, memo } from 'react';
3
3
 
4
4
  import { useAppLayout } from 'hooks';
5
5
  import { CardChecklist, Cog, Eraser, Github, KeyboardFill, List, Sack } from 'icons';
6
6
  import { GITHUB_PROJECT_URL } from 'parameters';
7
- import { selectConfig, selectHasInvalidWords, selectHasOverusedTiles, useTranslate, useTypedSelector } from 'state';
7
+ import { selectConfig, useTranslate, useTypedSelector } from 'state';
8
8
 
9
9
  import { IconButton } from '../IconButton';
10
10
 
11
11
  import styles from './NavButtons.module.scss';
12
+ import { selectHasInvalidWords, selectHasOverusedTiles } from './selectors';
12
13
 
13
14
  interface Props {
14
15
  onClear: () => void;
@@ -29,8 +30,8 @@ const NavButtonsBase: FunctionComponent<Props> = ({
29
30
  }) => {
30
31
  const translate = useTranslate();
31
32
  const config = useTypedSelector(selectConfig);
32
- const hasOverusedTiles = useTypedSelector(selectHasOverusedTiles);
33
33
  const hasInvalidWords = useTypedSelector(selectHasInvalidWords);
34
+ const hasOverusedTiles = useTypedSelector(selectHasOverusedTiles);
34
35
  const { showKeyMap, showShortNav } = useAppLayout();
35
36
 
36
37
  if (showShortNav) {
@@ -0,0 +1,11 @@
1
+ import { createSelector } from '@reduxjs/toolkit';
2
+
3
+ import { selectInvalidWords, selectRemainingTiles } from 'state';
4
+
5
+ export const selectHasInvalidWords = createSelector([selectInvalidWords], (invalidWords) => {
6
+ return invalidWords.length > 0;
7
+ });
8
+
9
+ export const selectHasOverusedTiles = createSelector([selectRemainingTiles], (remainingTiles) => {
10
+ return remainingTiles.some(({ count = 0, usedCount }) => usedCount > count);
11
+ });
@@ -1,4 +1,4 @@
1
- import { FunctionComponent } from 'react';
1
+ import { type FunctionComponent } from 'react';
2
2
 
3
3
  import { DashCircleFill } from 'icons';
4
4
 
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { CSSProperties, FunctionComponent, useMemo } from 'react';
2
+ import { type CSSProperties, type FunctionComponent, useMemo } from 'react';
3
3
 
4
4
  import { createPlainTiles, getViewbox } from './lib';
5
5
  import styles from './PlainTiles.module.scss';
@@ -1,4 +1,4 @@
1
- import { FunctionComponent } from 'react';
1
+ import { type FunctionComponent } from 'react';
2
2
 
3
3
  interface Props {
4
4
  character: string;
@@ -0,0 +1,90 @@
1
+ import { getConfig } from '@scrabble-solver/configs';
2
+ import { Game, Locale } from '@scrabble-solver/types';
3
+
4
+ import {
5
+ PLAIN_TILES_COLOR_DEFAULT,
6
+ PLAIN_TILES_PADDING_HORIZONTAL,
7
+ PLAIN_TILES_PADDING_VERTICAL,
8
+ PLAIN_TILES_POINTS_COLORS,
9
+ PLAIN_TILES_TILE_MARGIN,
10
+ PLAIN_TILES_TILE_MAX_ROTATE,
11
+ PLAIN_TILES_TILE_MAX_SCATTER,
12
+ PLAIN_TILES_TILE_SIZE,
13
+ } from 'parameters';
14
+
15
+ import type { CreatePlainTileOptions, CreatePlainTilesOptions, PlainTile } from './types';
16
+
17
+ export const createPlainTiles = ({ color, content, showPoints }: CreatePlainTilesOptions): PlainTile[] => {
18
+ const rows = content.map((words, rowIndex) => {
19
+ return words.map((word, wordIndex) => {
20
+ const cellOffset = words.slice(0, wordIndex).reduce((result, { length }) => result + length + ' '.length, 0);
21
+ const characters = word.split('');
22
+
23
+ return characters.map((character, cellIndex) => {
24
+ return createPlainTile({
25
+ cellIndex: cellOffset + cellIndex,
26
+ character,
27
+ color,
28
+ rowIndex,
29
+ showPoints,
30
+ });
31
+ });
32
+ });
33
+ });
34
+
35
+ const tiles = rows.flat(2);
36
+ return tiles;
37
+ };
38
+
39
+ export const createPlainTile = ({
40
+ cellIndex,
41
+ character,
42
+ color,
43
+ rowIndex,
44
+ showPoints,
45
+ }: CreatePlainTileOptions): PlainTile => {
46
+ const configPoints = getConfig(Game.Literaki, Locale.EN_US).getCharacterPoints(character.toLowerCase());
47
+ const points = showPoints ? configPoints : undefined;
48
+ const defaultColor =
49
+ typeof configPoints === 'number' ? PLAIN_TILES_POINTS_COLORS[configPoints] : PLAIN_TILES_COLOR_DEFAULT;
50
+ const x = getX(cellIndex) + PLAIN_TILES_TILE_SIZE / 2;
51
+ const y = getY(0) + PLAIN_TILES_TILE_SIZE / 2;
52
+
53
+ return {
54
+ character,
55
+ color: color || defaultColor,
56
+ points,
57
+ size: PLAIN_TILES_TILE_SIZE,
58
+ transform: `rotate(${randomize(0, PLAIN_TILES_TILE_MAX_ROTATE)}, ${x}, ${y})`,
59
+ x: randomize(getX(cellIndex), PLAIN_TILES_TILE_MAX_SCATTER),
60
+ y: randomize(getY(rowIndex), PLAIN_TILES_TILE_MAX_SCATTER),
61
+ };
62
+ };
63
+
64
+ export const getViewbox = (content: string[][]): string => {
65
+ const longestRowLength = content.reduce((result, words) => {
66
+ const wordsLength = words.reduce((sum, word) => sum + word.length, 0);
67
+ const rowLength = wordsLength + Math.max(words.length - 1, 0);
68
+ return Math.max(result, rowLength);
69
+ }, 0);
70
+ const width =
71
+ longestRowLength * (PLAIN_TILES_TILE_SIZE + PLAIN_TILES_TILE_MARGIN) -
72
+ (longestRowLength === 0 ? 0 : PLAIN_TILES_TILE_MARGIN);
73
+ const height =
74
+ content.length * (PLAIN_TILES_TILE_SIZE + PLAIN_TILES_TILE_MARGIN) -
75
+ (content.length === 0 ? 0 : PLAIN_TILES_TILE_MARGIN);
76
+
77
+ return `0 0 ${width} ${height}`;
78
+ };
79
+
80
+ export const getX = (index: number): number => {
81
+ return PLAIN_TILES_PADDING_HORIZONTAL + index * (PLAIN_TILES_TILE_SIZE + PLAIN_TILES_TILE_MARGIN);
82
+ };
83
+
84
+ export const getY = (index: number): number => {
85
+ return PLAIN_TILES_PADDING_VERTICAL + index * (PLAIN_TILES_TILE_SIZE + PLAIN_TILES_TILE_MARGIN);
86
+ };
87
+
88
+ export const randomize = (value: number, maxChange: number): number => {
89
+ return value + maxChange * 2 * (0.5 - Math.random());
90
+ };
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { FunctionComponent, HTMLProps } from 'react';
2
+ import { type FunctionComponent, type HTMLProps } from 'react';
3
3
 
4
4
  import { PROGRESS_COLOR_BACKGROUND, PROGRESS_COLOR_VALUE } from 'parameters';
5
5
  import { selectLocale, useTypedSelector } from 'state';
@@ -3,10 +3,10 @@
3
3
  import { FloatingPortal, autoUpdate, useFloating } from '@floating-ui/react';
4
4
  import classNames from 'classnames';
5
5
  import {
6
- ChangeEvent,
7
- ClipboardEvent,
8
- FunctionComponent,
9
- RefObject,
6
+ type ChangeEvent,
7
+ type ClipboardEvent,
8
+ type FunctionComponent,
9
+ type RefObject,
10
10
  createRef,
11
11
  useCallback,
12
12
  useMemo,
@@ -18,27 +18,12 @@ import { useDispatch } from 'react-redux';
18
18
 
19
19
  import { useAppLayout } from 'hooks';
20
20
  import { LOCALE_FEATURES } from 'i18n';
21
- import {
22
- createArray,
23
- createKeyboardNavigation,
24
- extractCharacters,
25
- extractInputValue,
26
- getTileSizes,
27
- isCtrl,
28
- zipCharactersAndTiles,
29
- } from 'lib';
30
- import {
31
- rackSlice,
32
- selectConfig,
33
- selectInputMode,
34
- selectLocale,
35
- selectRack,
36
- selectResultCandidateTiles,
37
- useTypedSelector,
38
- } from 'state';
21
+ import { createKeyboardNavigation, extractCharacters, extractInputValue, getTileSizes, isCtrl } from 'lib';
22
+ import { rackSlice, selectConfig, selectInputMode, selectLocale, selectRack, useTypedSelector } from 'state';
39
23
 
40
24
  import { InputPrompt, RackTile } from './components';
41
25
  import styles from './Rack.module.scss';
26
+ import { selectRemainingTilesGroups } from './selectors';
42
27
 
43
28
  interface Props {
44
29
  className?: string;
@@ -47,16 +32,15 @@ interface Props {
47
32
 
48
33
  export const Rack: FunctionComponent<Props> = ({ className, tileSize }) => {
49
34
  const dispatch = useDispatch();
35
+ const { rackHeight } = useAppLayout();
50
36
  const config = useTypedSelector(selectConfig);
51
37
  const locale = useTypedSelector(selectLocale);
52
38
  const rack = useTypedSelector(selectRack);
53
39
  const inputMode = useTypedSelector(selectInputMode);
54
- const { rackHeight } = useAppLayout();
55
- const resultCandidateTiles = useTypedSelector(selectResultCandidateTiles);
56
- const tiles = useMemo(() => zipCharactersAndTiles(rack, resultCandidateTiles), [rack, resultCandidateTiles]);
40
+ const tiles = useTypedSelector(selectRemainingTilesGroups);
57
41
  const tilesCount = tiles.length;
58
42
  const tilesRefs = useMemo(
59
- () => createArray(tilesCount).map(() => createRef<HTMLInputElement | null>()),
43
+ () => Array.from({ length: tilesCount }).map(() => createRef<HTMLInputElement | null>()),
60
44
  [tilesCount],
61
45
  );
62
46
  const activeIndexRef = useRef<number | undefined>(undefined);
@@ -1,8 +1,8 @@
1
1
  import classNames from 'classnames';
2
2
  import {
3
- CSSProperties,
4
- ChangeEventHandler,
5
- FormEventHandler,
3
+ type CSSProperties,
4
+ type ChangeEventHandler,
5
+ type FormEventHandler,
6
6
  forwardRef,
7
7
  useCallback,
8
8
  useEffect,
@@ -11,10 +11,10 @@ import {
11
11
  import { useDispatch } from 'react-redux';
12
12
 
13
13
  import { useAppLayout } from 'hooks';
14
- import { extractCharactersByCase } from 'lib';
15
14
  import { rackSlice, selectConfig, useTranslate, useTypedSelector } from 'state';
16
15
 
17
16
  import styles from './InputPrompt.module.scss';
17
+ import { extractRack } from './lib';
18
18
 
19
19
  interface Props {
20
20
  className?: string;
@@ -36,10 +36,7 @@ const InputPromptBase = forwardRef<HTMLFormElement, Props>(
36
36
  const handleSubmit: FormEventHandler<HTMLFormElement> = useCallback(
37
37
  (event) => {
38
38
  event.preventDefault();
39
- const charactersByCase = extractCharactersByCase(config, value);
40
- const characters = Array.from({ length: config.rackSize }, (_, index) => {
41
- return typeof charactersByCase[index] === 'string' ? charactersByCase[index] : null;
42
- });
39
+ const characters = extractRack(config, value);
43
40
  dispatch(rackSlice.actions.changeCharacters({ characters, index: 0 }));
44
41
  onSubmit(event);
45
42
  },
@@ -0,0 +1,27 @@
1
+ import { getConfig } from '@scrabble-solver/configs';
2
+ import { BLANK } from '@scrabble-solver/constants';
3
+ import { Game, Locale } from '@scrabble-solver/types';
4
+
5
+ import { extractRack } from './lib';
6
+
7
+ describe('extractRack', () => {
8
+ const locale = Locale.ES_ES;
9
+ const config = getConfig(Game.Scrabble, locale);
10
+
11
+ it.each([
12
+ { input: 'ab ', expected: ['a', 'b', BLANK, null, null, null, null] },
13
+ { input: 'śćźa', expected: ['s', 'c', 'z', 'a', null, null, null] },
14
+ { input: 'bueno', expected: ['b', 'u', 'e', 'n', 'o', null, null] },
15
+ { input: 'bellas', expected: ['b', 'e', 'l', 'l', 'a', 's', null] },
16
+ { input: 'churro', expected: ['c', 'h', 'u', 'r', 'r', 'o', null] },
17
+ { input: 'challulla', expected: ['c', 'h', 'a', 'l', 'l', 'u', 'l'] },
18
+ { input: 'beLlas', expected: ['b', 'e', 'l', 'l', 'a', 's', null] },
19
+ { input: 'belLas', expected: ['b', 'e', 'l', 'l', 'a', 's', null] },
20
+ { input: 'beLLas', expected: ['b', 'e', 'll', 'a', 's', null, null] },
21
+ { input: 'chuRRo', expected: ['c', 'h', 'u', 'rr', 'o', null, null] },
22
+ { input: 'CHuRRo', expected: ['ch', 'u', 'rr', 'o', null, null, null] },
23
+ { input: 'CHaLLuLLa', expected: ['ch', 'a', 'll', 'u', 'll', 'a', null] },
24
+ ])(`[${locale}] "$input"`, ({ input, expected }) => {
25
+ expect(extractRack(config, input)).toEqual(expected);
26
+ });
27
+ });
@@ -0,0 +1,19 @@
1
+ import { type Config } from '@scrabble-solver/types';
2
+
3
+ // eslint-disable-next-line no-warning-comments
4
+ // TODO: https://github.com/kamilmielnik/scrabble-solver/issues/393
5
+ import { extractCharacters } from '../../../../lib/extractCharacters';
6
+
7
+ export const extractRack = (config: Config, value: string): (string | null)[] => {
8
+ const charactersByCase = extractCharacters(config, value, {
9
+ /**
10
+ * This is to allow inserting digraphs on the rack in touchscreen input mode.
11
+ * This is not necessary on the board.
12
+ */
13
+ upperCaseDigraphsOnly: true,
14
+ });
15
+ const characters = Array.from({ length: config.rackSize }, (_, index) => {
16
+ return typeof charactersByCase[index] === 'string' ? charactersByCase[index] : null;
17
+ });
18
+ return characters;
19
+ };
@@ -1,15 +1,15 @@
1
1
  import { BLANK } from '@scrabble-solver/constants';
2
- import { Tile as TileModel } from '@scrabble-solver/types';
2
+ import { type Tile as TileModel } from '@scrabble-solver/types';
3
3
  import classNames from 'classnames';
4
4
  import {
5
- ChangeEvent,
6
- ChangeEventHandler,
7
- FocusEventHandler,
8
- FunctionComponent,
9
- KeyboardEventHandler,
10
- MouseEventHandler,
11
- RefObject,
12
- TouchEventHandler,
5
+ type ChangeEvent,
6
+ type ChangeEventHandler,
7
+ type FocusEventHandler,
8
+ type FunctionComponent,
9
+ type KeyboardEventHandler,
10
+ type MouseEventHandler,
11
+ type RefObject,
12
+ type TouchEventHandler,
13
13
  useCallback,
14
14
  useMemo,
15
15
  } from 'react';
@@ -0,0 +1,9 @@
1
+ import { createSelector } from '@reduxjs/toolkit';
2
+
3
+ import { zipCharactersAndTiles } from 'lib';
4
+ import { selectRack, selectResultCandidateTiles } from 'state';
5
+
6
+ export const selectRemainingTilesGroups = createSelector(
7
+ [selectRack, selectResultCandidateTiles],
8
+ zipCharactersAndTiles,
9
+ );
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { ChangeEventHandler, FunctionComponent, ReactNode } from 'react';
2
+ import { type ChangeEventHandler, type FunctionComponent, type ReactNode } from 'react';
3
3
 
4
4
  import styles from './Radio.module.scss';
5
5
 
@@ -1,8 +1,8 @@
1
1
  import classNames from 'classnames';
2
- import { CSSProperties, FunctionComponent, ReactNode } from 'react';
2
+ import { type CSSProperties, type FunctionComponent, type ReactNode } from 'react';
3
3
 
4
4
  import { selectLocale, useTranslate, useTypedSelector } from 'state';
5
- import { TranslationKey } from 'types';
5
+ import { type TranslationKey } from 'types';
6
6
 
7
7
  import { Tooltip } from '../Tooltip';
8
8
 
@@ -1,4 +1,4 @@
1
- import { FunctionComponent } from 'react';
1
+ import { type FunctionComponent } from 'react';
2
2
 
3
3
  import { useAppLayout, useColumns } from 'hooks';
4
4
  import { GeoAlt, OneTwoThree, Square, SquareA, SquareB, Squares, Words } from 'icons';
@@ -1,10 +1,10 @@
1
1
  import classNames from 'classnames';
2
- import { CSSProperties, FunctionComponent, ReactElement, SVGAttributes, useCallback } from 'react';
2
+ import { type CSSProperties, type FunctionComponent, type ReactElement, type SVGAttributes, useCallback } from 'react';
3
3
  import { useDispatch } from 'react-redux';
4
4
 
5
5
  import { SortDown, SortUp } from 'icons';
6
6
  import { resultsSlice, selectResultsSort, useTranslate, useTypedSelector } from 'state';
7
- import { ResultColumnId, SortDirection, TranslationKey } from 'types';
7
+ import { type ResultColumnId, SortDirection, type TranslationKey } from 'types';
8
8
 
9
9
  import { Tooltip } from '../Tooltip';
10
10
 
@@ -1,22 +1,22 @@
1
1
  import classNames from 'classnames';
2
- import { CSSProperties, FocusEventHandler, MouseEventHandler, ReactElement, useMemo, useRef } from 'react';
2
+ import { type CSSProperties, type FocusEventHandler, type MouseEventHandler, type ReactElement, useRef } from 'react';
3
3
  import Highlighter from 'react-highlight-words';
4
4
 
5
5
  import { useAppLayout, useColumns } from 'hooks';
6
6
  import { LOCALE_FEATURES } from 'i18n';
7
- import { getCoordinates, noop } from 'lib';
7
+ import { noop } from 'lib';
8
8
  import {
9
9
  selectIsResultMatching,
10
10
  selectLocale,
11
+ selectResultCoordinates,
11
12
  selectResultsQuery,
12
- selectShowCoordinates,
13
13
  useTypedSelector,
14
14
  } from 'state';
15
15
  import { ResultColumnId } from 'types';
16
16
 
17
17
  import { Cell } from './Cell';
18
18
  import styles from './Results.module.scss';
19
- import { ResultData } from './types';
19
+ import { type ResultData } from './types';
20
20
 
21
21
  interface Props {
22
22
  data: ResultData;
@@ -38,13 +38,12 @@ export const Result = ({ data, index, style }: Props): ReactElement => {
38
38
  const ref = useRef<HTMLButtonElement>(null);
39
39
  const columns = useColumns();
40
40
  const locale = useTypedSelector(selectLocale);
41
- const showCoordinates = useTypedSelector(selectShowCoordinates);
42
41
  const query = useTypedSelector(selectResultsQuery);
43
42
  const { direction, separator } = LOCALE_FEATURES[locale];
44
43
  const result = results[index];
45
44
  const isMatching = useTypedSelector((state) => selectIsResultMatching(state, index));
46
45
  const words = direction === 'rtl' ? [...result.words].reverse() : result.words;
47
- const coordinates = useMemo(() => getCoordinates(result, showCoordinates), [result, showCoordinates]);
46
+ const coordinates = useTypedSelector((state) => selectResultCoordinates(state, index));
48
47
 
49
48
  const handleClick: MouseEventHandler = (event) => onClick(result, event);
50
49
  const handleMouseEnter: MouseEventHandler = (event) => onMouseEnter(result, event);
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { FunctionComponent, useEffect, useMemo, useState } from 'react';
2
+ import { type FunctionComponent, useEffect, useMemo, useState } from 'react';
3
3
  import { FixedSizeList } from 'react-window';
4
4
  import { useDebounce } from 'use-debounce';
5
5
 
@@ -8,9 +8,9 @@ import { LOCALE_FEATURES } from 'i18n';
8
8
  import { BORDER_WIDTH, RESULTS_HEADER_HEIGHT, RESULTS_ITEM_HEIGHT, TEXT_INPUT_HEIGHT } from 'parameters';
9
9
  import {
10
10
  selectAreResultsOutdated,
11
- selectIsLoading,
11
+ selectSolveIsLoading,
12
12
  selectLocale,
13
- selectResults,
13
+ selectProcessedResults,
14
14
  selectSolveError,
15
15
  useTranslate,
16
16
  useTypedSelector,
@@ -24,7 +24,7 @@ import { Header } from './Header';
24
24
  import { Result } from './Result';
25
25
  import styles from './Results.module.scss';
26
26
  import { SolveButton } from './SolveButton';
27
- import { ResultCallbacks, ResultData } from './types';
27
+ import { type ResultCallbacks, type ResultData } from './types';
28
28
 
29
29
  interface Props {
30
30
  callbacks: ResultCallbacks;
@@ -39,8 +39,8 @@ export const Results: FunctionComponent<Props> = ({ callbacks, className, highli
39
39
  const { resultsHeight, resultsWidth } = useAppLayout();
40
40
  const locale = useTypedSelector(selectLocale);
41
41
  const { direction } = LOCALE_FEATURES[locale];
42
- const results = useTypedSelector(selectResults);
43
- const isLoading = useTypedSelector(selectIsLoading);
42
+ const results = useTypedSelector(selectProcessedResults);
43
+ const isLoading = useTypedSelector(selectSolveIsLoading);
44
44
  const [isLoadingDebounced] = useDebounce(isLoading, IS_LOADING_DEBOUNCE);
45
45
  const isOutdated = useTypedSelector(selectAreResultsOutdated);
46
46
  const error = useTypedSelector(selectSolveError);
@@ -1,10 +1,10 @@
1
- import { FunctionComponent } from 'react';
1
+ import { type FunctionComponent } from 'react';
2
2
  import { useDispatch } from 'react-redux';
3
3
 
4
4
  import { Search } from 'icons';
5
5
  import {
6
6
  selectAreResultsOutdated,
7
- selectIsLoading,
7
+ selectSolveIsLoading,
8
8
  selectRack,
9
9
  solveSlice,
10
10
  useTranslate,
@@ -20,7 +20,7 @@ interface Props {
20
20
  export const SolveButton: FunctionComponent<Props> = ({ className }) => {
21
21
  const dispatch = useDispatch();
22
22
  const translate = useTranslate();
23
- const isLoading = useTypedSelector(selectIsLoading);
23
+ const isLoading = useTypedSelector(selectSolveIsLoading);
24
24
  const rack = useTypedSelector(selectRack);
25
25
  const isOutdated = useTypedSelector(selectAreResultsOutdated);
26
26
  const hasTiles = rack.some((tile) => tile !== null);
@@ -1,5 +1,5 @@
1
- import { Result } from '@scrabble-solver/types';
2
- import { FocusEvent, MouseEvent } from 'react';
1
+ import { type Result } from '@scrabble-solver/types';
2
+ import { type FocusEvent, type MouseEvent } from 'react';
3
3
 
4
4
  export interface ResultCallbacks {
5
5
  onBlur?: (result: Result, event: FocusEvent) => void;
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { ChangeEvent, FormEventHandler, FunctionComponent, useState } from 'react';
2
+ import { type ChangeEvent, type FormEventHandler, type FunctionComponent, useState } from 'react';
3
3
  import { useDispatch } from 'react-redux';
4
4
 
5
5
  import { isRegExp } from 'lib';
@@ -1,4 +1,4 @@
1
- import { CSSProperties, FunctionComponent } from 'react';
1
+ import { type CSSProperties, type FunctionComponent } from 'react';
2
2
 
3
3
  const INVISIBLE_STYLE: CSSProperties = {
4
4
  color: 'transparent',
@@ -1,14 +1,14 @@
1
- import { Result } from '@scrabble-solver/types';
1
+ import { type Result } from '@scrabble-solver/types';
2
2
  import classNames from 'classnames';
3
- import { FunctionComponent, memo, SyntheticEvent, useEffect, useMemo } from 'react';
3
+ import { type FunctionComponent, memo, type SyntheticEvent, useEffect, useMemo } from 'react';
4
4
  import { useDispatch } from 'react-redux';
5
5
 
6
6
  import { useAppLayout, useIsTouchDevice } from 'hooks';
7
7
  import {
8
8
  resultsSlice,
9
9
  selectAreResultsOutdated,
10
+ selectProcessedResults,
10
11
  selectResultCandidate,
11
- selectResults,
12
12
  selectSolveError,
13
13
  solveSlice,
14
14
  useTranslate,
@@ -38,7 +38,7 @@ const SolverBase: FunctionComponent<Props> = ({ className, onShowResults }) => {
38
38
  const error = useTypedSelector(selectSolveError);
39
39
  const isOutdated = useTypedSelector(selectAreResultsOutdated);
40
40
  const resultCandidate = useTypedSelector(selectResultCandidate);
41
- const results = useTypedSelector(selectResults);
41
+ const results = useTypedSelector(selectProcessedResults);
42
42
  const [bestResult] = results || [];
43
43
  const touchCallbacks = useMemo(
44
44
  () => ({
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { FunctionComponent } from 'react';
2
+ import { type FunctionComponent } from 'react';
3
3
  import { useDispatch } from 'react-redux';
4
4
 
5
5
  import { Check } from 'icons';
@@ -1,15 +1,15 @@
1
1
  import classNames from 'classnames';
2
- import { FunctionComponent, HTMLProps, MouseEventHandler } from 'react';
2
+ import { type FunctionComponent, type HTMLProps, type MouseEventHandler } from 'react';
3
3
  import { useDispatch } from 'react-redux';
4
4
 
5
5
  import { ChevronDown, ChevronLeft, ChevronRight } from 'icons';
6
6
  import {
7
7
  resultsSlice,
8
8
  selectAreResultsOutdated,
9
- selectIsLoading,
9
+ selectSolveIsLoading,
10
10
  selectLocale,
11
+ selectProcessedResults,
11
12
  selectResultCandidate,
12
- selectResults,
13
13
  useTranslate,
14
14
  useTypedSelector,
15
15
  } from 'state';
@@ -28,9 +28,9 @@ export const ResultCandidatePicker: FunctionComponent<Props> = ({ className, onR
28
28
  const dispatch = useDispatch();
29
29
  const translate = useTranslate();
30
30
  const locale = useTypedSelector(selectLocale);
31
- const isLoading = useTypedSelector(selectIsLoading);
31
+ const isLoading = useTypedSelector(selectSolveIsLoading);
32
32
  const isOutdated = useTypedSelector(selectAreResultsOutdated);
33
- const results = useTypedSelector(selectResults);
33
+ const results = useTypedSelector(selectProcessedResults);
34
34
  const resultCandidate = useTypedSelector(selectResultCandidate);
35
35
  const index = resultCandidate && results ? results.findIndex((result) => result.id === resultCandidate.id) : -1;
36
36
  const disabled = isOutdated || !resultCandidate;
@@ -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 { useTranslate } from 'state';
5
5
 
@@ -1,13 +1,13 @@
1
1
  import { useMergeRefs } from '@floating-ui/react';
2
2
  import { EMPTY_CELL } from '@scrabble-solver/constants';
3
3
  import {
4
- ChangeEventHandler,
5
- FocusEventHandler,
6
- FunctionComponent,
7
- KeyboardEventHandler,
8
- MouseEventHandler,
9
- Ref,
10
- TouchEventHandler,
4
+ type ChangeEventHandler,
5
+ type FocusEventHandler,
6
+ type FunctionComponent,
7
+ type KeyboardEventHandler,
8
+ type MouseEventHandler,
9
+ type Ref,
10
+ type TouchEventHandler,
11
11
  useCallback,
12
12
  useMemo,
13
13
  useRef,
@@ -1,14 +1,14 @@
1
1
  import classNames from 'classnames';
2
2
  import {
3
- ChangeEventHandler,
4
- CSSProperties,
5
- FocusEventHandler,
6
- FunctionComponent,
7
- KeyboardEventHandler,
3
+ type ChangeEventHandler,
4
+ type CSSProperties,
5
+ type FocusEventHandler,
6
+ type FunctionComponent,
7
+ type KeyboardEventHandler,
8
8
  memo,
9
- MouseEventHandler,
10
- Ref,
11
- TouchEventHandler,
9
+ type MouseEventHandler,
10
+ type Ref,
11
+ type TouchEventHandler,
12
12
  } from 'react';
13
13
 
14
14
  import { ExclamationSquareFill } from 'icons';
@@ -1,5 +1,5 @@
1
1
  import type { Placement } from '@floating-ui/react';
2
- import { FunctionComponent, ReactNode } from 'react';
2
+ import { type FunctionComponent, type ReactNode } from 'react';
3
3
 
4
4
  import { TooltipContext } from './context';
5
5
  import { TooltipContent } from './TooltipContent';