scrabble-solver 2.15.23 → 2.15.25

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 (195) hide show
  1. package/.claude/settings.local.json +28 -1
  2. package/.github/workflows/oxfmt.yml +20 -0
  3. package/.github/workflows/{eslint.yml → oxlint.yml} +2 -2
  4. package/.nx/workspace-data/file-map.json +1369 -1365
  5. package/.nx/workspace-data/lockfile-dependencies.hash +1 -1
  6. package/.nx/workspace-data/lockfile-nodes.hash +1 -1
  7. package/.nx/workspace-data/nx_files.nxt +0 -0
  8. package/.nx/workspace-data/parsed-lock-file.dependencies.json +442 -502
  9. package/.nx/workspace-data/parsed-lock-file.nodes.json +854 -577
  10. package/.nx/workspace-data/project-graph.json +1257 -1125
  11. package/.oxfmtrc.json +17 -0
  12. package/.oxlintrc.json +316 -0
  13. package/README.md +6 -3
  14. package/cypress/e2e/bugs/401-board-state-on-game-change.ts +36 -0
  15. package/cypress/e2e/bugs.spec.cy.ts +1 -0
  16. package/jest.config.js +5 -0
  17. package/lerna.json +1 -1
  18. package/package.json +14 -23
  19. package/packages/configs/build/games/literaki.d.ts +1 -1
  20. package/packages/configs/package.json +4 -4
  21. package/packages/constants/package.json +2 -2
  22. package/packages/dictionaries/package.json +5 -5
  23. package/packages/logger/package.json +2 -2
  24. package/packages/scrabble-solver/.next/BUILD_ID +1 -1
  25. package/packages/scrabble-solver/.next/build-manifest.json +8 -8
  26. package/packages/scrabble-solver/.next/cache/.previewinfo +1 -1
  27. package/packages/scrabble-solver/.next/cache/.rscinfo +1 -1
  28. package/packages/scrabble-solver/.next/cache/.tsbuildinfo +1 -1
  29. package/packages/scrabble-solver/.next/cache/webpack/client-production/0.pack +0 -0
  30. package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack +0 -0
  31. package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack.old +0 -0
  32. package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack +0 -0
  33. package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack.old +0 -0
  34. package/packages/scrabble-solver/.next/cache/webpack/server-production/0.pack +0 -0
  35. package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack +0 -0
  36. package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack.old +0 -0
  37. package/packages/scrabble-solver/.next/diagnostics/framework.json +1 -1
  38. package/packages/scrabble-solver/.next/prerender-manifest.json +4 -4
  39. package/packages/scrabble-solver/.next/routes-manifest.json +1 -1
  40. package/packages/scrabble-solver/.next/server/chunks/30.js +1 -1
  41. package/packages/scrabble-solver/.next/server/chunks/712.js +1 -1
  42. package/packages/scrabble-solver/.next/server/middleware-build-manifest.js +1 -1
  43. package/packages/scrabble-solver/.next/server/pages/404.html +1 -1
  44. package/packages/scrabble-solver/.next/server/pages/500.html +1 -1
  45. package/packages/scrabble-solver/.next/server/pages/index.html +1 -1
  46. package/packages/scrabble-solver/.next/server/pages/index.js +1 -1
  47. package/packages/scrabble-solver/.next/server/pages/index.json +1 -1
  48. package/packages/scrabble-solver/.next/server/pages/not-found.html +1 -1
  49. package/packages/scrabble-solver/.next/static/{zFnoNsMXUha-MKjuZn6AN → FDUqldlsD7FXe6iWhIJmu}/_buildManifest.js +1 -1
  50. package/packages/scrabble-solver/.next/static/chunks/{main-ca07941c8a544c9a.js → main-65a5015b46ca9827.js} +1 -1
  51. package/packages/scrabble-solver/.next/static/chunks/pages/{_app-a3061a79f91b3796.js → _app-c0932b8ca24945cb.js} +5 -5
  52. package/packages/scrabble-solver/.next/static/chunks/pages/{index-6c5b582e7afc063c.js → index-08b3b0a754095919.js} +1 -1
  53. package/packages/scrabble-solver/.next/trace +21 -21
  54. package/packages/scrabble-solver/.next/trace-build +1 -1
  55. package/packages/scrabble-solver/package.json +10 -10
  56. package/packages/scrabble-solver/public/service-worker.js +1 -1
  57. package/packages/scrabble-solver/src/app-layout/useAppLayoutValue.ts +4 -4
  58. package/packages/scrabble-solver/src/components/Alert/Alert.tsx +1 -1
  59. package/packages/scrabble-solver/src/components/Board/Board.tsx +4 -4
  60. package/packages/scrabble-solver/src/components/Board/BoardPure.tsx +4 -4
  61. package/packages/scrabble-solver/src/components/Board/components/Actions/Actions.tsx +5 -5
  62. package/packages/scrabble-solver/src/components/Board/components/Actions/lib.ts +2 -2
  63. package/packages/scrabble-solver/src/components/Board/components/Cell/Cell.tsx +1 -1
  64. package/packages/scrabble-solver/src/components/Board/components/InputPrompt/InputPrompt.tsx +3 -3
  65. package/packages/scrabble-solver/src/components/Board/components/ToggleDirectionButton/ToggleDirectionButton.tsx +4 -4
  66. package/packages/scrabble-solver/src/components/Board/hooks/useBackgroundImage.tsx +13 -12
  67. package/packages/scrabble-solver/src/components/Board/hooks/useBoardStyle.ts +4 -4
  68. package/packages/scrabble-solver/src/components/Board/hooks/useFloatingActions.ts +2 -2
  69. package/packages/scrabble-solver/src/components/Board/hooks/useFloatingInputPrompt.ts +1 -1
  70. package/packages/scrabble-solver/src/components/Board/hooks/useGrid.ts +5 -5
  71. package/packages/scrabble-solver/src/components/Board/lib.ts +2 -2
  72. package/packages/scrabble-solver/src/components/Board/selectors.ts +2 -2
  73. package/packages/scrabble-solver/src/components/Dictionary/Dictionary.tsx +2 -2
  74. package/packages/scrabble-solver/src/components/DictionaryInput/DictionaryInput.tsx +2 -2
  75. package/packages/scrabble-solver/src/components/EmptyState/EmptyState.tsx +13 -5
  76. package/packages/scrabble-solver/src/components/Keys/Arrows/Arrows.tsx +1 -1
  77. package/packages/scrabble-solver/src/components/Keys/index.tsx +2 -2
  78. package/packages/scrabble-solver/src/components/Loading/Loading.tsx +2 -2
  79. package/packages/scrabble-solver/src/components/Logo/Logo.tsx +2 -2
  80. package/packages/scrabble-solver/src/components/Modal/Modal.tsx +3 -4
  81. package/packages/scrabble-solver/src/components/NavButtons/NavButtons.tsx +4 -4
  82. package/packages/scrabble-solver/src/components/NavButtons/selectors.ts +1 -1
  83. package/packages/scrabble-solver/src/components/NotFound/NotFound.tsx +1 -1
  84. package/packages/scrabble-solver/src/components/PlainTiles/lib.ts +1 -1
  85. package/packages/scrabble-solver/src/components/Progress/Progress.tsx +2 -2
  86. package/packages/scrabble-solver/src/components/Rack/Rack.tsx +4 -4
  87. package/packages/scrabble-solver/src/components/Rack/components/InputPrompt/InputPrompt.tsx +2 -2
  88. package/packages/scrabble-solver/src/components/Rack/components/InputPrompt/lib.ts +1 -3
  89. package/packages/scrabble-solver/src/components/Rack/components/RackTile/RackTile.tsx +2 -2
  90. package/packages/scrabble-solver/src/components/Rack/selectors.ts +2 -2
  91. package/packages/scrabble-solver/src/components/Results/Cell.tsx +2 -2
  92. package/packages/scrabble-solver/src/components/Results/Header.tsx +5 -5
  93. package/packages/scrabble-solver/src/components/Results/HeaderButton.tsx +3 -3
  94. package/packages/scrabble-solver/src/components/Results/Result.tsx +6 -6
  95. package/packages/scrabble-solver/src/components/Results/Results.tsx +4 -4
  96. package/packages/scrabble-solver/src/components/Results/SolveButton.tsx +2 -2
  97. package/packages/scrabble-solver/src/components/ResultsInput/ResultsInput.tsx +2 -2
  98. package/packages/scrabble-solver/src/components/Solver/Solver.tsx +3 -3
  99. package/packages/scrabble-solver/src/components/Solver/components/InsertButton/InsertButton.tsx +2 -2
  100. package/packages/scrabble-solver/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.tsx +2 -2
  101. package/packages/scrabble-solver/src/components/Spinner/Spinner.tsx +1 -1
  102. package/packages/scrabble-solver/src/components/Tile/Tile.tsx +3 -3
  103. package/packages/scrabble-solver/src/components/Tile/TilePure.tsx +1 -1
  104. package/packages/scrabble-solver/src/components/Tooltip/TooltipContent.tsx +1 -1
  105. package/packages/scrabble-solver/src/hooks/useColumns.ts +3 -3
  106. package/packages/scrabble-solver/src/hooks/useDirection.ts +1 -1
  107. package/packages/scrabble-solver/src/hooks/useLanguage.ts +1 -1
  108. package/packages/scrabble-solver/src/hooks/useLocalStorage.ts +1 -1
  109. package/packages/scrabble-solver/src/hooks/useMedia.ts +0 -1
  110. package/packages/scrabble-solver/src/hooks/useMediaQuery.ts +1 -1
  111. package/packages/scrabble-solver/src/i18n/constants.ts +1 -1
  112. package/packages/scrabble-solver/src/i18n/i18n.ts +1 -1
  113. package/packages/scrabble-solver/src/i18n/languages/english.json +1 -1
  114. package/packages/scrabble-solver/src/i18n/languages/french.json +1 -1
  115. package/packages/scrabble-solver/src/i18n/languages/german.json +1 -1
  116. package/packages/scrabble-solver/src/i18n/languages/polish.json +1 -1
  117. package/packages/scrabble-solver/src/i18n/languages/romanian.json +1 -1
  118. package/packages/scrabble-solver/src/i18n/languages/spanish.json +1 -1
  119. package/packages/scrabble-solver/src/i18n/languages/turkish.json +1 -1
  120. package/packages/scrabble-solver/src/lib/createComparator.ts +1 -1
  121. package/packages/scrabble-solver/src/lib/createKeyComparator.ts +1 -1
  122. package/packages/scrabble-solver/src/lib/createStringComparator.ts +1 -1
  123. package/packages/scrabble-solver/src/lib/getTileSizes.ts +1 -1
  124. package/packages/scrabble-solver/src/lib/numberComparator.ts +1 -1
  125. package/packages/scrabble-solver/src/lib/reverseComparator.ts +1 -1
  126. package/packages/scrabble-solver/src/lib/zipCharactersAndTiles.ts +1 -1
  127. package/packages/scrabble-solver/src/modals/DictionaryModal/DictionaryModal.tsx +2 -2
  128. package/packages/scrabble-solver/src/modals/KeyMapModal/KeyMapModal.tsx +2 -2
  129. package/packages/scrabble-solver/src/modals/MenuModal/MenuModal.tsx +5 -5
  130. package/packages/scrabble-solver/src/modals/RemainingTilesModal/RemainingTilesModal.tsx +5 -5
  131. package/packages/scrabble-solver/src/modals/RemainingTilesModal/components/Character/Character.tsx +5 -5
  132. package/packages/scrabble-solver/src/modals/RemainingTilesModal/lib.ts +1 -1
  133. package/packages/scrabble-solver/src/modals/RemainingTilesModal/selectors.ts +1 -1
  134. package/packages/scrabble-solver/src/modals/ResultsModal/ResultsModal.tsx +4 -4
  135. package/packages/scrabble-solver/src/modals/SettingsModal/SettingsModal.tsx +3 -3
  136. package/packages/scrabble-solver/src/modals/SettingsModal/components/AutoGroupTilesSetting/AutoGroupTilesSetting.tsx +2 -2
  137. package/packages/scrabble-solver/src/modals/SettingsModal/components/AutoGroupTilesSetting/lib.ts +1 -1
  138. package/packages/scrabble-solver/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.tsx +2 -2
  139. package/packages/scrabble-solver/src/modals/SettingsModal/components/InputModeSetting/InputModeSetting.tsx +2 -2
  140. package/packages/scrabble-solver/src/modals/SettingsModal/components/InputModeSetting/lib.ts +1 -1
  141. package/packages/scrabble-solver/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.tsx +3 -3
  142. package/packages/scrabble-solver/src/modals/SettingsModal/components/RemoveCellFiltersSetting/RemoveCellFiltersSetting.tsx +2 -2
  143. package/packages/scrabble-solver/src/modals/SettingsModal/components/RemoveCellFiltersSetting/lib.ts +1 -1
  144. package/packages/scrabble-solver/src/modals/SettingsModal/components/ShowCoordinatesSetting/ShowCoordinatesSetting.tsx +2 -2
  145. package/packages/scrabble-solver/src/modals/WordsModal/WordsModal.tsx +3 -3
  146. package/packages/scrabble-solver/src/pages/_app.tsx +3 -4
  147. package/packages/scrabble-solver/src/pages/api/dictionary/[locale]/[word].ts +1 -1
  148. package/packages/scrabble-solver/src/pages/api/dictionary/[locale]/index.ts +1 -1
  149. package/packages/scrabble-solver/src/pages/api/solve.ts +2 -2
  150. package/packages/scrabble-solver/src/pages/api/verify.ts +1 -1
  151. package/packages/scrabble-solver/src/pages/api/visit.ts +1 -1
  152. package/packages/scrabble-solver/src/pages/index.tsx +6 -6
  153. package/packages/scrabble-solver/src/pages/not-found.tsx +1 -1
  154. package/packages/scrabble-solver/src/parameters/index.ts +4 -4
  155. package/packages/scrabble-solver/src/sdk/fetchJson.ts +3 -7
  156. package/packages/scrabble-solver/src/service-worker/index.ts +0 -1
  157. package/packages/scrabble-solver/src/service-worker/routeSolveRequests.ts +19 -13
  158. package/packages/scrabble-solver/src/service-worker/routeVerifyRequests.ts +1 -1
  159. package/packages/scrabble-solver/src/state/board/slice.ts +30 -5
  160. package/packages/scrabble-solver/src/state/cellFilters/lib.ts +1 -1
  161. package/packages/scrabble-solver/src/state/cellFilters/selectors.ts +1 -1
  162. package/packages/scrabble-solver/src/state/cellFilters/slice.ts +1 -1
  163. package/packages/scrabble-solver/src/state/cellFilters/types.ts +1 -1
  164. package/packages/scrabble-solver/src/state/lib.ts +2 -2
  165. package/packages/scrabble-solver/src/state/localStorage.ts +1 -1
  166. package/packages/scrabble-solver/src/state/rack/slice.ts +2 -2
  167. package/packages/scrabble-solver/src/state/rack/types.ts +1 -1
  168. package/packages/scrabble-solver/src/state/results/initialState.ts +1 -1
  169. package/packages/scrabble-solver/src/state/results/lib.ts +9 -2
  170. package/packages/scrabble-solver/src/state/results/selectors.ts +1 -1
  171. package/packages/scrabble-solver/src/state/results/slice.ts +1 -1
  172. package/packages/scrabble-solver/src/state/results/types.ts +1 -1
  173. package/packages/scrabble-solver/src/state/sagas.ts +4 -5
  174. package/packages/scrabble-solver/src/state/selectors.ts +1 -1
  175. package/packages/scrabble-solver/src/state/settings/selectors.ts +1 -1
  176. package/packages/scrabble-solver/src/state/settings/slice.ts +1 -1
  177. package/packages/scrabble-solver/src/state/settings/types.ts +1 -1
  178. package/packages/scrabble-solver/src/state/useTranslate.ts +1 -1
  179. package/packages/scrabble-solver/tsconfig.json +1 -16
  180. package/packages/scrabble-solver/tsconfig.tsbuildinfo +1 -1
  181. package/packages/solver/build/fillPattern.d.ts +1 -3
  182. package/packages/solver/package.json +6 -6
  183. package/packages/solver/src/getPatternScore.test.ts +52 -4
  184. package/packages/types/build/Result.d.ts +1 -1
  185. package/packages/types/package.json +3 -3
  186. package/packages/word-definitions/build/languages/english.js +1 -3
  187. package/packages/word-definitions/package.json +4 -4
  188. package/packages/word-definitions/src/languages/english.ts +0 -1
  189. package/packages/word-lists/package.json +4 -4
  190. package/tsconfig.jest.json +4 -1
  191. package/tsconfig.json +1 -0
  192. package/.prettierignore +0 -8
  193. package/.prettierrc +0 -11
  194. package/eslint.config.mjs +0 -722
  195. /package/packages/scrabble-solver/.next/static/{zFnoNsMXUha-MKjuZn6AN → FDUqldlsD7FXe6iWhIJmu}/_ssgManifest.js +0 -0
