@scrabble-solver/scrabble-solver 2.15.11 → 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 (290) 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/974.js +1 -1
  24. package/.next/server/middleware-build-manifest.js +1 -1
  25. package/.next/server/pages/404.html +1 -1
  26. package/.next/server/pages/404.js.nft.json +1 -1
  27. package/.next/server/pages/500.html +1 -1
  28. package/.next/server/pages/_app.js +1 -1
  29. package/.next/server/pages/_app.js.nft.json +1 -1
  30. package/.next/server/pages/_error.js +1 -1
  31. package/.next/server/pages/_error.js.nft.json +1 -1
  32. package/.next/server/pages/api/solve.js +1 -1
  33. package/.next/server/pages/index.html +1 -1
  34. package/.next/server/pages/index.js +1 -1
  35. package/.next/server/pages/index.js.nft.json +1 -1
  36. package/.next/server/pages/index.json +1 -1
  37. package/.next/server/pages-manifest.json +1 -1
  38. package/.next/static/{47JHul8F9NSWCNSEuahuL → X6ny8arpUxpRCZ4OMm7Vo}/_buildManifest.js +1 -1
  39. package/.next/static/chunks/framework-57125a0cc6749ff9.js +1 -0
  40. package/.next/static/chunks/main-03618e8bd3cd04dd.js +1 -0
  41. package/.next/static/chunks/pages/{404-590e2a3839c1d9e0.js → 404-18b9f6f5faa91442.js} +1 -1
  42. package/.next/static/chunks/pages/_app-2378fe90e1762e8c.js +1 -0
  43. package/.next/static/chunks/pages/index-bfc599d9351773ae.js +1 -0
  44. package/.next/static/css/{6682db14f926d4c7.css → 04a3767982ec10e8.css} +1 -1
  45. package/.next/static/css/{d875648f38121a28.css → 1fae874a25934f54.css} +1 -1
  46. package/.next/trace +23 -23
  47. package/coverage/clover.xml +6 -0
  48. package/coverage/coverage-final.json +1 -0
  49. package/coverage/lcov-report/base.css +224 -0
  50. package/coverage/lcov-report/block-navigation.js +87 -0
  51. package/coverage/lcov-report/favicon.png +0 -0
  52. package/coverage/lcov-report/index.html +101 -0
  53. package/coverage/lcov-report/prettify.css +1 -0
  54. package/coverage/lcov-report/prettify.js +2 -0
  55. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  56. package/coverage/lcov-report/sorter.js +196 -0
  57. package/coverage/lcov.info +0 -0
  58. package/package.json +17 -17
  59. package/src/api/getServerLoggingData.ts +1 -1
  60. package/src/api/isBoardValid.ts +1 -1
  61. package/src/api/isCellValid.ts +1 -1
  62. package/src/api/isRowValid.ts +1 -1
  63. package/src/components/Alert/Alert.tsx +1 -1
  64. package/src/components/Badge/Badge.tsx +1 -1
  65. package/src/components/Board/Board.tsx +8 -8
  66. package/src/components/Board/BoardPure.tsx +11 -11
  67. package/src/components/Board/components/Actions/Actions.tsx +3 -3
  68. package/src/components/Board/components/Actions/lib.ts +3 -3
  69. package/src/components/Board/components/Cell/Cell.tsx +7 -7
  70. package/src/components/Board/components/InputPrompt/InputPrompt.tsx +2 -2
  71. package/src/components/Board/components/ToggleDirectionButton/ToggleDirectionButton.tsx +2 -2
  72. package/src/components/Board/hooks/useBackgroundImage.tsx +1 -1
  73. package/src/components/Board/hooks/useBoardStyle.ts +1 -1
  74. package/src/components/Board/hooks/useGrid.ts +13 -13
  75. package/src/components/Board/lib.ts +37 -0
  76. package/src/components/Board/selectors.ts +8 -0
  77. package/src/components/Button/Button.tsx +1 -1
  78. package/src/components/Button/Link.tsx +1 -1
  79. package/src/components/Dictionary/Dictionary.tsx +10 -3
  80. package/src/components/DictionaryInput/DictionaryInput.tsx +1 -1
  81. package/src/components/EmptyState/EmptyState.tsx +3 -3
  82. package/src/components/IconButton/IconButton.tsx +1 -1
  83. package/src/components/IconButton/Link.tsx +1 -1
  84. package/src/components/Key/Key.tsx +1 -1
  85. package/src/components/Keys/Arrows/Arrows.tsx +1 -1
  86. package/src/components/Keys/index.tsx +1 -1
  87. package/src/components/Loading/Loading.tsx +6 -8
  88. package/src/components/Logo/LogoBlueprint.tsx +1 -1
  89. package/src/components/Modal/Modal.tsx +4 -2
  90. package/src/components/Modal/components/Section/Section.tsx +1 -1
  91. package/src/components/NavButtons/NavButtons.tsx +4 -3
  92. package/src/components/NavButtons/selectors.ts +11 -0
  93. package/src/components/NotFound/NotFound.tsx +1 -1
  94. package/src/components/PlainTiles/PlainTiles.tsx +1 -1
  95. package/src/components/PlainTiles/Tile.tsx +1 -1
  96. package/src/components/PlainTiles/lib.ts +90 -0
  97. package/src/components/Progress/Progress.tsx +1 -1
  98. package/src/components/Rack/Rack.tsx +10 -26
  99. package/src/components/Rack/components/InputPrompt/InputPrompt.tsx +5 -8
  100. package/src/components/Rack/components/InputPrompt/lib.test.ts +27 -0
  101. package/src/components/Rack/components/InputPrompt/lib.ts +19 -0
  102. package/src/components/Rack/components/RackTile/RackTile.tsx +9 -9
  103. package/src/components/Rack/selectors.ts +9 -0
  104. package/src/components/Radio/Radio.tsx +1 -1
  105. package/src/components/Results/Cell.tsx +2 -2
  106. package/src/components/Results/Header.tsx +1 -1
  107. package/src/components/Results/HeaderButton.tsx +2 -2
  108. package/src/components/Results/Result.tsx +5 -6
  109. package/src/components/Results/Results.tsx +6 -6
  110. package/src/components/Results/SolveButton.tsx +3 -3
  111. package/src/components/Results/types.ts +2 -2
  112. package/src/components/ResultsInput/ResultsInput.tsx +1 -1
  113. package/src/components/SeoMessage/SeoMessage.tsx +1 -1
  114. package/src/components/Solver/Solver.tsx +4 -4
  115. package/src/components/Solver/components/InsertButton/InsertButton.tsx +1 -1
  116. package/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.tsx +5 -5
  117. package/src/components/Spinner/Spinner.tsx +1 -1
  118. package/src/components/Tile/Tile.tsx +7 -7
  119. package/src/components/Tile/TilePure.tsx +8 -8
  120. package/src/components/Tooltip/Tooltip.tsx +1 -1
  121. package/src/components/Tooltip/TooltipContent.tsx +1 -1
  122. package/src/components/Tooltip/TooltipTrigger.tsx +1 -1
  123. package/src/components/Tooltip/context.ts +1 -1
  124. package/src/components/Tooltip/useTooltip.ts +1 -1
  125. package/src/hooks/useAppLayout.ts +1 -1
  126. package/src/hooks/useColumns.ts +28 -1
  127. package/src/hooks/useEffectOnce.ts +1 -1
  128. package/src/hooks/useLocalStorage.ts +8 -0
  129. package/src/i18n/constants.ts +1 -1
  130. package/src/i18n/i18n.ts +1 -1
  131. package/src/i18n/languages/english.json +3 -0
  132. package/src/i18n/languages/french.json +3 -0
  133. package/src/i18n/languages/german.json +3 -0
  134. package/src/i18n/languages/persian.json +3 -0
  135. package/src/i18n/languages/polish.json +3 -0
  136. package/src/i18n/languages/romanian.json +3 -0
  137. package/src/i18n/languages/spanish.json +3 -0
  138. package/src/i18n/languages/turkish.json +3 -0
  139. package/src/lib/createComparator.ts +1 -1
  140. package/src/lib/createKeyComparator.ts +1 -1
  141. package/src/lib/createKeyboardNavigation.ts +1 -1
  142. package/src/lib/createStringComparator.ts +1 -1
  143. package/src/lib/extractCharacters.test.ts +42 -15
  144. package/src/lib/extractCharacters.ts +27 -25
  145. package/src/lib/findCell.ts +1 -1
  146. package/src/lib/index.ts +2 -17
  147. package/src/lib/isCtrl.ts +1 -1
  148. package/src/lib/localeTransliterate.test.ts +14 -0
  149. package/src/lib/localeTransliterate.ts +18 -0
  150. package/src/lib/numberComparator.ts +1 -1
  151. package/src/lib/reverseComparator.ts +1 -1
  152. package/src/lib/zipCharactersAndTiles.ts +2 -2
  153. package/src/modals/DictionaryModal/DictionaryModal.tsx +1 -1
  154. package/src/modals/KeyMapModal/KeyMapModal.tsx +1 -1
  155. package/src/modals/KeyMapModal/components/Mapping/Mapping.tsx +1 -1
  156. package/src/modals/MenuModal/MenuModal.tsx +1 -1
  157. package/src/modals/RemainingTilesModal/RemainingTilesModal.tsx +3 -2
  158. package/src/modals/RemainingTilesModal/components/Character/Character.tsx +2 -2
  159. package/src/{lib/getRemainingTilesGroups.ts → modals/RemainingTilesModal/lib.ts} +26 -9
  160. package/src/modals/RemainingTilesModal/selectors.ts +7 -0
  161. package/src/modals/ResultsModal/ResultsModal.tsx +4 -4
  162. package/src/modals/SettingsModal/SettingsModal.tsx +6 -1
  163. package/src/modals/SettingsModal/components/AutoGroupTilesSetting/AutoGroupTilesSetting.tsx +1 -1
  164. package/src/modals/SettingsModal/components/AutoGroupTilesSetting/lib.ts +1 -1
  165. package/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.tsx +1 -1
  166. package/src/modals/SettingsModal/components/ConfigSetting/lib.ts +1 -1
  167. package/src/modals/SettingsModal/components/InputModeSetting/InputModeSetting.tsx +1 -1
  168. package/src/modals/SettingsModal/components/InputModeSetting/lib.ts +1 -1
  169. package/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.tsx +2 -2
  170. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/RemoveCellFiltersSetting.module.scss +12 -0
  171. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/RemoveCellFiltersSetting.tsx +53 -0
  172. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/index.ts +1 -0
  173. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/lib.ts +13 -0
  174. package/src/modals/SettingsModal/components/ShowCoordinatesSetting/ShowCoordinatesSetting.tsx +2 -2
  175. package/src/modals/SettingsModal/components/index.ts +1 -0
  176. package/src/modals/WordsModal/WordsModal.tsx +4 -3
  177. package/src/pages/_app.tsx +2 -2
  178. package/src/pages/_document.tsx +1 -1
  179. package/src/pages/api/dictionary/[locale]/[word].ts +2 -2
  180. package/src/pages/api/dictionary/[locale]/index.ts +2 -2
  181. package/src/pages/api/solve.ts +11 -2
  182. package/src/pages/api/verify.ts +2 -2
  183. package/src/pages/api/visit.ts +1 -1
  184. package/src/pages/index.tsx +34 -43
  185. package/src/parameters/index.ts +1 -0
  186. package/src/sdk/findWordDefinitions.ts +1 -1
  187. package/src/sdk/getDictionary.ts +1 -1
  188. package/src/sdk/solve.ts +1 -1
  189. package/src/sdk/verify.ts +1 -1
  190. package/src/service-worker/dictionaries/getDictionary.ts +1 -1
  191. package/src/service-worker/dictionaries/getDictionaryUrl.ts +1 -1
  192. package/src/service-worker/dictionaries/revalidateDictionary.ts +1 -1
  193. package/src/service-worker/getTrie.ts +1 -1
  194. package/src/service-worker/routeSolveRequests.ts +2 -2
  195. package/src/service-worker/routeVerifyRequests.ts +1 -1
  196. package/src/state/board/index.ts +4 -0
  197. package/src/state/{slices/boardInitialState.ts → board/initialState.ts} +3 -6
  198. package/src/state/board/selectors.ts +3 -0
  199. package/src/state/{slices/boardSlice.ts → board/slice.ts} +5 -4
  200. package/src/state/board/types.ts +3 -0
  201. package/src/state/cellFilters/index.ts +4 -0
  202. package/src/state/cellFilters/initialState.ts +3 -0
  203. package/src/state/cellFilters/lib.ts +8 -0
  204. package/src/state/cellFilters/selectors.ts +13 -0
  205. package/src/state/{slices/cellFilterSlice.ts → cellFilters/slice.ts} +15 -14
  206. package/src/state/cellFilters/types.ts +3 -0
  207. package/src/state/dictionary/index.ts +4 -0
  208. package/src/state/dictionary/initialState.ts +8 -0
  209. package/src/state/dictionary/selectors.ts +16 -0
  210. package/src/state/{slices/dictionarySlice.ts → dictionary/slice.ts} +3 -3
  211. package/src/state/dictionary/types.ts +8 -0
  212. package/src/state/index.ts +12 -5
  213. package/src/{lib/getRemainingTiles.ts → state/lib.ts} +3 -4
  214. package/src/state/localStorage.ts +11 -2
  215. package/src/state/rack/index.ts +4 -0
  216. package/src/state/rack/initialState.ts +12 -0
  217. package/src/state/rack/selectors.ts +7 -0
  218. package/src/state/{slices/rackSlice.ts → rack/slice.ts} +4 -4
  219. package/src/state/rack/types.ts +3 -0
  220. package/src/state/results/index.ts +4 -0
  221. package/src/state/results/initialState.ts +13 -0
  222. package/src/state/results/lib.ts +96 -0
  223. package/src/state/results/selectors.ts +75 -0
  224. package/src/state/{slices/resultsSlice.ts → results/slice.ts} +4 -4
  225. package/src/state/results/types.ts +10 -0
  226. package/src/state/sagas.ts +22 -23
  227. package/src/state/selectors.ts +15 -235
  228. package/src/state/settings/index.ts +4 -0
  229. package/src/state/{slices/settingsInitialState.ts → settings/initialState.ts} +4 -11
  230. package/src/state/settings/lib.ts +42 -0
  231. package/src/state/settings/selectors.ts +69 -0
  232. package/src/state/{slices/settingsSlice.ts → settings/slice.ts} +9 -4
  233. package/src/state/settings/types.ts +12 -0
  234. package/src/state/solve/index.ts +4 -0
  235. package/src/state/solve/initialState.ts +12 -0
  236. package/src/state/solve/selectors.ts +14 -0
  237. package/src/state/{slices/solveSlice.ts → solve/slice.ts} +3 -3
  238. package/src/state/solve/types.ts +10 -0
  239. package/src/state/store.ts +9 -11
  240. package/src/state/types.ts +16 -18
  241. package/src/state/useTranslate.ts +2 -2
  242. package/src/state/useTypedSelector.ts +2 -2
  243. package/src/state/verify/index.ts +4 -0
  244. package/src/state/verify/initialState.ts +12 -0
  245. package/src/state/verify/selectors.ts +9 -0
  246. package/src/state/{slices/verifySlice.ts → verify/slice.ts} +3 -3
  247. package/src/state/verify/types.ts +10 -0
  248. package/src/styles/global.scss +5 -0
  249. package/src/types/api.ts +1 -1
  250. package/src/types/index.ts +8 -3
  251. package/tsconfig.tsbuildinfo +1 -1
  252. package/.eslintrc.js +0 -10
  253. package/.next/server/chunks/968.js +0 -1
  254. package/.next/static/chunks/framework-288d1abd95de88d9.js +0 -1
  255. package/.next/static/chunks/main-016492249b3393e2.js +0 -1
  256. package/.next/static/chunks/pages/_app-0e951de0aebb6505.js +0 -1
  257. package/.next/static/chunks/pages/index-c1d5a66d0f4794a6.js +0 -1
  258. package/src/components/Board/lib/getBonusColor.ts +0 -16
  259. package/src/components/Board/lib/getPositionInGrid.ts +0 -13
  260. package/src/components/Board/lib/index.ts +0 -2
  261. package/src/components/PlainTiles/lib/createPlainTile.ts +0 -41
  262. package/src/components/PlainTiles/lib/createPlainTiles.ts +0 -25
  263. package/src/components/PlainTiles/lib/getViewbox.ts +0 -17
  264. package/src/components/PlainTiles/lib/getX.ts +0 -5
  265. package/src/components/PlainTiles/lib/getY.ts +0 -5
  266. package/src/components/PlainTiles/lib/index.ts +0 -6
  267. package/src/components/PlainTiles/lib/randomize.ts +0 -1
  268. package/src/lib/createArray.ts +0 -1
  269. package/src/lib/createGridOf.ts +0 -9
  270. package/src/lib/detectLocale.ts +0 -27
  271. package/src/lib/extractCharactersByCase.test.ts +0 -29
  272. package/src/lib/extractCharactersByCase.ts +0 -29
  273. package/src/lib/getCellSize.ts +0 -10
  274. package/src/lib/getCoordinates.ts +0 -16
  275. package/src/lib/getRemainingTilesCount.ts +0 -11
  276. package/src/lib/getTotalRemainingTilesCount.ts +0 -11
  277. package/src/lib/groupResults.ts +0 -35
  278. package/src/lib/guessLocale.ts +0 -20
  279. package/src/lib/isUpperCase.ts +0 -5
  280. package/src/lib/resultMatchesCellFilter.ts +0 -21
  281. package/src/lib/sortGroupedResults.ts +0 -21
  282. package/src/lib/sortResults.ts +0 -41
  283. package/src/state/slices/cellFilterInitialState.ts +0 -5
  284. package/src/state/slices/dictionaryInitialState.ts +0 -15
  285. package/src/state/slices/index.ts +0 -16
  286. package/src/state/slices/rackInitialState.ts +0 -9
  287. package/src/state/slices/resultsInitialState.ts +0 -20
  288. package/src/state/slices/solveInitialState.ts +0 -21
  289. package/src/state/slices/verifyInitialState.ts +0 -19
  290. /package/.next/static/{47JHul8F9NSWCNSEuahuL → X6ny8arpUxpRCZ4OMm7Vo}/_ssgManifest.js +0 -0
