@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
@@ -1,4 +1,4 @@
1
- import { Locale } from '@scrabble-solver/types';
1
+ import { type Locale } from '@scrabble-solver/types';
2
2
 
3
3
  import { DICTIONARY_CACHE } from './constants';
4
4
  import { expirationManager } from './expirationManager';
@@ -1,5 +1,5 @@
1
1
  import { Trie } from '@kamilmielnik/trie';
2
- import { Locale } from '@scrabble-solver/types';
2
+ import { type Locale } from '@scrabble-solver/types';
3
3
 
4
4
  import { getDictionary } from './dictionaries';
5
5
 
@@ -1,11 +1,11 @@
1
- import { Trie } from '@kamilmielnik/trie';
1
+ import { type Trie } from '@kamilmielnik/trie';
2
2
  import { getConfig } from '@scrabble-solver/configs';
3
3
  import { BLANK } from '@scrabble-solver/constants';
4
4
  import { solve } from '@scrabble-solver/solver';
5
5
  import { Board, Tile } from '@scrabble-solver/types';
6
6
  import { registerRoute } from 'workbox-routing';
7
7
 
8
- import { SolveRequestPayload } from 'types';
8
+ import { type SolveRequestPayload } from 'types';
9
9
 
10
10
  import { average } from './average';
11
11
  import { revalidateDictionary } from './dictionaries';
@@ -1,7 +1,7 @@
1
1
  import { Board } from '@scrabble-solver/types';
2
2
  import { registerRoute } from 'workbox-routing';
3
3
 
4
- import { VerifyRequestPayload } from 'types';
4
+ import { type VerifyRequestPayload } from 'types';
5
5
 
6
6
  import { revalidateDictionary } from './dictionaries';
7
7
  import { getTrie } from './getTrie';
@@ -0,0 +1,4 @@
1
+ export * from './initialState';
2
+ export * from './selectors';
3
+ export * from './slice';
4
+ export * from './types';
@@ -2,17 +2,14 @@ import { getConfig } from '@scrabble-solver/configs';
2
2
  import { Board } from '@scrabble-solver/types';
3
3
 
4
4
  import { localStorage } from '../localStorage';
5
+ import { settingsInitialState } from '../settings';
5
6
 
6
- import { settingsInitialState } from './settingsInitialState';
7
-
8
- export type BoardState = Board;
7
+ import type { BoardState } from './types';
9
8
 
10
9
  const { game, locale } = settingsInitialState;
11
10
  const { boardHeight, boardWidth } = getConfig(game, locale);
12
11
 
13
- export const boardDefaultState = Board.create(boardWidth, boardHeight);
14
-
15
- export const boardInitialState: BoardState = localStorage.getBoard() || boardDefaultState;
12
+ export const boardInitialState: BoardState = localStorage.getBoard() ?? Board.create(boardWidth, boardHeight);
16
13
 
17
14
  // const createOxyphenbutazone = () => {
18
15
  // // Tiles: oypbaze
@@ -0,0 +1,3 @@
1
+ import type { RootState } from '../types';
2
+
3
+ export const selectBoard = (state: RootState) => state.board;
@@ -1,10 +1,11 @@
1
- import { createSlice, PayloadAction } from '@reduxjs/toolkit';
1
+ import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
2
2
  import { games } from '@scrabble-solver/configs';
3
3
  import { EMPTY_CELL } from '@scrabble-solver/constants';
4
- import { Board, Cell, Result, Tile } from '@scrabble-solver/types';
4
+ import { Board, Cell, type Result, Tile } from '@scrabble-solver/types';
5
5
 
6
- import { boardInitialState } from './boardInitialState';
7
- import { settingsSlice } from './settingsSlice';
6
+ import { settingsSlice } from '../settings';
7
+
8
+ import { boardInitialState } from './initialState';
8
9
 