@@ -42,7 +42,7 @@
42
42
  "keyMap.board-and-rack.insert-two-letter-tile": "Introducere piesa 2 litere",
43
43
  "keyMap.board-and-rack.navigate": "Navigare",
44
44
  "keyMap.board-and-rack.remove-tile": "Indeparteaza piesa",
45
- "keyMap.board-and-rack.submit": "Pornire cautare",
45
+ "keyMap.board-and-rack.submit": "Rezolvă",
46
46
  "keyMap.rack": "Grupa litere",
47
47
  "keyMap.rack.insert-blank": "Introducere joker",
48
48
  "menu": "Meniu",
@@ -42,7 +42,7 @@
42
42
  "keyMap.board-and-rack.insert-two-letter-tile": "Insertar mosaico de dos letras",
43
43
  "keyMap.board-and-rack.navigate": "Navegar",
44
44
  "keyMap.board-and-rack.remove-tile": "Quitar Letra",
45
- "keyMap.board-and-rack.submit": "Empezar a resolver",
45
+ "keyMap.board-and-rack.submit": "Resolver",
46
46
  "keyMap.rack": "Estante",
47
47
  "keyMap.rack.insert-blank": "Insertar espacio en blanco",
48
48
  "menu": "Menú",
@@ -42,7 +42,7 @@
42
42
  "keyMap.board-and-rack.insert-two-letter-tile": "İki harfli kutucuğu ekle",