@@ -1,5 +1,5 @@
1
1
  import { FloatingArrow, FloatingPortal, useDelayGroup, useMergeRefs, useTransitionStyles } from '@floating-ui/react';
2
- import { forwardRef, HTMLProps } from 'react';
2
+ import { forwardRef, type HTMLProps } from 'react';
3
3
 
4
4
  import { TOOLTIP_DURATION } from 'parameters';
5
5
 
@@ -1,6 +1,6 @@
1
1
  import { useMergeRefs } from '@floating-ui/react';
2
2
  import { isObject } from '@scrabble-solver/types';
3
- import { HTMLProps, ReactElement, RefObject, cloneElement, forwardRef, isValidElement } from 'react';
3
+ import { type HTMLProps, type ReactElement, type RefObject, cloneElement, forwardRef, isValidElement } from 'react';
4
4
 
5
5
  import { useTooltipContext } from './context';
6
6
 
@@ -1,6 +1,6 @@
1
1
  import { createContext, useContext } from 'react';
2
2
 
3
- import { useTooltip } from './useTooltip';
3
+ import { type useTooltip } from './useTooltip';
4
4
 
5
5
  type TooltipContextType = ReturnType<typeof useTooltip> | null;
6
6
 
@@ -1,5 +1,5 @@
1
1
  import {
2
- Placement,
2
+ type Placement,
3
3
  arrow,
4
4
  autoUpdate,
5
5
  flip,
@@ -20,7 +20,7 @@ import {
20
20
  TEXT_INPUT_HEIGHT,
21
21
  } from 'parameters';
22
22
  import { selectConfig, selectShowCoordinates, useTypedSelector } from 'state';
23
- import { ResultColumnId } from 'types';
23
+ import { type ResultColumnId } from 'types';
24
24
 
25
25
  import { useColumns } from './useColumns';
26
26
  import { useIsTouchDevice } from './useIsTouchDevice';
@@ -1,6 +1,8 @@
1
+ import { createSelector } from '@reduxjs/toolkit';
1
2
  import { useMemo } from 'react';
2
3
 
3
- import { selectColumns, useTypedSelector } from 'state';
4
+ import { LOCALE_FEATURES } from 'i18n';
5
+ import { selectLocale, selectShowCoordinates, useTypedSelector } from 'state';
4
6
  import { ResultColumnId } from 'types';
5
7
 
6
8
  import { useMediaQueries } from './useMediaQueries';
@@ -13,6 +15,31 @@ const COLUMNS_M = [...COLUMNS_XS];
13
15
 
14
16
  const COLUMNS_L = [...COLUMNS_XS];
15
17
 
18
+ const selectColumns = createSelector([selectLocale, selectShowCoordinates], (locale, showCoordinates) => {
19
+ const { consonants, vowels } = LOCALE_FEATURES[locale];
20
+ const columns: ResultColumnId[] = [
21
+ ResultColumnId.Word,
22
+ ResultColumnId.TilesCount,
23
+ ResultColumnId.BlanksCount,
24
+ ResultColumnId.WordsCount,
25
+ ResultColumnId.Points,
26
+ ];
27
+
28
+ if (showCoordinates !== 'hidden') {
29
+ columns.push(ResultColumnId.Coordinates);
30
+ }
31
+
32
+ if (vowels) {
33
+ columns.push(ResultColumnId.VowelsCount);
34
+ }
35
+
36
+ if (consonants) {
37
+ columns.push(ResultColumnId.ConsonantsCount);
38
+ }
39
+
40
+ return columns;
41
+ });
42
+
16
43
  export const useColumns = (): Partial<Record<ResultColumnId, boolean>> => {
17
44
  const columns = useTypedSelector(selectColumns);
18
45
  const { isLessThanXs, isLessThanS, isLessThanM, isLessThanL } = useMediaQueries();
@@ -1,4 +1,4 @@
1
- import { EffectCallback, useEffect } from 'react';
1
+ import { type EffectCallback, useEffect } from 'react';
2
2
 
3
3
  import { useLatest } from './useLatest';
4
4
 
@@ -9,6 +9,7 @@ import {
9
9
  selectLocale,
10
10
  selectRack,
11
11
  selectShowCoordinates,
12
+ selectRemoveCellFilters,
12
13
  useTypedSelector,
13
14
  } from 'state';
14
15
 
@@ -20,6 +21,7 @@ export const useLocalStorage = () => {
20
21
  const locale = useTypedSelector(selectLocale);
21
22
  const rack = useTypedSelector(selectRack);
22
23
  const showCoordinates = useTypedSelector(selectShowCoordinates);
24
+ const removeCellFilters = useTypedSelector(selectRemoveCellFilters);
23
25
 
24
26
  useEffect(() => {
25
27
  if (autoGroupTiles) {
@@ -62,4 +64,10 @@ export const useLocalStorage = () => {
62
64
  localStorage.setShowCoordinates(showCoordinates);
63
65
  }
64
66
  }, [showCoordinates]);
67
+
68
+ useEffect(() => {
69
+ if (removeCellFilters) {
70
+ localStorage.setRemoveCellFilters(removeCellFilters);
71
+ }
72
+ }, [removeCellFilters]);
65
73
  };
@@ -1,6 +1,6 @@
1
1
  import { COMMA_ARABIC, COMMA_LATIN } from '@scrabble-solver/constants';
2
2
  import { Locale } from '@scrabble-solver/types';
3
- import { FunctionComponent, SVGAttributes } from 'react';
3
+ import { type FunctionComponent, type SVGAttributes } from 'react';
4
4
 
5
5
  import { FlagDe, FlagEs, FlagFa, FlagFr, FlagGb, FlagPl, FlagRo, FlagTr, FlagUs } from 'icons';
6
6
 
package/src/i18n/i18n.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Locale } from '@scrabble-solver/types';
2
2
 
3
- import { Translations } from 'types';
3
+ import { type Translations } from 'types';
4
4
 
5
5
  import english from './languages/english.json';
6
6
  import french from './languages/french.json';
@@ -68,6 +68,9 @@
68
68
  "settings.inputMode.keyboard": "Keyboard",
69
69
  "settings.inputMode.touchscreen": "Touchscreen",
70
70
  "settings.language": "Language",
71
+ "settings.removeCellFilters": "Automatically remove filters from board",
72
+ "settings.removeCellFilters.always": "Always",
73
+ "settings.removeCellFilters.never": "Never",
71
74
  "settings.showCoordinates": "Coordinates",
72
75
  "settings.showCoordinates.alternative": "Alternative",
73
76
  "settings.showCoordinates.hidden": "Hidden",
@@ -68,6 +68,9 @@
68
68
  "settings.inputMode.keyboard": "Clavier",
69
69
  "settings.inputMode.touchscreen": "Écran tactile",
70
70
  "settings.language": "Langue",
71
+ "settings.removeCellFilters": "Supprimer automatiquement les filtres du plateau",
72
+ "settings.removeCellFilters.always": "Toujours",
73
+ "settings.removeCellFilters.never": "Jamais",
71
74
  "settings.showCoordinates": "Coordonnés",
72
75
  "settings.showCoordinates.alternative": "Alternative",
73
76
  "settings.showCoordinates.hidden": "Caché",
@@ -68,6 +68,9 @@
68
68
  "settings.inputMode.keyboard": "Tastatur",
69
69
  "settings.inputMode.touchscreen": "Touchscreen",
70
70
  "settings.language": "Sprache",
71
+ "settings.removeCellFilters": "Filter automatisch vom Spielbrett entfernen",
72
+ "settings.removeCellFilters.always": "Immer",
73
+ "settings.removeCellFilters.never": "Nie",
71
74
  "settings.showCoordinates": "Koordinaten",
72
75
  "settings.showCoordinates.alternative": "Alternative",
73
76
  "settings.showCoordinates.hidden": "Versteckt",
@@ -68,6 +68,9 @@
68
68
  "settings.inputMode.keyboard": "صفحه کلید",
69
69
  "settings.inputMode.touchscreen": "صفحه لمسی",
70
70
  "settings.language": "زبان",
71
+ "settings.removeCellFilters": "فیلترها را به‌صورت خودکار از صفحه بازی حذف کن",
72
+ "settings.removeCellFilters.always": "همیشه",
73
+ "settings.removeCellFilters.never": "هرگز",
71
74
  "settings.showCoordinates": "مختصات",
72
75
  "settings.showCoordinates.alternative": "بديل",
73
76
  "settings.showCoordinates.hidden": "مختفي",
@@ -68,6 +68,9 @@
68
68
  "settings.inputMode.keyboard": "Klawiatura",
69
69
  "settings.inputMode.touchscreen": "Ekran dotykowy",
70
70
  "settings.language": "Język",
71
+ "settings.removeCellFilters": "Automatycznie usuwaj filtry z planszy",
72
+ "settings.removeCellFilters.always": "Zawsze",
73
+ "settings.removeCellFilters.never": "Nigdy",
71
74
  "settings.showCoordinates": "Współrzędne",
72
75
  "settings.showCoordinates.alternative": "Alternatywne",
73
76
  "settings.showCoordinates.hidden": "Ukryte",
@@ -68,6 +68,9 @@
68
68
  "settings.inputMode.keyboard": "Tastatura",
69
69
  "settings.inputMode.touchscreen": "Ecran",
70
70
  "settings.language": "Limba",
71
+ "settings.removeCellFilters": "Elimină automat filtrele de pe tablă",
72
+ "settings.removeCellFilters.always": "Întotdeauna",
73
+ "settings.removeCellFilters.never": "Niciodată",
71
74
  "settings.showCoordinates": "Coordonate",
72
75
  "settings.showCoordinates.alternative": "Alternativă",
73
76
  "settings.showCoordinates.hidden": "Ascuns",
@@ -68,6 +68,9 @@
68
68
  "settings.inputMode.keyboard": "Teclado",
69
69
  "settings.inputMode.touchscreen": "Pantalla táctil",
70
70
  "settings.language": "Idioma",
71
+ "settings.removeCellFilters": "Eliminar automáticamente los filtros del tablero",
72
+ "settings.removeCellFilters.always": "Siempre",
73
+ "settings.removeCellFilters.never": "Nunca",
71
74
  "settings.showCoordinates": "Coordenadas",
72
75
  "settings.showCoordinates.alternative": "Alternativa",
73
76
  "settings.showCoordinates.hidden": "Oculto",
@@ -68,6 +68,9 @@
68
68
  "settings.inputMode.keyboard": "Klavye",
69
69
  "settings.inputMode.touchscreen": "Dokunmatik ekran",
70
70
  "settings.language": "Dil",
71
+ "settings.removeCellFilters": "Tahtadan filtreleri otomatik olarak kaldır",
72
+ "settings.removeCellFilters.always": "Her zaman",
73
+ "settings.removeCellFilters.never": "Asla",
71
74
  "settings.showCoordinates": "Koordinatlar",
72
75
  "settings.showCoordinates.alternative": "Alternatif",
73
76
  "settings.showCoordinates.hidden": "Gizlenmiş",
@@ -1,4 +1,4 @@
1
- import { Comparator } from 'types';
1
+ import type { Comparator } from 'types';
2
2
 
3
3
  import { createStringComparator } from './createStringComparator';
4
4
  import { numberComparator } from './numberComparator';
@@ -1,4 +1,4 @@
1
- import { Comparator } from 'types';
1
+ import { type Comparator } from 'types';
2
2
 
3
3
  import { createStringComparator } from './createStringComparator';
4
4
  import { numberComparator } from './numberComparator';
@@ -1,4 +1,4 @@
1
- import { KeyboardEventHandler } from 'react';
1
+ import { type KeyboardEventHandler } from 'react';
2
2
 
3
3
  import { noop } from './noop';
4
4
 
@@ -1,4 +1,4 @@
1
- import { Comparator } from 'types';
1
+ import { type Comparator } from 'types';
2
2
 
3
3
  export const createStringComparator: (locale: string) => Comparator<string> = (locale) => {
4
4
  return (a, b) => {
@@ -4,22 +4,49 @@ import { Game, Locale } from '@scrabble-solver/types';
4
4
 
5
5
  import { extractCharacters } from './extractCharacters';
6
6
 
7
- const tests = [
8
- { input: 'ab ', expected: ['a', 'b', BLANK] },
9
- { input: 'śćźa', expected: ['s', 'c', 'z', 'a'] },
10
- { input: 'bañó', expected: ['b', 'a', 'ñ', 'o'] },
11
- { input: 'bueno', expected: ['b', 'u', 'e', 'n', 'o'] },
12
- { input: 'bellas', expected: ['b', 'e', 'll', 'a', 's'] },
13
- { input: 'BELLAS', expected: ['b', 'e', 'll', 'a', 's'] },
14
- { input: 'churro', expected: ['ch', 'u', 'rr', 'o'] },
15
- { input: 'challulla', expected: ['ch', 'a', 'll', 'u', 'll', 'a'] },
16
- ];
7
+ describe('upperCaseDigraphsOnly = false', () => {
8
+ describe('extractCharacters', () => {
9
+ const locale = Locale.ES_ES;
10
+ const config = getConfig(Game.Scrabble, locale);
17
11
 
18
- describe('extractCharacters', () => {
19
- const locale = Locale.ES_ES;
20
- const config = getConfig(Game.Scrabble, locale);
12
+ it.each([
13
+ { input: 'ab ', expected: ['a', 'b', BLANK] },
14
+ { input: 'śćźa', expected: ['s', 'c', 'z', 'a'] },
15
+ { input: 'bañó', expected: ['b', 'a', 'ñ', 'o'] },
16
+ { input: 'bueno', expected: ['b', 'u', 'e', 'n', 'o'] },
17
+ { input: 'bellas', expected: ['b', 'e', 'll', 'a', 's'] },
18
+ { input: 'BELLAS', expected: ['b', 'e', 'll', 'a', 's'] },
19
+ { input: 'churro', expected: ['ch', 'u', 'rr', 'o'] },
20
+ { input: 'challulla', expected: ['ch', 'a', 'll', 'u', 'll', 'a'] },
21
+ ])(`[${locale}] "$input"`, ({ input, expected }) => {
22
+ expect(extractCharacters(config, input)).toEqual(expected);
23
+ });
24
+ });
25
+
26
+ describe('upperCaseDigraphsOnly = true', () => {
27
+ const locale = Locale.ES_ES;
28
+ const config = getConfig(Game.Scrabble, locale);
21
29
 
22
- it.each(tests)(`[${locale}] "$input"`, ({ input, expected }) => {
23
- expect(extractCharacters(config, input)).toEqual(expected);
30
+ it.each([
31
+ { input: 'ab ', expected: ['a', 'b', BLANK] },
32
+ { input: 'śćźa', expected: ['s', 'c', 'z', 'a'] },
33
+ { input: 'bañó', expected: ['b', 'a', 'ñ', 'o'] },
34
+ { input: 'bueno', expected: ['b', 'u', 'e', 'n', 'o'] },
35
+ { input: 'bellas', expected: ['b', 'e', 'l', 'l', 'a', 's'] },
36
+ { input: 'churro', expected: ['c', 'h', 'u', 'r', 'r', 'o'] },
37
+ { input: 'challulla', expected: ['c', 'h', 'a', 'l', 'l', 'u', 'l', 'l', 'a'] },
38
+ { input: 'beLlas', expected: ['b', 'e', 'l', 'l', 'a', 's'] },
39
+ { input: 'belLas', expected: ['b', 'e', 'l', 'l', 'a', 's'] },
40
+ { input: 'beLLas', expected: ['b', 'e', 'll', 'a', 's'] },
41
+ { input: 'chuRRo', expected: ['c', 'h', 'u', 'rr', 'o'] },
42
+ { input: 'CHuRRo', expected: ['ch', 'u', 'rr', 'o'] },
43
+ { input: 'CHaLLuLLa', expected: ['ch', 'a', 'll', 'u', 'll', 'a'] },
44
+ ])(`[${locale}] "$input"`, ({ input, expected }) => {
45
+ expect(
46
+ extractCharacters(config, input, {
47
+ upperCaseDigraphsOnly: true,
48
+ }),
49
+ ).toEqual(expected);
50
+ });
24
51
  });
25
52
  });
@@ -1,35 +1,33 @@
1
1
  import { BLANK } from '@scrabble-solver/constants';
2
- import { Config, Locale } from '@scrabble-solver/types';
3
- import { transliterate } from 'transliteration';
4
-
5
- const transliteratePerLocale: Record<Locale, (word: string) => string> = {
6
- [Locale.DE_DE]: (word) => word,
7
- [Locale.EN_GB]: (word) => word,
8
- [Locale.EN_US]: (word) => word,
9
- [Locale.ES_ES]: (word) => transliterate(word, { ignore: ['ñ'] }),
10
- [Locale.FA_IR]: (word) => word,
11
- [Locale.FR_FR]: (word) => transliterate(word),
12
- [Locale.PL_PL]: (word) => word,
13
- [Locale.RO_RO]: (word) => transliterate(word),
14
- [Locale.TR_TR]: (word) => word,
15
- };
2
+ import { type Config, type Locale } from '@scrabble-solver/types';
3
+
4
+ import { localeTransliterate } from './localeTransliterate';
5
+
6
+ interface Options {
7
+ upperCaseDigraphsOnly?: boolean;
8
+ }
16
9
 
17
- export const extractCharacters = (config: Config, value: string): string[] => {
10
+ export const extractCharacters = (config: Config, value: string, options?: Options): string[] => {
18
11
  let index = 0;
19
12
  const characters: string[] = [];
20
- const localeTransliterate = transliteratePerLocale[config.locale];
21
- const valueLowercase = localeTransliterate(value.toLocaleLowerCase(config.locale));
13
+ const finalValue = localeTransliterate(config.locale, value);
22
14
 
23
- while (index < valueLowercase.length) {
24
- const character = valueLowercase[index];
25
- const nextCharacter = valueLowercase[index + 1];
15
+ while (index < finalValue.length) {
16
+ const character = finalValue[index];
17
+ const characterLowercase = character.toLocaleLowerCase(config.locale);
18
+ const nextCharacter = finalValue[index + 1];
26
19
  const digraph = `${character}${nextCharacter}`;
20
+ const digraphLowercase = digraph.toLocaleLowerCase(config.locale);
27
21
 
28
- if (config.twoCharacterTiles.includes(digraph)) {
29
- characters.push(digraph);
30
- index += digraph.length;
31
- } else if (config.hasCharacter(character) || character === BLANK) {
32
- characters.push(character);
22
+ const isValidDigraph = options?.upperCaseDigraphsOnly
23
+ ? config.twoCharacterTiles.includes(digraphLowercase) && isUpperCase(config.locale, digraph)
24
+ : config.twoCharacterTiles.includes(digraphLowercase);
25
+
26
+ if (isValidDigraph) {
27
+ characters.push(digraphLowercase);
28
+ index += digraphLowercase.length;
29
+ } else if (config.hasCharacter(characterLowercase) || characterLowercase === BLANK) {
30
+ characters.push(characterLowercase);
33
31
  ++index;
34
32
  } else {
35
33
  ++index;
@@ -38,3 +36,7 @@ export const extractCharacters = (config: Config, value: string): string[] => {
38
36
 
39
37
  return characters;
40
38
  };
39
+
40
+ const isUpperCase = (locale: Locale, value: string): boolean => {
41
+ return value === value.toLocaleUpperCase(locale);
42
+ };
@@ -1,4 +1,4 @@
1
- import { Cell } from '@scrabble-solver/types';
1
+ import { type Cell } from '@scrabble-solver/types';
2
2
 
3
3
  export const findCell = (cells: Cell[], x: number, y: number): Cell | undefined => {
4
4
  return cells.find((cell) => cell.x === x && cell.y === y);
package/src/lib/index.ts CHANGED
@@ -1,39 +1,24 @@
1
1
  export { arrayEquals } from './arrayEquals';
2
- export { createArray } from './createArray';
3
2
  export { createComparator } from './createComparator';
4
- export { createGridOf } from './createGridOf';
5
- export { createKeyComparator } from './createKeyComparator';
6
3
  export { createKeyboardNavigation } from './createKeyboardNavigation';
4
+ export { createKeyComparator } from './createKeyComparator';
7
5
  export { createNullMovingComparator } from './createNullMovingComparator';
8
6
  export { createRegExp } from './createRegExp';
9
7
  export { createStringComparator } from './createStringComparator';
10
- export { detectLocale } from './detectLocale';
11
8
  export { extractCharacters } from './extractCharacters';
12
- export { extractCharactersByCase } from './extractCharactersByCase';
13
9
  export { extractInputValue } from './extractInputValue';
14
10
  export { findCell } from './findCell';
15
- export { getCellSize } from './getCellSize';
16
11
  export { getCoordinate } from './getCoordinate';
17
- export { getCoordinates } from './getCoordinates';
18
- export { getRemainingTiles } from './getRemainingTiles';
19
- export { getRemainingTilesCount } from './getRemainingTilesCount';
20
- export { getRemainingTilesGroups } from './getRemainingTilesGroups';
21
12
  export { getTileSizes } from './getTileSizes';
22
- export { getTotalRemainingTilesCount } from './getTotalRemainingTilesCount';
23
- export { groupResults } from './groupResults';
24
- export { guessLocale } from './guessLocale';
25
13
  export { inverseDirection } from './inverseDirection';
26
14
  export { isCtrl } from './isCtrl';
27
15
  export { isMac } from './isMac';
28
16
  export { isRegExp } from './isRegExp';
29
17
  export { isStringArray } from './isStringArray';
30
- export { isUpperCase } from './isUpperCase';
18
+ export { localeTransliterate } from './localeTransliterate';
31
19
  export { memoize } from './memoize';
32
20
  export { noop } from './noop';
33
21
  export { numberComparator } from './numberComparator';
34
- export { resultMatchesCellFilter } from './resultMatchesCellFilter';
35
22
  export { reverseComparator } from './reverseComparator';
36
- export { sortGroupedResults } from './sortGroupedResults';
37
- export { sortResults } from './sortResults';
38
23
  export { unorderedArraysEqual } from './unorderedArraysEqual';
39
24
  export { zipCharactersAndTiles } from './zipCharactersAndTiles';
package/src/lib/isCtrl.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { KeyboardEvent } from 'react';
1
+ import { type KeyboardEvent } from 'react';
2
2
 
3
3
  export const isCtrl = <T>(event: KeyboardEvent<T> | globalThis.KeyboardEvent): boolean => {
4
4
  return event.ctrlKey || event.metaKey;
@@ -0,0 +1,14 @@
1
+ import { Locale } from '@scrabble-solver/types';
2
+
3
+ import { localeTransliterate } from './localeTransliterate';
4
+
5
+ describe('localeTransliterate', () => {
6
+ it.each([
7
+ { locale: Locale.ES_ES, word: 'bañó', expected: 'baño' },
8
+ { locale: Locale.FR_FR, word: 'très', expected: 'tres' },
9
+ { locale: Locale.PL_PL, word: 'źdźbło', expected: 'źdźbło' },
10
+ { locale: Locale.RO_RO, word: 'mămăligă', expected: 'mamaliga' },
11
+ ])(`[$locale] "$word"`, ({ locale, word, expected }) => {
12
+ expect(localeTransliterate(locale, word)).toEqual(expected);
13
+ });
14
+ });
@@ -0,0 +1,18 @@
1
+ import { Locale } from '@scrabble-solver/types';
2
+ import { transliterate } from 'transliteration';
3
+
4
+ const transliteratePerLocale: Record<Locale, (word: string) => string> = {
5
+ [Locale.DE_DE]: (word) => word,
6
+ [Locale.EN_GB]: (word) => word,
7
+ [Locale.EN_US]: (word) => word,
8
+ [Locale.ES_ES]: (word) => transliterate(word, { ignore: ['ñ', 'Ñ'] }),
9
+ [Locale.FA_IR]: (word) => word,
10
+ [Locale.FR_FR]: (word) => transliterate(word),
11
+ [Locale.PL_PL]: (word) => word,
12
+ [Locale.RO_RO]: (word) => transliterate(word),
13
+ [Locale.TR_TR]: (word) => word,
14
+ };
15
+
16
+ export const localeTransliterate = (locale: Locale, value: string): string => {
17
+ return transliteratePerLocale[locale](value);
18
+ };
@@ -1,3 +1,3 @@
1
- import { Comparator } from 'types';
1
+ import { type Comparator } from 'types';
2
2
 
3
3
  export const numberComparator: Comparator<number> = (a, b) => a - b;
@@ -1,4 +1,4 @@
1
- import { Comparator } from 'types';
1
+ import { type Comparator } from 'types';
2
2
 
3
3
  export const reverseComparator = <T>(comparator: Comparator<T>): Comparator<T> => {
4
4
  return (a: T, b: T): number => -comparator(a, b);
@@ -1,7 +1,7 @@
1
1
  import { BLANK } from '@scrabble-solver/constants';
2
- import { Tile } from '@scrabble-solver/types';
2
+ import { type Tile } from '@scrabble-solver/types';
3
3
 
4
- import { Rack } from 'types';
4
+ import { type Rack } from 'types';
5
5
 
6
6
  interface CharacterTilePair {
7
7
  character: string | null;
@@ -1,4 +1,4 @@
1
- import { FunctionComponent, memo } from 'react';
1
+ import { type FunctionComponent, memo } from 'react';
2
2
 
3
3
  import { Dictionary, DictionaryInput, Modal } from 'components';
4
4
  import { useTranslate } from 'state';
@@ -1,4 +1,4 @@
1
- import { FunctionComponent, memo } from 'react';
1
+ import { type FunctionComponent, memo } from 'react';
2
2
 
3
3
  import { Arrows, Backspace, Ctrl, Del, Enter, Key, Modal, Space } from 'components';
4
4
  import { selectConfig, useTranslate, useTypedSelector } from 'state';
@@ -1,5 +1,5 @@
1
1
  import classNames from 'classnames';
2
- import { Fragment, FunctionComponent, ReactNode } from 'react';
2
+ import { Fragment, type FunctionComponent, type ReactNode } from 'react';
3
3
 
4
4
  import styles from './Mapping.module.scss';
5
5
 
@@ -1,4 +1,4 @@
1
- import { FunctionComponent, memo } from 'react';
1
+ import { type FunctionComponent, memo } from 'react';
2
2
 
3
3
  import { Button, Modal } from 'components';
4
4
  import { LOCALE_FEATURES } from 'i18n';
@@ -1,13 +1,14 @@
1
- import { FunctionComponent, memo } from 'react';
1
+ import { type FunctionComponent, memo } from 'react';
2
2
 
3
3
  import { Badge, Modal } from 'components';
4
4
  import { LOCALE_FEATURES } from 'i18n';
5
5
  import { getTileSizes } from 'lib';
6
6
  import { REMAINING_TILES_TILE_SIZE } from 'parameters';
7
- import { selectLocale, selectRemainingTilesGroups, useTranslate, useTypedSelector } from 'state';
7
+ import { selectLocale, useTranslate, useTypedSelector } from 'state';
8
8
 
9
9
  import { Character } from './components';
10
10
  import styles from './RemainingTilesModal.module.scss';
11
+ import { selectRemainingTilesGroups } from './selectors';
11
12
 
12
13
  interface Props {
13
14
  className?: string;
@@ -1,12 +1,12 @@
1
1
  import { BLANK } from '@scrabble-solver/constants';
2
2
  import classNames from 'classnames';
3
- import { FunctionComponent } from 'react';
3
+ import { type FunctionComponent } from 'react';
4
4
 
5
5
  import { Progress, Tile } from 'components';
6
6
  import { LOCALE_FEATURES } from 'i18n';
7
7
  import { REMAINING_TILES_TILE_SIZE } from 'parameters';
8
8
  import { selectCharacterPoints, selectLocale, useTypedSelector } from 'state';
9
- import { RemainingTile } from 'types';
9
+ import { type RemainingTile } from 'types';
10
10
 
11
11
  import styles from './Character.module.scss';
12
12