9
10
  export const boardSlice = createSlice({
10
11
  initialState: boardInitialState,
@@ -0,0 +1,3 @@
1
+ import { type Board } from '@scrabble-solver/types';
2
+
3
+ export type BoardState = Board;
@@ -0,0 +1,4 @@
1
+ export * from './initialState';
2
+ export * from './selectors';
3
+ export * from './slice';
4
+ export * from './types';
@@ -0,0 +1,3 @@
1
+ import type { CellFiltersState } from './types';
2
+
3
+ export const cellFiltersInitialState: CellFiltersState = [];
@@ -0,0 +1,8 @@
1
+ import type { CellFilterType } from 'types';
2
+
3
+ export const toggleCellFilterState = (type: CellFilterType): CellFilterType | null => {
4
+ const chain: (CellFilterType | null)[] = ['include', 'exclude', null];
5
+ const index = chain.indexOf(type);
6
+ const nextIndex = (index + 1) % chain.length;
7
+ return chain[nextIndex];
8
+ };
@@ -0,0 +1,13 @@
1
+ import { createSelector } from '@reduxjs/toolkit';
2
+
3
+ import type { Point } from 'types';
4
+
5
+ import type { RootState } from '../types';
6
+
7
+ const selectPoint = (_: unknown, point: Point): Point => point;
8
+
9
+ export const selectCellFilters = (state: RootState) => state.cellFilters;
10
+
11
+ export const selectCellFilter = createSelector([selectCellFilters, selectPoint], (cellFilters, point) => {
12
+ return cellFilters.find((cell) => cell.x === point.x && cell.y === point.y);
13
+ });
@@ -1,12 +1,14 @@
1
- import { createSlice, PayloadAction } from '@reduxjs/toolkit';
1
+ import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
2
+ import type { Cell } from '@scrabble-solver/types';
2
3
 
3
- import { CellFilterType, Point } from 'types';
4
+ import type { Point } from 'types';
4
5
 
5
- import { cellFilterInitialState } from './cellFilterInitialState';
6
+ import { cellFiltersInitialState } from './initialState';
7
+ import { toggleCellFilterState } from './lib';
6
8
 
7
- export const cellFilterSlice = createSlice({
8
- initialState: cellFilterInitialState,
9
- name: 'cellFilter',
9
+ export const cellFiltersSlice = createSlice({
10
+ initialState: cellFiltersInitialState,
11
+ name: 'cellFilters',
10
12
  reducers: {
11
13
  toggle: (state, action: PayloadAction<Point>) => {
12
14
  const { x, y } = action.payload;
@@ -37,13 +39,12 @@ export const cellFilterSlice = createSlice({
37
39
  return state.filter((point) => point.x !== x || point.y !== y);
38
40
  },
39
41
 
40
- reset: () => cellFilterInitialState,
42
+ removeCells: (state, action: PayloadAction<Cell[]>) => {
43
+ const cellsToRemove = action.payload;
44
+ return state.filter((entry) =>
45
+ cellsToRemove.every((cell) => cell.x !== entry.x || cell.y !== entry.y));
46
+ },
47
+
48
+ reset: () => cellFiltersInitialState,
41
49
  },
42
50
  });
43
-
44
- const toggleCellFilterState = (type: CellFilterType): CellFilterType | null => {
45
- const chain: (CellFilterType | null)[] = ['include', 'exclude', null];
46
- const index = chain.indexOf(type);
47
- const nextIndex = (index + 1) % chain.length;
48
- return chain[nextIndex];
49
- };
@@ -0,0 +1,3 @@
1
+ import type { CellFilter } from 'types';
2
+
3
+ export type CellFiltersState = CellFilter[];
@@ -0,0 +1,4 @@
1
+ export * from './initialState';
2
+ export * from './selectors';
3
+ export * from './slice';
4
+ export * from './types';
@@ -0,0 +1,8 @@
1
+ import { type DictionaryState } from './types';
2
+
3
+ export const dictionaryInitialState: DictionaryState = {
4
+ error: undefined,
5
+ input: '',
6
+ isLoading: false,
7
+ results: [],
8
+ };
@@ -0,0 +1,16 @@
1
+ import { createSelector } from '@reduxjs/toolkit';
2
+ import { isError } from '@scrabble-solver/types';
3
+
4
+ import type { RootState } from '../types';
5
+
6
+ export const selectDictionary = (state: RootState) => state.dictionary;
7
+
8
+ export const selectDictionaryInput = createSelector([selectDictionary], (dictionary) => dictionary.input);
9
+
10
+ export const selectDictionaryResults = createSelector([selectDictionary], (dictionary) => dictionary.results);
11
+
12
+ export const selectDictionaryIsLoading = createSelector([selectDictionary], (dictionary) => dictionary.isLoading);
13
+
14
+ export const selectDictionaryError = createSelector([selectDictionary], (dictionary) => {
15
+ return isError(dictionary.error) ? dictionary.error : undefined;
16
+ });
@@ -1,7 +1,7 @@
1
- import { createSlice, PayloadAction } from '@reduxjs/toolkit';
2
- import { WordDefinition } from '@scrabble-solver/types';
1
+ import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
2
+ import { type WordDefinition } from '@scrabble-solver/types';
3
3
 
4
- import { dictionaryInitialState } from './dictionaryInitialState';
4
+ import { dictionaryInitialState } from './initialState';
5
5
 
6
6
  export const dictionarySlice = createSlice({
7
7
  initialState: dictionaryInitialState,
@@ -0,0 +1,8 @@
1
+ import { type WordDefinition } from '@scrabble-solver/types';
2
+
3
+ export interface DictionaryState {
4
+ error: unknown;
5
+ input: string;
6
+ isLoading: boolean;
7
+ results: WordDefinition[];
8
+ }
@@ -1,7 +1,14 @@
1
1
  export * from './actions';
2
- export { localStorage } from './localStorage';
2
+ export * from './board';
3
+ export * from './cellFilters';
4
+ export * from './dictionary';
5
+ export * from './localStorage';
6
+ export * from './rack';
7
+ export * from './results';
3
8
  export * from './selectors';
4
- export * from './slices';
5
- export { store } from './store';
6
- export { useTranslate } from './useTranslate';
7
- export { useTypedSelector } from './useTypedSelector';
9
+ export * from './settings';
10
+ export * from './solve';
11
+ export * from './store';
12
+ export * from './useTranslate';
13
+ export * from './useTypedSelector';
14
+ export * from './verify';
@@ -1,9 +1,8 @@
1
1
  import { BLANK } from '@scrabble-solver/constants';
2
- import { Board, Config } from '@scrabble-solver/types';
2
+ import { type Board, type Config } from '@scrabble-solver/types';
3
3
 
4
- import { RemainingTile } from 'types';
5
-
6
- import { createKeyComparator } from './createKeyComparator';
4
+ import { createKeyComparator } from 'lib';
5
+ import { type RemainingTile } from 'types';
7
6
 
8
7
  export const getRemainingTiles = (
9
8
  config: Config,
@@ -1,12 +1,13 @@
1
- import { Board, BoardJson, Game, Locale, ShowCoordinates } from '@scrabble-solver/types';
1
+ import { Board, type BoardJson, type Game, type Locale, type ShowCoordinates } from '@scrabble-solver/types';
2
2
  import store2 from 'store2';
3
3
 
4
- import { AutoGroupTiles, InputMode, Rack } from 'types';
4
+ import type { AutoGroupTiles, InputMode, Rack, RemoveCellFilters } from 'types';
5
5
 
6
6
  const AUTO_GROUP_TILES = 'auto-group-tiles';
7
7
  const BOARD = 'board';
8
8
  const GAME_ID = 'config-id';
9
9
  const INPUT_MODE = 'input-mode';
10
+ const REMOVE_CELL_FILTERS = 'remove-cell-filters';
10
11
  const LOCALE = 'locale';
11
12
  const RACK = 'rack';
12
13
  const SHOW_COORDINATES = 'show-coordinates';
@@ -71,4 +72,12 @@ export const localStorage = {
71
72
  setShowCoordinates(showCoordinates: ShowCoordinates | undefined): void {
72
73
  store.set(SHOW_COORDINATES, showCoordinates, true);
73
74
  },
75
+
76
+ getRemoveCellFilters(): RemoveCellFilters | undefined {
77
+ return store.get(REMOVE_CELL_FILTERS) as RemoveCellFilters | undefined;
78
+ },
79
+
80
+ setRemoveCellFilters(removeCellFilters: RemoveCellFilters | undefined): void {
81
+ store.set(REMOVE_CELL_FILTERS, removeCellFilters, true);
82
+ },
74
83
  };
@@ -0,0 +1,4 @@
1
+ export * from './initialState';
2
+ export * from './selectors';
3
+ export * from './slice';
4
+ export * from './types';
@@ -0,0 +1,12 @@
1
+ import { getConfig } from '@scrabble-solver/configs';
2
+
3
+ import { localStorage } from '../localStorage';
4
+ import { settingsInitialState } from '../settings';
5
+
6
+ import type { RackState } from './types';
7
+
8
+ const defaultConfig = getConfig(settingsInitialState.game, settingsInitialState.locale);
9
+
10
+ export const rackDefaultState: RackState = Array(defaultConfig.rackSize).fill(null);
11
+
12
+ export const rackInitialState: RackState = localStorage.getRack() ?? rackDefaultState;
@@ -0,0 +1,7 @@
1
+ import { createSelector } from '@reduxjs/toolkit';
2
+
3
+ import { type RootState } from '../types';
4
+
5
+ export const selectRack = (state: RootState) => state.rack;
6
+
7
+ export const selectCharacters = createSelector(selectRack, (rack) => rack.filter((tile) => tile !== null));
@@ -1,10 +1,10 @@
1
- import { createSlice, PayloadAction } from '@reduxjs/toolkit';
2
- import { Tile } from '@scrabble-solver/types';
1
+ import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
2
+ import { type Tile } from '@scrabble-solver/types';
3
3
 
4
4
  import { arrayEquals, createNullMovingComparator, inverseDirection, zipCharactersAndTiles } from 'lib';
5
- import { AutoGroupTiles, Rack } from 'types';
5
+ import { type AutoGroupTiles, type Rack } from 'types';
6
6
 
7
- import { rackInitialState, rackDefaultState } from './rackInitialState';
7
+ import { rackDefaultState, rackInitialState } from './initialState';
8
8
 
9
9
  export const rackSlice = createSlice({
10
10
  initialState: rackInitialState,
@@ -0,0 +1,3 @@
1
+ import { type Rack } from 'types';
2
+
3
+ export type RackState = Rack;
@@ -0,0 +1,4 @@
1
+ export * from './initialState';
2
+ export * from './selectors';
3
+ export * from './slice';
4
+ export * from './types';
@@ -0,0 +1,13 @@
1
+ import { ResultColumnId, SortDirection } from 'types';
2
+
3
+ import type { ResultsState } from './types';
4
+
5
+ export const resultsInitialState: ResultsState = {
6
+ candidate: null,
7
+ query: '',
8
+ results: undefined,
9
+ sort: {
10
+ column: ResultColumnId.Points,
11
+ direction: SortDirection.Descending,
12
+ },
13
+ };
@@ -0,0 +1,96 @@
1
+ import { type Result, type ShowCoordinates } from '@scrabble-solver/types';
2
+
3
+ import { createKeyComparator, createRegExp, createStringComparator, getCoordinate, reverseComparator } from 'lib';
4
+ import { type CellFilter, type Comparator, type GroupedResults, ResultColumnId, type Sort, SortDirection } from 'types';
5
+
6
+ export const getCoordinates = (result: Result, showCoordinates: ShowCoordinates): string => {
7
+ if (showCoordinates === 'hidden') {
8
+ return '';
9
+ }
10
+
11
+ const firstCell = result.cells[0];
12
+ const x = getCoordinate(firstCell.x, showCoordinates === 'original' ? 'letter' : 'number');
13
+ const y = getCoordinate(firstCell.y, showCoordinates === 'original' ? 'number' : 'letter');
14
+
15
+ return result.isHorizontal() ? `${y}${x}` : `${x}${y}`;
16
+ };
17
+
18
+ export const groupResults = (
19
+ results: Result[] | undefined,
20
+ query: string,
21
+ cellFilters: CellFilter[],
22
+ ): GroupedResults | undefined => {
23
+ if (typeof results === 'undefined') {
24
+ return undefined;
25
+ }
26
+
27
+ const regExp = createRegExp(query);
28
+
29
+ const { matching, other } = results.reduce<GroupedResults>(
30
+ (groupedResults, result) => {
31
+ const matchesQuery = () => Boolean(result.word.match(regExp));
32
+
33
+ if (resultMatchesCellFilter(result, cellFilters) && matchesQuery()) {
34
+ groupedResults.matching.push(result);
35
+ } else {
36
+ groupedResults.other.push(result);
37
+ }
38
+
39
+ return groupedResults;
40
+ },
41
+ { matching: [], other: [] },
42
+ );
43
+
44
+ return { matching, other };
45
+ };
46
+
47
+ export const resultMatchesCellFilter = (result: Result, cellFilters: CellFilter[]): boolean => {
48
+ const excludeFilters = cellFilters.filter((filter) => filter.type === 'exclude');
49
+ const matchesExcludeFilters = excludeFilters.every(({ x, y }) => {
50
+ return result.cells.every((cell) => cell.x !== x || cell.y !== y);
51
+ });
52
+
53
+ if (!matchesExcludeFilters) {
54
+ return false;
55
+ }
56
+
57
+ const includeFilter = cellFilters.filter((filter) => filter.type === 'include');
58
+ const matchesIncludeFilters = includeFilter.every(({ x, y }) => {
59
+ return result.cells.some((cell) => cell.x === x && cell.y === y);
60
+ });
61
+
62
+ return matchesExcludeFilters && matchesIncludeFilters;
63
+ };
64
+
65
+ const comparators: Record<ResultColumnId, (locale: string, showCoordinates: ShowCoordinates) => Comparator<Result>> = {
66
+ [ResultColumnId.BlanksCount]: (locale: string) => createKeyComparator('blanksCount', locale),
67
+ [ResultColumnId.ConsonantsCount]: (locale: string) => createKeyComparator('consonantsCount', locale),
68
+ [ResultColumnId.Coordinates]: (locale: string, showCoordinates: ShowCoordinates) => (a, b) => {
69
+ const stringComparator = createStringComparator(locale);
70
+ const aValue = getCoordinates(a, showCoordinates);
71
+ const bValue = getCoordinates(b, showCoordinates);
72
+ return stringComparator(aValue, bValue);
73
+ },
74
+ [ResultColumnId.Points]: (locale: string) => createKeyComparator('points', locale),
75
+ [ResultColumnId.TilesCount]: (locale: string) => createKeyComparator('tilesCount', locale),
76
+ [ResultColumnId.VowelsCount]: (locale: string) => createKeyComparator('vowelsCount', locale),
77
+ [ResultColumnId.Word]: (locale: string) => createKeyComparator('word', locale),
78
+ [ResultColumnId.WordsCount]: (locale: string) => createKeyComparator('wordsCount', locale),
79
+ };
80
+
81
+ export const sortResults = (
82
+ results: Result[] | undefined,
83
+ sort: Sort,
84
+ locale: string,
85
+ showCoordinates: ShowCoordinates,
86
+ ): Result[] | undefined => {
87
+ if (typeof results === 'undefined') {
88
+ return undefined;
89
+ }
90
+
91
+ const createComparator = comparators[sort.column];
92
+ const comparator = createComparator(locale, showCoordinates);
93
+ const finalComparator = sort.direction === SortDirection.Descending ? reverseComparator(comparator) : comparator;
94
+ const sortedResults = [...results].sort(finalComparator);
95
+ return sortedResults;
96
+ };
@@ -0,0 +1,75 @@
1
+ import { createSelector } from '@reduxjs/toolkit';
2
+
3
+ import { createRegExp } from 'lib';
4
+
5
+ import { selectCellFilters } from '../cellFilters';
6
+ import { selectLocale, selectShowCoordinates } from '../settings';
7
+ import type { RootState } from '../types';
8
+
9
+ import { getCoordinates, groupResults, resultMatchesCellFilter, sortResults } from './lib';
10
+
11
+ const selectResultIndex = (_: unknown, index: number): number => index;
12
+
13
+ export const selectResults = (state: RootState) => state.results;
14
+
15
+ export const selectResultCandidate = createSelector([selectResults], (results) => results.candidate);
16
+
17
+ export const selectResultsQuery = createSelector([selectResults], (results) => results.query);
18
+
19
+ const selectResultsResults = createSelector([selectResults], (results) => results.results);
20
+
21
+ export const selectResultsSort = createSelector([selectResults], (results) => results.sort);
22
+
23
+ export const selectResultCandidateCells = createSelector(
24
+ [selectResultCandidate],
25
+ (resultCandidate) => resultCandidate?.cells ?? [],
26
+ );
27
+
28
+ export const selectResultCandidateTiles = createSelector(
29
+ [selectResultCandidate],
30
+ (resultCandidate) => resultCandidate?.tiles ?? [],
31
+ );
32
+
33
+ const selectSortedResults = createSelector(
34
+ [selectResultsResults, selectResultsSort, selectLocale, selectShowCoordinates],
35
+ sortResults,
36
+ );
37
+
38
+ const selectGroupedSortedResults = createSelector(
39
+ [selectSortedResults, selectResultsQuery, selectCellFilters],
40
+ groupResults,
41
+ );
42
+
43
+ export const selectProcessedResults = createSelector([selectGroupedSortedResults], (results) => {
44
+ return results ? [...results.matching, ...results.other] : undefined;
45
+ });
46
+
47
+ export const selectIsResultMatching = createSelector(
48
+ [selectProcessedResults, selectResultsQuery, selectCellFilters, selectResultIndex],
49
+ (results, query, cellFilters, index) => {
50
+ if (!results) {
51
+ return false;
52
+ }
53
+
54
+ const result = results[index];
55
+ const regExp = createRegExp(query);
56
+
57
+ if (!regExp.test(result.word)) {
58
+ return false;
59
+ }
60
+
61
+ return resultMatchesCellFilter(result, cellFilters);
62
+ },
63
+ );
64
+
65
+ export const selectResultCoordinates = createSelector(
66
+ [selectProcessedResults, selectShowCoordinates, selectResultIndex],
67
+ (results, showCoordinates, index) => {
68
+ if (!results) {
69
+ return '';
70
+ }
71
+
72
+ const result = results[index];
73
+ return getCoordinates(result, showCoordinates);
74
+ },
75
+ );
@@ -1,9 +1,9 @@
1
- import { createSlice, PayloadAction } from '@reduxjs/toolkit';
2
- import { Result } from '@scrabble-solver/types';
1
+ import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
2
+ import { type Result } from '@scrabble-solver/types';
3
3
 
4
- import { ResultColumnId, SortDirection } from 'types';
4
+ import { type ResultColumnId, SortDirection } from 'types';
5
5
 
6
- import { resultsInitialState } from './resultsInitialState';
6
+ import { resultsInitialState } from './initialState';
7
7
 
8
8
  const toggleDirection = (direction: SortDirection): SortDirection => {
9
9
  return direction === SortDirection.Ascending ? SortDirection.Descending : SortDirection.Ascending;
@@ -0,0 +1,10 @@
1
+ import { type Result } from '@scrabble-solver/types';
2
+
3
+ import type { Sort } from 'types';
4
+
5
+ export interface ResultsState {
6
+ candidate: Result | null;
7
+ query: string;
8
+ results: Result[] | undefined;
9
+ sort: Sort;
10
+ }