43
43
  "keyMap.board-and-rack.navigate": "Gezinme",
44
44
  "keyMap.board-and-rack.remove-tile": "Taşı kaldır",
45
- "keyMap.board-and-rack.submit": "Çözmeye başla",
45
+ "keyMap.board-and-rack.submit": "Çöz",
46
46
  "keyMap.rack": "Deste",
47
47
  "keyMap.rack.insert-blank": "Joker ekle (spacebar)",
48
48
  "menu": "Menü",
@@ -1,4 +1,4 @@
1
- import type { 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 { type 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 { type 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) => {
@@ -1,4 +1,4 @@
1
- import { BOARD_TILE_FONT_SIZE_MIN, BOARD_TILE_FONT_SIZE_POINTS_MIN } from 'parameters';
1
+ import { BOARD_TILE_FONT_SIZE_MIN, BOARD_TILE_FONT_SIZE_POINTS_MIN } from '@/parameters';
2
2
 
3
3
  interface TileSizes {
4
4
  pointsFontSize: number;
@@ -1,3 +1,3 @@
1
- import { type 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 { type 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
2
  import { type Tile } from '@scrabble-solver/types';
3
3
 
4
- import { type Rack } from 'types';
4
+ import { type Rack } from '@/types';
5
5
 
6
6
  interface CharacterTilePair {
7
7
  character: string | null;
@@ -1,7 +1,7 @@
1
1
  import { type FunctionComponent, memo } from 'react';
2
2
 
3
- import { Dictionary, DictionaryInput, Modal } from 'components';
4
- import { useTranslate } from 'state';
3
+ import { Dictionary, DictionaryInput, Modal } from '@/components';
4
+ import { useTranslate } from '@/state';
5
5
 
6
6
  import styles from './DictionaryModal.module.scss';
7
7
 
@@ -1,7 +1,7 @@
1
1
  import { type FunctionComponent, memo } from 'react';
2
2
 
3
- import { Arrows, Backspace, Ctrl, Del, Enter, Key, Modal, Space } from 'components';
4
- import { selectConfig, useTranslate, useTypedSelector } from 'state';
3
+ import { Arrows, Backspace, Ctrl, Del, Enter, Key, Modal, Space } from '@/components';
4
+ import { selectConfig, useTranslate, useTypedSelector } from '@/state';
5
5
 
6
6
  import { Mapping } from './components';
7
7
 
@@ -1,10 +1,10 @@
1
1
  import { type FunctionComponent, memo } from 'react';
2
2
 
3
- import { Button, Modal } from 'components';
4
- import { LOCALE_FEATURES } from 'i18n';
5
- import { BookHalf, CardChecklist, Cog, Github, Sack } from 'icons';
6
- import { GITHUB_PROJECT_URL } from 'parameters';
7
- import { selectLocale, useTranslate, useTypedSelector } from 'state';
3
+ import { Button, Modal } from '@/components';
4
+ import { LOCALE_FEATURES } from '@/i18n';
5
+ import { BookHalf, CardChecklist, Cog, Github, Sack } from '@/icons';
6
+ import { GITHUB_PROJECT_URL } from '@/parameters';
7
+ import { selectLocale, useTranslate, useTypedSelector } from '@/state';
8
8
 
9
9
  import styles from './MenuModal.module.scss';
10
10
 
@@ -1,10 +1,10 @@
1
1
  import { type FunctionComponent, memo } from 'react';
2
2
 
3
- import { Badge, Modal } from 'components';
4
- import { LOCALE_FEATURES } from 'i18n';
5
- import { getTileSizes } from 'lib';
6
- import { REMAINING_TILES_TILE_SIZE } from 'parameters';
7
- import { selectLocale, useTranslate, useTypedSelector } from 'state';
3
+ import { Badge, Modal } from '@/components';
4
+ import { LOCALE_FEATURES } from '@/i18n';
5
+ import { getTileSizes } from '@/lib';
6
+ import { REMAINING_TILES_TILE_SIZE } from '@/parameters';
7
+ import { selectLocale, useTranslate, useTypedSelector } from '@/state';
8
8
 
9
9
  import { Character } from './components';
10
10
  import styles from './RemainingTilesModal.module.scss';
@@ -2,11 +2,11 @@ import { BLANK } from '@scrabble-solver/constants';
2
2
  import classNames from 'classnames';
3
3
  import { type FunctionComponent } from 'react';
4
4
 
5
- import { Progress, Tile } from 'components';
6
- import { LOCALE_FEATURES } from 'i18n';
7
- import { REMAINING_TILES_TILE_SIZE } from 'parameters';
8
- import { selectCharacterPoints, selectLocale, useTypedSelector } from 'state';
9
- import { type RemainingTile } from 'types';
5
+ import { Progress, Tile } from '@/components';
6
+ import { LOCALE_FEATURES } from '@/i18n';
7
+ import { REMAINING_TILES_TILE_SIZE } from '@/parameters';
8
+ import { selectCharacterPoints, selectLocale, useTypedSelector } from '@/state';
9
+ import { type RemainingTile } from '@/types';
10
10
 
11
11
  import styles from './Character.module.scss';
12
12
 
@@ -1,6 +1,6 @@
1
1
  import { BLANK, CONSONANTS, VOWELS } from '@scrabble-solver/constants';
2
2
 
3
- import { type RemainingTile, type RemainingTilesGroup } from 'types';
3
+ import { type RemainingTile, type RemainingTilesGroup } from '@/types';
4
4
 
5
5
  export const getRemainingTilesGroups = (remainingTiles: RemainingTile[]): RemainingTilesGroup[] => {
6
6
  const consonants = remainingTiles.filter(isConsonant);
@@ -1,6 +1,6 @@
1
1
  import { createSelector } from '@reduxjs/toolkit';
2
2
 
3
- import { selectRemainingTiles } from 'state';
3
+ import { selectRemainingTiles } from '@/state';
4
4
 
5
5
  import { getRemainingTilesGroups } from './lib';
6
6
 
@@ -2,10 +2,10 @@ import { type Result } from '@scrabble-solver/types';
2
2
  import { type FunctionComponent, memo, useEffect, useMemo } from 'react';
3
3
  import { useDispatch } from 'react-redux';
4
4
 
5
- import { useAppLayout } from 'app-layout';
6
- import { Button, Dictionary, Modal, Results } from 'components';
7
- import { Check, EyeFill } from 'icons';
8
- import { resultsSlice, selectProcessedResults, selectResultCandidate, useTranslate, useTypedSelector } from 'state';
5
+ import { useAppLayout } from '@/app-layout';
6
+ import { Button, Dictionary, Modal, Results } from '@/components';
7
+ import { Check, EyeFill } from '@/icons';
8
+ import { resultsSlice, selectProcessedResults, selectResultCandidate, useTranslate, useTypedSelector } from '@/state';
9
9
 
10
10
  import styles from './ResultsModal.module.scss';
11
11
 
@@ -1,8 +1,8 @@
1
1
  import { type FunctionComponent, memo } from 'react';
2
2
 
3
- import { Modal } from 'components';
4
- import { useIsTouchDevice } from 'hooks';
5
- import { useTranslate } from 'state';
3
+ import { Modal } from '@/components';
4
+ import { useIsTouchDevice } from '@/hooks';
5
+ import { useTranslate } from '@/state';
6
6
 
7
7
  import {
8
8
  AutoGroupTilesSetting,
@@ -1,8 +1,8 @@
1
1
  import { type ChangeEvent, type FunctionComponent } from 'react';
2
2
  import { useDispatch } from 'react-redux';
3
3
 
4
- import { Radio } from 'components';
5
- import { selectAutoGroupTiles, settingsSlice, useTranslate, useTypedSelector } from 'state';
4
+ import { Radio } from '@/components';
5
+ import { selectAutoGroupTiles, settingsSlice, useTranslate, useTypedSelector } from '@/state';
6
6
 
7
7
  import styles from './AutoGroupTilesSetting.module.scss';
8
8
  import { NULL_VALUE } from './constants';
@@ -1,4 +1,4 @@
1
- import { type AutoGroupTiles } from 'types';
1
+ import { type AutoGroupTiles } from '@/types';
2
2
 
3
3
  import { NULL_VALUE } from './constants';
4
4
 
@@ -2,8 +2,8 @@ import { isGame } from '@scrabble-solver/types';
2
2
  import { type ChangeEvent, type FunctionComponent, useMemo } from 'react';
3
3
  import { useDispatch } from 'react-redux';
4
4
 
5
- import { Radio } from 'components';
6
- import { selectGame, selectLocale, settingsSlice, useTypedSelector } from 'state';
5
+ import { Radio } from '@/components';
6
+ import { selectGame, selectLocale, settingsSlice, useTypedSelector } from '@/state';
7
7
 
8
8
  import styles from './ConfigSetting.module.scss';
9
9
  import { getOptions } from './lib';
@@ -1,8 +1,8 @@
1
1
  import { type ChangeEvent, type FunctionComponent } from 'react';
2
2
  import { useDispatch } from 'react-redux';
3
3
 
4
- import { Radio } from 'components';
5
- import { selectInputMode, settingsSlice, useTranslate, useTypedSelector } from 'state';
4
+ import { Radio } from '@/components';
5
+ import { selectInputMode, settingsSlice, useTranslate, useTypedSelector } from '@/state';
6
6
 
7
7
  import styles from './InputModeSetting.module.scss';
8
8
  import { parseValue } from './lib';
@@ -1,4 +1,4 @@
1
- import { type InputMode } from 'types';
1
+ import { type InputMode } from '@/types';
2
2
 
3
3
  export const parseValue = (value: string): InputMode => {
4
4
  if (value === 'keyboard') {
@@ -3,9 +3,9 @@ import classNames from 'classnames';
3
3
  import { type ChangeEvent, type FunctionComponent } from 'react';
4
4
  import { useDispatch } from 'react-redux';
5
5
 
6
- import { Radio } from 'components';
7
- import { LOCALE_FEATURES } from 'i18n';
8
- import { selectLocale, settingsSlice, useTypedSelector } from 'state';
6
+ import { Radio } from '@/components';
7
+ import { LOCALE_FEATURES } from '@/i18n';
8
+ import { selectLocale, settingsSlice, useTypedSelector } from '@/state';
9
9
 
10
10
  import styles from './LocaleSetting.module.scss';
11
11
 
@@ -1,8 +1,8 @@
1
1
  import { type ChangeEvent, type FunctionComponent } from 'react';
2
2
  import { useDispatch } from 'react-redux';
3
3
 
4
- import { Radio } from 'components';
5
- import { selectRemoveCellFilters, settingsSlice, useTranslate, useTypedSelector } from 'state';
4
+ import { Radio } from '@/components';
5
+ import { selectRemoveCellFilters, settingsSlice, useTranslate, useTypedSelector } from '@/state';
6
6
 
7
7
  import { parseValue } from './lib';
8
8
  import styles from './RemoveCellFiltersSetting.module.scss';
@@ -1,4 +1,4 @@
1
- import { type RemoveCellFilters } from 'types';
1
+ import { type RemoveCellFilters } from '@/types';
2
2
 
3
3
  export const parseValue = (value: string): RemoveCellFilters => {
4
4
  if (value === 'always') {
@@ -2,8 +2,8 @@ import { type ShowCoordinates } from '@scrabble-solver/types';
2
2
  import { type ChangeEvent, type FunctionComponent } from 'react';
3
3
  import { useDispatch } from 'react-redux';
4
4
 
5
- import { Radio } from 'components';
6
- import { selectShowCoordinates, settingsSlice, useTranslate, useTypedSelector } from 'state';
5
+ import { Radio } from '@/components';
6
+ import { selectShowCoordinates, settingsSlice, useTranslate, useTypedSelector } from '@/state';
7
7
 
8
8
  import styles from './ShowCoordinatesSetting.module.scss';
9
9
 
@@ -1,9 +1,9 @@
1
1
  import classNames from 'classnames';
2
2
  import { type FunctionComponent, memo } from 'react';
3
3
 
4
- import { Badge, Modal } from 'components';
5
- import { Check, Cross } from 'icons';
6
- import { selectInvalidWords, selectLocale, selectValidWords, useTranslate, useTypedSelector } from 'state';
4
+ import { Badge, Modal } from '@/components';
5
+ import { Check, Cross } from '@/icons';
6
+ import { selectInvalidWords, selectLocale, selectValidWords, useTranslate, useTypedSelector } from '@/state';
7
7
 
8
8
  import styles from './WordsModal.module.scss';
9
9
 
@@ -4,14 +4,13 @@ import Head from 'next/head';
4
4
  import { type FunctionComponent } from 'react';
5
5
  import { Provider } from 'react-redux';
6
6
 
7
- import { AppLayoutProvider } from 'app-layout';
8
- import { SeoMessage } from 'components';
9
- import { store } from 'state';
7
+ import { AppLayoutProvider } from '@/app-layout';
8
+ import { SeoMessage } from '@/components';
9
+ import { store } from '@/state';
10
10
 
11
11
  import '../styles/global.scss';
12
12
 
13
13
  const DESCRIPTION =
14
- // eslint-disable-next-line max-len
15
14
  'Scrabble Solver 2 - Free and open-source analysis tool for Scrabble, Scrabble Duel, Super Scrabble, Letter League, Crossplay, Literaki and Kelimelik. Quickly find top scoring words using given letters and board state. Available in English, French, German, Persian, Polish, Romanian, Spanish, and Turkish.';
16
15
 
17
16
  const KEYWORDS = [
@@ -6,7 +6,7 @@ import { type Locale, isLocale } from '@scrabble-solver/types';
6
6
  import { getWordDefinition } from '@scrabble-solver/word-definitions';
7
7
  import { type NextApiRequest, type NextApiResponse } from 'next';
8
8
 
9
- import { getServerLoggingData } from 'api';
9
+ import { getServerLoggingData } from '@/api';
10
10
 
11
11
  interface RequestData {
12
12
  locale: Locale;
@@ -3,7 +3,7 @@ import { logger } from '@scrabble-solver/logger';
3
3
  import { isLocale, type Locale } from '@scrabble-solver/types';
4
4
  import { type NextApiRequest, type NextApiResponse } from 'next';
5
5
 
6
- import { getServerLoggingData } from 'api';
6
+ import { getServerLoggingData } from '@/api';
7
7
 
8
8
  interface RequestData {
9
9
  locale: Locale;
@@ -15,8 +15,8 @@ import {
15
15
  } from '@scrabble-solver/types';
16
16
  import { type NextApiRequest, type NextApiResponse } from 'next';
17
17
 
18
- import { getServerLoggingData, isBoardValid, isCharacterValid } from 'api';
19
- import { isStringArray } from 'lib';
18
+ import { getServerLoggingData, isBoardValid, isCharacterValid } from '@/api';
19
+ import { isStringArray } from '@/lib';
20
20
 
21
21
  interface RequestData {
22
22
  board: Board;
@@ -4,7 +4,7 @@ import { logger } from '@scrabble-solver/logger';
4
4
  import { Board, type Config, type Game, type Locale, isBoardJson, isGame, isLocale } from '@scrabble-solver/types';
5
5
  import { type NextApiRequest, type NextApiResponse } from 'next';
6
6
 
7
- import { getServerLoggingData, isBoardValid } from 'api';
7
+ import { getServerLoggingData, isBoardValid } from '@/api';
8
8
 
9
9
  interface RequestData {
10
10
  board: Board;
@@ -1,7 +1,7 @@
1
1
  import { logger } from '@scrabble-solver/logger';
2
2
  import { type NextApiRequest, type NextApiResponse } from 'next';
3
3
 
4
- import { getServerLoggingData } from 'api';
4
+ import { getServerLoggingData } from '@/api';
5
5
 
6
6
  const visit = (request: NextApiRequest, response: NextApiResponse): void => {
7
7
  const meta = getServerLoggingData(request);
@@ -7,9 +7,9 @@ import { type FunctionComponent, useCallback, useState } from 'react';
7
7
  import ReactModal from 'react-modal';
8
8
  import { useDispatch } from 'react-redux';
9
9
 
10
- import { Logo, NavButtons, Solver } from 'components';
11
- import { useDirection, useEffectOnce, useLanguage, useLocalStorage } from 'hooks';
12
- import { LOCALE_FEATURES } from 'i18n';
10
+ import { Logo, NavButtons, Solver } from '@/components';
11
+ import { useDirection, useEffectOnce, useLanguage, useLocalStorage } from '@/hooks';
12
+ import { LOCALE_FEATURES } from '@/i18n';
13
13
  import {
14
14
  DictionaryModal,
15
15
  KeyMapModal,
@@ -18,9 +18,9 @@ import {
18
18
  ResultsModal,
19
19
  SettingsModal,
20
20
  WordsModal,
21
- } from 'modals';
22
- import { registerServiceWorker } from 'serviceWorkerManager';
23
- import { initialize, reset, selectConfig, selectLocale, useTypedSelector } from 'state';
21
+ } from '@/modals';
22
+ import { registerServiceWorker } from '@/serviceWorkerManager';
23
+ import { initialize, reset, selectConfig, selectLocale, useTypedSelector } from '@/state';
24
24
 
25
25
  import styles from './index.module.scss';
26
26
 
@@ -1,5 +1,5 @@
1
1
  'use-client';
2
2
 
3
- import { NotFound } from 'components';
3
+ import { NotFound } from '@/components';
4
4
 
5
5
  export default NotFound;
@@ -1,4 +1,4 @@
1
- import { ResultColumnId } from 'types';
1
+ import { ResultColumnId } from '@/types';
2
2
 
3
3
  export const BREAKPOINTS = {
4
4
  xs: 480,
@@ -62,11 +62,13 @@ export const SPACING_XL = 40;
62
62
  export const COMPONENTS_SPACING = SPACING_XL;
63
63
  export const COMPONENTS_SPACING_SMALL = SPACING_L;
64
64
 
65
+ export const RACK_TILE_SIZE_MAX = 80;
66
+
65
67
  export const BOARD_CELL_ACTIONS_OFFSET = 3;
66
68
  export const BOARD_CELL_BORDER_WIDTH = 1;
67
69
  export const BOARD_TILE_FONT_SIZE_MIN = 14;
68
70
  export const BOARD_TILE_FONT_SIZE_POINTS_MIN = 10;
69
- export const BOARD_TILE_SIZE_MAX = 64;
71
+ export const BOARD_TILE_SIZE_MAX = RACK_TILE_SIZE_MAX;
70
72
 
71
73
  export const BORDER_COLOR = '#cdcdcd';
72
74
  export const BORDER_COLOR_LIGHT = '#d9d9d9';
@@ -119,8 +121,6 @@ export const PLAIN_TILES_VERSION_TILE_SIZE = TILE_SIZE;
119
121
  export const PROGRESS_COLOR_VALUE = 'var(--color--violet--light)';
120
122
  export const PROGRESS_COLOR_BACKGROUND = 'var(--color--inactive)';
121
123
 
122
- export const RACK_TILE_SIZE_MAX = 80;
123
-
124
124
  export const REMAINING_TILES_TILE_SIZE = 50;
125
125
 
126
126
  export const RESULTS_COLUMN_WIDTH: Record<ResultColumnId, number | undefined> = {
@@ -1,13 +1,9 @@
1
1
  import { fetch } from './fetch';
2
2
 
3
3
  export const fetchJson = async <T>(input: RequestInfo | URL, init?: RequestInit): Promise<T> => {
4
- const response = await fetch(input, {
5
- ...init,
6
- headers: {
7
- 'Content-Type': 'application/json',
8
- ...init?.headers,
9
- },
10
- });
4
+ const headers = new Headers(init?.headers);
5
+ headers.set('Content-Type', 'application/json');
11
6
 
7
+ const response = await fetch(input, { ...init, headers });
12
8
  return response.json();
13
9
  };
@@ -18,7 +18,6 @@ self.addEventListener('activate', () => {
18
18
  });
19
19
 
20
20
  cleanupOutdatedCaches();
21
- // eslint-disable-next-line no-underscore-dangle
22
21
  precacheAndRoute(self.__WB_MANIFEST);
23
22
  routeSolveRequests();
24
23
  routeVerifyRequests();
@@ -5,7 +5,7 @@ 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 { type SolveRequestPayload } from 'types';
8
+ import { type SolveRequestPayload } from '@/types';
9
9
 
10
10
  import { average } from './average';
11
11
  import { revalidateDictionary } from './dictionaries';
@@ -19,18 +19,6 @@ const MIN_MEASUREMENTS = 5;
19
19
  const localDurations: number[] = [];
20
20
  const serverDurations: number[] = [];
21
21
 
22
- const isSlowDevice = (): boolean | undefined => {
23
- if (localDurations.length < MIN_MEASUREMENTS || serverDurations.length < MIN_MEASUREMENTS) {
24
- return undefined;
25
- }
26
-
27
- const count = Math.min(localDurations.length, serverDurations.length);
28
- const local = localDurations.slice(0, count).sort().slice(1, -1);
29
- const server = serverDurations.slice(0, count).sort().slice(1, -1);
30
-
31
- return average(local) > average(server);
32
- };
33
-
34
22
  export const routeSolveRequests = () => {
35
23
  registerRoute(
36
24
  ({ url }) => url.origin === location.origin && url.pathname === '/api/solve',
@@ -83,3 +71,21 @@ export const routeSolveRequests = () => {
83
71
  'POST',
84
72
  );
85
73
  };
74
+
75
+ const isSlowDevice = (): boolean | undefined => {
76
+ if (localDurations.length < MIN_MEASUREMENTS || serverDurations.length < MIN_MEASUREMENTS) {
77
+ return undefined;
78
+ }
79
+
80
+ const count = Math.min(localDurations.length, serverDurations.length);
81
+ const local = localDurations
82
+ .slice(0, count)
83
+ .sort((a, b) => a - b)
84
+ .slice(1, -1);
85
+ const server = localDurations
86
+ .slice(0, count)
87
+ .sort((a, b) => a - b)
88
+ .slice(1, -1);
89
+
90
+ return average(local) > average(server);
91
+ };
@@ -1,7 +1,7 @@
1
1
  import { Board } from '@scrabble-solver/types';
2
2
  import { registerRoute } from 'workbox-routing';
3
3
 
4
- import { type VerifyRequestPayload } from 'types';
4
+ import { type VerifyRequestPayload } from '@/types';
5
5
 
6
6
  import { revalidateDictionary } from './dictionaries';
7
7
  import { getTrie } from './getTrie';
@@ -16,7 +16,7 @@ export const boardSlice = createSlice({
16
16
  const result = action.payload;
17
17
 
18
18
  result.cells.forEach((cell) => {
19
- newBoard.updateCell(cell.x, cell.y, () => new Cell({ ...cell, isEmpty: false }));
19
+ newBoard.updateCell(cell.x, cell.y, () => new Cell({ isEmpty: false, tile: cell.tile, x: cell.x, y: cell.y }));
20
20
  });
21
21
 
22
22
  return newBoard;
@@ -34,7 +34,7 @@ export const boardSlice = createSlice({
34
34
  const tile = isEmpty ? Tile.Null : new Tile({ character: value });
35
35
 
36
36
  newBoard.updateCell(x, y, (cell) => {
37
- return new Cell({ ...cell, isEmpty, tile });
37
+ return new Cell({ isEmpty, tile, x: cell.x, y: cell.y });
38
38
  });
39
39
 
40
40
  return newBoard;
@@ -50,8 +50,10 @@ export const boardSlice = createSlice({
50
50
  const { x, y } = action.payload;
51
51
 
52
52
  newBoard.updateCell(x, y, (cell) => {
53
- const tile = cell.isEmpty ? cell.tile : new Tile({ ...cell.tile, isBlank: !cell.tile.isBlank });
54
- return new Cell({ ...cell, tile });
53
+ const tile = cell.isEmpty
54
+ ? cell.tile
55
+ : new Tile({ isBlank: !cell.tile.isBlank, character: cell.tile.character });
56
+ return new Cell({ isEmpty: cell.isEmpty, tile, x: cell.x, y: cell.y });
55
57
  });
56
58
 
57
59
  return newBoard;
@@ -67,7 +69,30 @@ export const boardSlice = createSlice({
67
69
  }
68
70
 
69
71
  if (state.rows.length !== config.boardHeight || state.rows[0].length !== config.boardWidth) {
70
- return Board.create(config.boardWidth, config.boardHeight);
72
+ const newBoard = Board.create(config.boardWidth, config.boardHeight);
73
+ const offsetX = Math.floor(config.boardWidth / 2) - Math.floor(state.rows[0].length / 2);
74
+ const offsetY = Math.floor(config.boardHeight / 2) - Math.floor(state.rows.length / 2);
75
+
76
+ for (let y = 0; y < state.rows.length; ++y) {
77
+ for (let x = 0; x < state.rows[y].length; ++x) {
78
+ const cell = state.rows[y][x];
79
+
80
+ if (cell.isEmpty) {
81
+ continue;
82
+ }
83
+
84
+ const newX = x + offsetX;
85
+ const newY = y + offsetY;
86
+
87
+ if (newX < 0 || newX >= config.boardWidth || newY < 0 || newY >= config.boardHeight) {
88
+ continue;
89
+ }
90
+
91
+ newBoard.updateCell(newX, newY, () => new Cell({ ...cell, x: newX, y: newY }));
92
+ }
93
+ }
94
+
95
+ return newBoard;
71
96
  }
72
97
 
73
98
  return state;
@@ -1,4 +1,4 @@
1
- import type { CellFilterType } from 'types';
1
+ import type { CellFilterType } from '@/types';
2
2
 
3
3
  export const toggleCellFilterState = (type: CellFilterType): CellFilterType | null => {
4
4
  const chain: (CellFilterType | null)[] = ['include', 'exclude', null];
@@ -1,6 +1,6 @@
1
1
  import { createSelector } from '@reduxjs/toolkit';
2
2
 
3
- import type { Point } from 'types';
3
+ import type { Point } from '@/types';
4
4
 
5
5
  import type { RootState } from '../types';
6
6
 
@@ -1,7 +1,7 @@
1
1
  import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
2
2
  import type { Cell } from '@scrabble-solver/types';
3
3
 
4
- import type { Point } from 'types';
4
+ import type { Point } from '@/types';
5
5
 
6
6
  import { cellFiltersInitialState } from './initialState';
7
7
  import { toggleCellFilterState } from './lib';