scrabble-solver 2.16.7 → 2.18.0

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 (589) hide show
  1. package/.github/workflows/bunx.yml +13 -10
  2. package/.github/workflows/e2e.yml +7 -9
  3. package/.github/workflows/npx.yml +13 -10
  4. package/.nx/workspace-data/d/server-process.json +2 -2
  5. package/.nx/workspace-data/file-map.json +796 -816
  6. package/.nx/workspace-data/lockfile-dependencies.hash +1 -1
  7. package/.nx/workspace-data/lockfile-nodes.hash +1 -1
  8. package/.nx/workspace-data/nx_files.nxt +0 -0
  9. package/.nx/workspace-data/parsed-lock-file.dependencies.json +218 -1298
  10. package/.nx/workspace-data/parsed-lock-file.nodes.json +770 -2669
  11. package/.nx/workspace-data/project-graph.json +1083 -4104
  12. package/.nx/workspace-data/source-maps.json +128 -0
  13. package/.oxlintrc.json +13 -10
  14. package/CLAUDE.md +36 -28
  15. package/README.md +17 -1
  16. package/bun.lock +233 -528
  17. package/e2e/app.spec.ts +124 -0
  18. package/e2e/bugs/112-character-bonus.spec.ts +25 -0
  19. package/e2e/bugs/129-esc-sidebar.spec.ts +17 -0
  20. package/e2e/bugs/2-q-tile-in-english.spec.ts +19 -0
  21. package/e2e/bugs/3-x-tile-in-polish.spec.ts +19 -0
  22. package/e2e/bugs/30-click-inside-radio-icon.spec.ts +25 -0
  23. package/e2e/bugs/333-disabled-radio-cursor.spec.ts +18 -0
  24. package/e2e/bugs/342-results-sorting.spec.ts +30 -0
  25. package/e2e/bugs/352-dictionary-race-condition.spec.ts +27 -0
  26. package/e2e/bugs/363-dictionary-input-unique-words.spec.ts +27 -0
  27. package/e2e/bugs/380-transliteration-when-pasting.spec.ts +55 -0
  28. package/e2e/bugs/398-digraphs-in-created-words.spec.ts +23 -0
  29. package/e2e/bugs/401-board-state-on-game-change.spec.ts +24 -0
  30. package/e2e/features/198-highlight-unreachable-cells.spec.ts +85 -0
  31. package/e2e/features/91-hover-remaining-tile-highlights.spec.ts +76 -0
  32. package/e2e/features/hidden-coordinates-migration.spec.ts +27 -0
  33. package/e2e/features/solver-paths.spec.ts +45 -0
  34. package/e2e/lib/actions.ts +119 -0
  35. package/e2e/lib/selectors.ts +71 -0
  36. package/e2e/tsconfig.json +10 -0
  37. package/lerna.json +1 -1
  38. package/package.json +16 -18
  39. package/packages/configs/package.json +3 -3
  40. package/packages/constants/package.json +1 -1
  41. package/packages/dictionaries/README.md +1 -1
  42. package/packages/dictionaries/build/Dictionaries.d.ts +2 -2
  43. package/packages/dictionaries/build/Dictionaries.js +6 -6
  44. package/packages/dictionaries/build/lib/DiskCache.d.ts +11 -4
  45. package/packages/dictionaries/build/lib/DiskCache.js +27 -10
  46. package/packages/dictionaries/build/lib/LayeredCache.d.ts +4 -4
  47. package/packages/dictionaries/build/lib/LayeredCache.js +3 -3
  48. package/packages/dictionaries/build/lib/MemoryCache.d.ts +4 -4
  49. package/packages/dictionaries/build/lib/MemoryCache.js +2 -2
  50. package/packages/dictionaries/build/lib/createCacheTimestampComparator.d.ts +2 -2
  51. package/packages/dictionaries/build/lib/downloadDictionary.d.ts +2 -2
  52. package/packages/dictionaries/build/lib/downloadDictionary.js +4 -3
  53. package/packages/dictionaries/build/lib/getDictionaryFilepath.d.ts +3 -1
  54. package/packages/dictionaries/build/lib/getDictionaryFilepath.js +8 -3
  55. package/packages/dictionaries/package.json +7 -6
  56. package/packages/dictionaries/src/Dictionaries.ts +12 -12
  57. package/packages/dictionaries/src/lib/DiskCache.test.ts +85 -0
  58. package/packages/dictionaries/src/lib/DiskCache.ts +34 -14
  59. package/packages/dictionaries/src/lib/LayeredCache.ts +7 -7
  60. package/packages/dictionaries/src/lib/MemoryCache.ts +6 -6
  61. package/packages/dictionaries/src/lib/createCacheTimestampComparator.ts +2 -2
  62. package/packages/dictionaries/src/lib/downloadDictionary.ts +5 -4
  63. package/packages/dictionaries/src/lib/getDictionaryFilepath.ts +7 -2
  64. package/packages/gaddag/build/Gaddag.d.ts +39 -0
  65. package/packages/gaddag/build/Gaddag.js +128 -0
  66. package/packages/gaddag/build/buildGaddag.d.ts +10 -0
  67. package/packages/gaddag/build/buildGaddag.js +360 -0
  68. package/packages/gaddag/build/constants.d.ts +12 -0
  69. package/packages/gaddag/build/constants.js +15 -0
  70. package/packages/gaddag/build/index.d.ts +3 -0
  71. package/packages/gaddag/build/index.js +13 -0
  72. package/packages/logger/package.json +1 -1
  73. package/packages/scrabble-solver/.next/BUILD_ID +1 -1
  74. package/packages/scrabble-solver/.next/build-manifest.json +22 -20
  75. package/packages/scrabble-solver/.next/cache/.previewinfo +1 -1
  76. package/packages/scrabble-solver/.next/cache/.rscinfo +1 -1
  77. package/packages/scrabble-solver/.next/cache/.tsbuildinfo +1 -1
  78. package/packages/scrabble-solver/.next/cache/webpack/client-production/0.pack +0 -0
  79. package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack +0 -0
  80. package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack.old +0 -0
  81. package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack +0 -0
  82. package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack.old +0 -0
  83. package/packages/scrabble-solver/.next/cache/webpack/server-production/0.pack +0 -0
  84. package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack +0 -0
  85. package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack.old +0 -0
  86. package/packages/scrabble-solver/.next/diagnostics/framework.json +1 -1
  87. package/packages/scrabble-solver/.next/dynamic-css-manifest.json +8 -1
  88. package/packages/scrabble-solver/.next/next-minimal-server.js.nft.json +1 -1
  89. package/packages/scrabble-solver/.next/next-server.js.nft.json +1 -1
  90. package/packages/scrabble-solver/.next/prerender-manifest.json +4 -4
  91. package/packages/scrabble-solver/.next/react-loadable-manifest.json +176 -1
  92. package/packages/scrabble-solver/.next/required-server-files.js +3 -2
  93. package/packages/scrabble-solver/.next/required-server-files.json +3 -2
  94. package/packages/scrabble-solver/.next/routes-manifest.json +1 -1
  95. package/packages/scrabble-solver/.next/server/chunks/30.js +1 -1
  96. package/packages/scrabble-solver/.next/server/chunks/309.js +1 -0
  97. package/packages/scrabble-solver/.next/server/chunks/316.js +1 -0
  98. package/packages/scrabble-solver/.next/server/chunks/344.js +1 -0
  99. package/packages/scrabble-solver/.next/server/chunks/371.js +1 -0
  100. package/packages/scrabble-solver/.next/server/chunks/392.js +1 -1
  101. package/packages/scrabble-solver/.next/server/chunks/465.js +1 -0
  102. package/packages/scrabble-solver/.next/server/chunks/546.js +1 -0
  103. package/packages/scrabble-solver/.next/server/chunks/623.js +1 -0
  104. package/packages/scrabble-solver/.next/server/chunks/624.js +1 -0
  105. package/packages/scrabble-solver/.next/server/chunks/641.js +1 -0
  106. package/packages/scrabble-solver/.next/server/chunks/671.js +1 -1
  107. package/packages/scrabble-solver/.next/server/chunks/692.js +1 -0
  108. package/packages/scrabble-solver/.next/server/chunks/705.js +1 -0
  109. package/packages/scrabble-solver/.next/server/chunks/712.js +1 -1
  110. package/packages/scrabble-solver/.next/server/chunks/846.js +1 -0
  111. package/packages/scrabble-solver/.next/server/chunks/853.js +15 -0
  112. package/packages/scrabble-solver/.next/server/chunks/886.js +1 -0
  113. package/packages/scrabble-solver/.next/server/chunks/916.js +1 -0
  114. package/packages/scrabble-solver/.next/server/chunks/953.js +1 -0
  115. package/packages/scrabble-solver/.next/server/chunks/961.js +1 -0
  116. package/packages/scrabble-solver/.next/server/chunks/968.js +1 -0
  117. package/packages/scrabble-solver/.next/server/dynamic-css-manifest.js +1 -1
  118. package/packages/scrabble-solver/.next/server/middleware-build-manifest.js +1 -1
  119. package/packages/scrabble-solver/.next/server/middleware-react-loadable-manifest.js +1 -1
  120. package/packages/scrabble-solver/.next/server/pages/404.html +28 -1
  121. package/packages/scrabble-solver/.next/server/pages/500.html +28 -1
  122. package/packages/scrabble-solver/.next/server/pages/_app.js +1 -1
  123. package/packages/scrabble-solver/.next/server/pages/_app.js.nft.json +1 -1
  124. package/packages/scrabble-solver/.next/server/pages/_document.js +28 -1
  125. package/packages/scrabble-solver/.next/server/pages/_document.js.nft.json +1 -1
  126. package/packages/scrabble-solver/.next/server/pages/_error.js +28 -1
  127. package/packages/scrabble-solver/.next/server/pages/_error.js.nft.json +1 -1
  128. package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale]/[word].js +1 -1
  129. package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale]/[word].js.nft.json +1 -1
  130. package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale].js +1 -1
  131. package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale].js.nft.json +1 -1
  132. package/packages/scrabble-solver/.next/server/pages/api/solve.js +1 -1
  133. package/packages/scrabble-solver/.next/server/pages/api/solve.js.nft.json +1 -1
  134. package/packages/scrabble-solver/.next/server/pages/api/verify.js +1 -1
  135. package/packages/scrabble-solver/.next/server/pages/api/verify.js.nft.json +1 -1
  136. package/packages/scrabble-solver/.next/server/pages/api/visit.js.nft.json +1 -1
  137. package/packages/scrabble-solver/.next/server/pages/index.html +28 -1
  138. package/packages/scrabble-solver/.next/server/pages/index.js +30 -1
  139. package/packages/scrabble-solver/.next/server/pages/index.js.nft.json +1 -1
  140. package/packages/scrabble-solver/.next/server/pages/index.json +1 -1
  141. package/packages/scrabble-solver/.next/server/pages/not-found.html +28 -1
  142. package/packages/scrabble-solver/.next/server/pages/not-found.js.nft.json +1 -1
  143. package/packages/scrabble-solver/.next/server/pages-manifest.json +1 -1
  144. package/packages/scrabble-solver/.next/server/webpack-api-runtime.js +1 -1
  145. package/packages/scrabble-solver/.next/server/webpack-runtime.js +1 -1
  146. package/packages/scrabble-solver/.next/static/FL82obwzFHRzvV6z76I-U/_buildManifest.js +1 -0
  147. package/packages/scrabble-solver/.next/static/chunks/101-829ab8a8d310e7a0.js +3 -0
  148. package/packages/scrabble-solver/.next/static/chunks/106.e414e88694add27f.js +1 -0
  149. package/packages/scrabble-solver/.next/static/chunks/127.125d896a19061d71.js +1 -0
  150. package/packages/scrabble-solver/.next/static/chunks/18.8b91e137d239e15c.js +1 -0
  151. package/packages/scrabble-solver/.next/static/chunks/277.6785dfaf22fdb0b7.js +1 -0
  152. package/packages/scrabble-solver/.next/static/chunks/307.67f52f13e3d60d4e.js +1 -0
  153. package/packages/scrabble-solver/.next/static/chunks/341.79535ba85bf1986f.js +1 -0
  154. package/packages/scrabble-solver/.next/static/chunks/363.01eed3233f92b6a4.js +1 -0
  155. package/packages/scrabble-solver/.next/static/chunks/422.1559ae6756912ca5.js +1 -0
  156. package/packages/scrabble-solver/.next/static/chunks/541.dcd9e8b804f88da5.js +1 -0
  157. package/packages/scrabble-solver/.next/static/chunks/583.7a46807be14c377e.js +1 -0
  158. package/packages/scrabble-solver/.next/static/chunks/631.98d42abad0a60af6.js +1 -0
  159. package/packages/scrabble-solver/.next/static/chunks/663.d2c9ca36b26695b8.js +1 -0
  160. package/packages/scrabble-solver/.next/static/chunks/711.ba7b8f900dfd40d0.js +1 -0
  161. package/packages/scrabble-solver/.next/static/chunks/744.b06c9a3de4a1d877.js +1 -0
  162. package/packages/scrabble-solver/.next/static/chunks/820.97b82f751ca49579.js +1 -0
  163. package/packages/scrabble-solver/.next/static/chunks/865.a9b563a45848a83c.js +1 -0
  164. package/packages/scrabble-solver/.next/static/chunks/912.ff8037ba9d4db5c8.js +1 -0
  165. package/packages/scrabble-solver/.next/static/chunks/939.19b33a3d3c351d73.js +1 -0
  166. package/packages/scrabble-solver/.next/static/chunks/990.61296e5870b91f11.js +1 -0
  167. package/packages/scrabble-solver/.next/static/chunks/framework-626cbd48ac5aca57.js +1 -0
  168. package/packages/scrabble-solver/.next/static/chunks/main-b92e08f3fc96dd8d.js +5 -0
  169. package/packages/scrabble-solver/.next/static/chunks/pages/_app-ba5d628e81a15461.js +1 -0
  170. package/packages/scrabble-solver/.next/static/chunks/pages/{_error-afeda7c5231b6c3c.js → _error-f0290a98eb3ed0ec.js} +1 -1
  171. package/packages/scrabble-solver/.next/static/chunks/pages/index-5f9fa6ac3cd3d97b.js +1 -0
  172. package/packages/scrabble-solver/.next/static/chunks/pages/not-found-23d61fd3ed791cad.js +1 -0
  173. package/packages/scrabble-solver/.next/static/chunks/webpack-e34c3ae12275e978.js +1 -0
  174. package/packages/scrabble-solver/.next/static/css/2d03f0da2c678dfc.css +1 -0
  175. package/packages/scrabble-solver/.next/static/css/7b6724d2df70f48f.css +1 -0
  176. package/packages/scrabble-solver/.next/static/css/abc2425d3ba607bc.css +1 -0
  177. package/packages/scrabble-solver/.next/static/css/b736be3bd02b5d99.css +1 -0
  178. package/packages/scrabble-solver/.next/static/css/b74cd7de82dabcdd.css +1 -0
  179. package/packages/scrabble-solver/.next/static/css/c403ce739a9c0d83.css +1 -0
  180. package/packages/scrabble-solver/.next/static/css/ca311e6c030663d4.css +1 -0
  181. package/packages/scrabble-solver/.next/static/css/dee878eb64099d92.css +1 -0
  182. package/packages/scrabble-solver/.next/static/css/fbfdce70731d0d2b.css +1 -0
  183. package/packages/scrabble-solver/.next/trace +21 -21
  184. package/packages/scrabble-solver/.next/trace-build +1 -1
  185. package/packages/scrabble-solver/empty-module.js +2 -0
  186. package/packages/scrabble-solver/next.config.js +13 -8
  187. package/packages/scrabble-solver/package.json +34 -15
  188. package/packages/scrabble-solver/public/llms.txt +11 -0
  189. package/packages/scrabble-solver/public/robots.txt +4 -0
  190. package/packages/scrabble-solver/public/service-worker.js +2 -2
  191. package/packages/scrabble-solver/scripts/generate-scss-types.ts +112 -0
  192. package/packages/scrabble-solver/src/@types/scss.d.ts +6 -9
  193. package/packages/scrabble-solver/src/@types/svg.d.ts +1 -1
  194. package/packages/scrabble-solver/src/components/Alert/Alert.module.scss.d.ts +13 -0
  195. package/packages/scrabble-solver/src/components/Alert/Alert.tsx +4 -1
  196. package/packages/scrabble-solver/src/components/Badge/Badge.module.scss.d.ts +6 -0
  197. package/packages/scrabble-solver/src/components/Board/Board.module.scss +10 -0
  198. package/packages/scrabble-solver/src/components/Board/Board.module.scss.d.ts +17 -0
  199. package/packages/scrabble-solver/src/components/Board/Board.tsx +14 -26
  200. package/packages/scrabble-solver/src/components/Board/BoardPure.tsx +54 -49
  201. package/packages/scrabble-solver/src/components/Board/components/Actions/Actions.module.scss +18 -18
  202. package/packages/scrabble-solver/src/components/Board/components/Actions/Actions.module.scss.d.ts +7 -0
  203. package/packages/scrabble-solver/src/components/Board/components/Actions/Actions.tsx +6 -3
  204. package/packages/scrabble-solver/src/components/Board/components/Actions/lib.ts +3 -1
  205. package/packages/scrabble-solver/src/components/Board/components/Cell/Cell.module.scss.d.ts +13 -0
  206. package/packages/scrabble-solver/src/components/Board/components/Cell/Cell.tsx +32 -34
  207. package/packages/scrabble-solver/src/components/Board/components/InputPrompt/InputPrompt.module.scss.d.ts +10 -0
  208. package/packages/scrabble-solver/src/components/Board/components/InputPrompt/InputPrompt.tsx +1 -1
  209. package/packages/scrabble-solver/src/components/Board/components/ToggleDirectionButton/ToggleDirectionButton.module.scss.d.ts +8 -0
  210. package/packages/scrabble-solver/src/components/Board/components/ToggleDirectionButton/ToggleDirectionButton.tsx +2 -2
  211. package/packages/scrabble-solver/src/components/Board/getBoardBackground.ts +175 -0
  212. package/packages/scrabble-solver/src/components/Board/hooks/index.ts +0 -1
  213. package/packages/scrabble-solver/src/components/Board/hooks/useBoardStyle.ts +10 -20
  214. package/packages/scrabble-solver/src/components/Board/hooks/useFloatingActions.ts +3 -6
  215. package/packages/scrabble-solver/src/components/Board/hooks/useGrid.ts +23 -9
  216. package/packages/scrabble-solver/src/components/Board/selectors.ts +1 -1
  217. package/packages/scrabble-solver/src/components/Button/Button.module.scss.d.ts +12 -0
  218. package/packages/scrabble-solver/src/components/Dictionary/Dictionary.module.scss +8 -22
  219. package/packages/scrabble-solver/src/components/Dictionary/Dictionary.module.scss.d.ts +14 -0
  220. package/packages/scrabble-solver/src/components/Dictionary/Dictionary.tsx +1 -10
  221. package/packages/scrabble-solver/src/components/DictionaryInput/DictionaryInput.module.scss.d.ts +7 -0
  222. package/packages/scrabble-solver/src/components/DictionaryInput/DictionaryInput.tsx +1 -1
  223. package/packages/scrabble-solver/src/components/EmptyState/EmptyState.module.scss.d.ts +7 -0
  224. package/packages/scrabble-solver/src/components/EmptyState/EmptyState.tsx +1 -1
  225. package/packages/scrabble-solver/src/components/IconButton/IconButton.module.scss.d.ts +8 -0
  226. package/packages/scrabble-solver/src/components/Key/Key.module.scss.d.ts +6 -0
  227. package/packages/scrabble-solver/src/components/Keys/Arrows/Arrows.module.scss.d.ts +11 -0
  228. package/packages/scrabble-solver/src/components/Keys/Arrows/Arrows.tsx +4 -1
  229. package/packages/scrabble-solver/src/components/Keys/index.tsx +1 -1
  230. package/packages/scrabble-solver/src/components/Loading/Loading.module.scss.d.ts +9 -0
  231. package/packages/scrabble-solver/src/components/Loading/Loading.tsx +1 -1
  232. package/packages/scrabble-solver/src/components/Logo/Logo.tsx +4 -9
  233. package/packages/scrabble-solver/src/components/Logo/LogoBlueprint.tsx +1 -0
  234. package/packages/scrabble-solver/src/components/Modal/Modal.module.scss.d.ts +15 -0
  235. package/packages/scrabble-solver/src/components/Modal/Modal.tsx +16 -3
  236. package/packages/scrabble-solver/src/components/Modal/components/Section/Section.module.scss.d.ts +7 -0
  237. package/packages/scrabble-solver/src/components/NavButtons/NavButtons.module.scss +20 -0
  238. package/packages/scrabble-solver/src/components/NavButtons/NavButtons.module.scss.d.ts +13 -0
  239. package/packages/scrabble-solver/src/components/NavButtons/NavButtons.tsx +29 -45
  240. package/packages/scrabble-solver/src/components/NotFound/NotFound.module.scss.d.ts +9 -0
  241. package/packages/scrabble-solver/src/components/NotFound/NotFound.tsx +1 -1
  242. package/packages/scrabble-solver/src/components/PlainTiles/PlainTiles.module.scss.d.ts +11 -0
  243. package/packages/scrabble-solver/src/components/PlainTiles/PlainTiles.tsx +0 -1
  244. package/packages/scrabble-solver/src/components/PlainTiles/Tile.tsx +3 -4
  245. package/packages/scrabble-solver/src/components/PlainTiles/lib.ts +4 -19
  246. package/packages/scrabble-solver/src/components/PlainTiles/types.ts +0 -1
  247. package/packages/scrabble-solver/src/components/Progress/Progress.module.scss +7 -0
  248. package/packages/scrabble-solver/src/components/Progress/Progress.module.scss.d.ts +6 -0
  249. package/packages/scrabble-solver/src/components/Progress/Progress.tsx +2 -11
  250. package/packages/scrabble-solver/src/components/Rack/Rack.module.scss +3 -0
  251. package/packages/scrabble-solver/src/components/Rack/Rack.module.scss.d.ts +10 -0
  252. package/packages/scrabble-solver/src/components/Rack/Rack.tsx +8 -11
  253. package/packages/scrabble-solver/src/components/Rack/components/InputPrompt/InputPrompt.module.scss +2 -0
  254. package/packages/scrabble-solver/src/components/Rack/components/InputPrompt/InputPrompt.module.scss.d.ts +7 -0
  255. package/packages/scrabble-solver/src/components/Rack/components/InputPrompt/InputPrompt.tsx +1 -13
  256. package/packages/scrabble-solver/src/components/Rack/components/InputPrompt/lib.ts +1 -1
  257. package/packages/scrabble-solver/src/components/Rack/components/RackTile/RackTile.module.scss.d.ts +6 -0
  258. package/packages/scrabble-solver/src/components/Rack/components/RackTile/RackTile.tsx +5 -4
  259. package/packages/scrabble-solver/src/components/Rack/selectors.ts +1 -1
  260. package/packages/scrabble-solver/src/components/Radio/Radio.module.scss.d.ts +12 -0
  261. package/packages/scrabble-solver/src/components/Results/Cell.tsx +3 -12
  262. package/packages/scrabble-solver/src/components/Results/Header.tsx +9 -18
  263. package/packages/scrabble-solver/src/components/Results/HeaderButton.tsx +4 -5
  264. package/packages/scrabble-solver/src/components/Results/Result.tsx +4 -15
  265. package/packages/scrabble-solver/src/components/Results/Results.module.scss +4 -7
  266. package/packages/scrabble-solver/src/components/Results/Results.module.scss.d.ts +27 -0
  267. package/packages/scrabble-solver/src/components/Results/Results.tsx +14 -5
  268. package/packages/scrabble-solver/src/components/Results/SolveButton.tsx +1 -1
  269. package/packages/scrabble-solver/src/components/Results/types.ts +3 -3
  270. package/packages/scrabble-solver/src/components/ResultsInput/ResultsInput.module.scss.d.ts +7 -0
  271. package/packages/scrabble-solver/src/components/ResultsInput/ResultsInput.tsx +1 -1
  272. package/packages/scrabble-solver/src/components/Solver/Solver.module.scss +6 -5
  273. package/packages/scrabble-solver/src/components/Solver/Solver.module.scss.d.ts +20 -0
  274. package/packages/scrabble-solver/src/components/Solver/Solver.tsx +23 -24
  275. package/packages/scrabble-solver/src/components/Solver/components/InsertButton/InsertButton.module.scss.d.ts +7 -0
  276. package/packages/scrabble-solver/src/components/Solver/components/InsertButton/InsertButton.tsx +1 -1
  277. package/packages/scrabble-solver/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.module.scss.d.ts +18 -0
  278. package/packages/scrabble-solver/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.tsx +3 -1
  279. package/packages/scrabble-solver/src/components/Spinner/Spinner.module.scss.d.ts +10 -0
  280. package/packages/scrabble-solver/src/components/Tile/Tile.module.scss +3 -0
  281. package/packages/scrabble-solver/src/components/Tile/Tile.module.scss.d.ts +19 -0
  282. package/packages/scrabble-solver/src/components/Tile/Tile.tsx +5 -14
  283. package/packages/scrabble-solver/src/components/Tile/TilePure.tsx +2 -12
  284. package/packages/scrabble-solver/src/components/Tooltip/Tooltip.module.scss.d.ts +7 -0
  285. package/packages/scrabble-solver/src/components/Tooltip/Tooltip.tsx +14 -3
  286. package/packages/scrabble-solver/src/components/Tooltip/useTooltip.ts +2 -1
  287. package/packages/scrabble-solver/src/hooks/useColumns.ts +4 -7
  288. package/packages/scrabble-solver/src/hooks/useDeferredRender.ts +20 -0
  289. package/packages/scrabble-solver/src/hooks/useDirection.ts +4 -3
  290. package/packages/scrabble-solver/src/hooks/useLanguage.ts +2 -2
  291. package/packages/scrabble-solver/src/hooks/useLocalStorage.ts +32 -8
  292. package/packages/scrabble-solver/src/hooks/useMedia.ts +26 -26
  293. package/packages/scrabble-solver/src/i18n/constants.ts +2 -15
  294. package/packages/scrabble-solver/src/i18n/i18n.ts +18 -17
  295. package/packages/scrabble-solver/src/i18n/languages/english.json +0 -1
  296. package/packages/scrabble-solver/src/i18n/languages/french.json +0 -1
  297. package/packages/scrabble-solver/src/i18n/languages/german.json +0 -1
  298. package/packages/scrabble-solver/src/i18n/languages/persian.json +0 -1
  299. package/packages/scrabble-solver/src/i18n/languages/polish.json +0 -1
  300. package/packages/scrabble-solver/src/i18n/languages/romanian.json +0 -1
  301. package/packages/scrabble-solver/src/i18n/languages/spanish.json +0 -1
  302. package/packages/scrabble-solver/src/i18n/languages/turkish.json +0 -1
  303. package/packages/scrabble-solver/src/i18n/localeIcons.ts +24 -0
  304. package/packages/scrabble-solver/src/lib/localeTransliterate.test.ts +5 -0
  305. package/packages/scrabble-solver/src/lib/localeTransliterate.ts +26 -6
  306. package/packages/scrabble-solver/src/lib/waitForIdleOrFirstIntent.ts +33 -0
  307. package/packages/scrabble-solver/src/modals/DictionaryModal/DictionaryModal.module.scss.d.ts +8 -0
  308. package/packages/scrabble-solver/src/modals/DictionaryModal/DictionaryModal.tsx +3 -1
  309. package/packages/scrabble-solver/src/modals/KeyMapModal/KeyMapModal.tsx +3 -1
  310. package/packages/scrabble-solver/src/modals/KeyMapModal/components/Mapping/Mapping.module.scss.d.ts +11 -0
  311. package/packages/scrabble-solver/src/modals/MenuModal/MenuModal.module.scss +5 -0
  312. package/packages/scrabble-solver/src/modals/MenuModal/MenuModal.module.scss.d.ts +10 -0
  313. package/packages/scrabble-solver/src/modals/MenuModal/MenuModal.tsx +16 -5
  314. package/packages/scrabble-solver/src/modals/RemainingTilesModal/RemainingTilesModal.module.scss +4 -1
  315. package/packages/scrabble-solver/src/modals/RemainingTilesModal/RemainingTilesModal.module.scss.d.ts +9 -0
  316. package/packages/scrabble-solver/src/modals/RemainingTilesModal/RemainingTilesModal.tsx +4 -6
  317. package/packages/scrabble-solver/src/modals/RemainingTilesModal/components/Character/Character.module.scss +1 -0
  318. package/packages/scrabble-solver/src/modals/RemainingTilesModal/components/Character/Character.module.scss.d.ts +12 -0
  319. package/packages/scrabble-solver/src/modals/RemainingTilesModal/components/Character/Character.tsx +5 -12
  320. package/packages/scrabble-solver/src/modals/ResultsModal/ResultsModal.module.scss.d.ts +8 -0
  321. package/packages/scrabble-solver/src/modals/ResultsModal/ResultsModal.tsx +8 -4
  322. package/packages/scrabble-solver/src/modals/SettingsModal/SettingsModal.tsx +2 -2
  323. package/packages/scrabble-solver/src/modals/SettingsModal/components/AutoGroupTilesSetting/AutoGroupTilesSetting.module.scss.d.ts +7 -0
  324. package/packages/scrabble-solver/src/modals/SettingsModal/components/AutoGroupTilesSetting/AutoGroupTilesSetting.tsx +1 -1
  325. package/packages/scrabble-solver/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.module.scss.d.ts +7 -0
  326. package/packages/scrabble-solver/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.tsx +1 -1
  327. package/packages/scrabble-solver/src/modals/SettingsModal/components/HighlightUnreachableCellsSetting/HighlightUnreachableCellsSetting.module.scss.d.ts +7 -0
  328. package/packages/scrabble-solver/src/modals/SettingsModal/components/HighlightUnreachableCellsSetting/HighlightUnreachableCellsSetting.tsx +1 -1
  329. package/packages/scrabble-solver/src/modals/SettingsModal/components/InputModeSetting/InputModeSetting.module.scss.d.ts +7 -0
  330. package/packages/scrabble-solver/src/modals/SettingsModal/components/InputModeSetting/InputModeSetting.tsx +1 -1
  331. package/packages/scrabble-solver/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.module.scss.d.ts +8 -0
  332. package/packages/scrabble-solver/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.tsx +24 -21
  333. package/packages/scrabble-solver/src/modals/SettingsModal/components/RemoveCellFiltersSetting/RemoveCellFiltersSetting.module.scss.d.ts +7 -0
  334. package/packages/scrabble-solver/src/modals/SettingsModal/components/RemoveCellFiltersSetting/RemoveCellFiltersSetting.tsx +1 -1
  335. package/packages/scrabble-solver/src/modals/SettingsModal/components/ShowCoordinatesSetting/ShowCoordinatesSetting.module.scss.d.ts +7 -0
  336. package/packages/scrabble-solver/src/modals/SettingsModal/components/ShowCoordinatesSetting/ShowCoordinatesSetting.tsx +1 -5
  337. package/packages/scrabble-solver/src/modals/WordsModal/WordsModal.module.scss.d.ts +11 -0
  338. package/packages/scrabble-solver/src/modals/WordsModal/WordsModal.tsx +4 -2
  339. package/packages/scrabble-solver/src/modals/preload.ts +24 -0
  340. package/packages/scrabble-solver/src/pages/_app.tsx +5 -8
  341. package/packages/scrabble-solver/src/pages/_document.tsx +91 -5
  342. package/packages/scrabble-solver/src/pages/api/dictionary/[locale]/[word].ts +2 -2
  343. package/packages/scrabble-solver/src/pages/api/dictionary/[locale]/index.ts +80 -3
  344. package/packages/scrabble-solver/src/pages/api/solve.ts +3 -3
  345. package/packages/scrabble-solver/src/pages/api/verify.ts +12 -3
  346. package/packages/scrabble-solver/src/pages/index.module.scss +1 -0
  347. package/packages/scrabble-solver/src/pages/index.module.scss.d.ts +11 -0
  348. package/packages/scrabble-solver/src/pages/index.tsx +98 -38
  349. package/packages/scrabble-solver/src/pages/not-found.tsx +1 -1
  350. package/packages/scrabble-solver/src/parameters/index.ts +24 -93
  351. package/packages/scrabble-solver/src/sdk/solve.ts +13 -7
  352. package/packages/scrabble-solver/src/sdk/verify.ts +12 -6
  353. package/packages/scrabble-solver/src/service-worker/appShell.test.ts +86 -0
  354. package/packages/scrabble-solver/src/service-worker/appShell.ts +39 -0
  355. package/packages/scrabble-solver/src/service-worker/index.ts +4 -5
  356. package/packages/scrabble-solver/src/serviceWorkerManager.ts +5 -19
  357. package/packages/scrabble-solver/src/solver-worker/client.test.ts +151 -0
  358. package/packages/scrabble-solver/src/solver-worker/client.ts +106 -0
  359. package/packages/scrabble-solver/src/solver-worker/dictionaries/constants.ts +9 -0
  360. package/packages/scrabble-solver/src/solver-worker/dictionaries/getDictionary.ts +21 -0
  361. package/packages/scrabble-solver/src/solver-worker/dictionaries/index.ts +2 -0
  362. package/packages/scrabble-solver/src/solver-worker/dictionaries/revalidateDictionary.test.ts +199 -0
  363. package/packages/scrabble-solver/src/solver-worker/dictionaries/revalidateDictionary.ts +86 -0
  364. package/packages/scrabble-solver/src/solver-worker/dictionaries/revalidatedAt.ts +43 -0
  365. package/packages/scrabble-solver/src/solver-worker/getGaddag.test.ts +109 -0
  366. package/packages/scrabble-solver/src/solver-worker/getGaddag.ts +62 -0
  367. package/packages/scrabble-solver/src/solver-worker/index.ts +1 -0
  368. package/packages/scrabble-solver/src/solver-worker/index.worker.ts +124 -0
  369. package/packages/scrabble-solver/src/solver-worker/messages.ts +20 -0
  370. package/packages/scrabble-solver/src/state/actions.ts +1 -1
  371. package/packages/scrabble-solver/src/state/app/index.ts +4 -0
  372. package/packages/scrabble-solver/src/state/app/initialState.ts +6 -0
  373. package/packages/scrabble-solver/src/state/app/selectors.ts +5 -0
  374. package/packages/scrabble-solver/src/state/app/slice.ts +20 -0
  375. package/packages/scrabble-solver/src/state/app/types.ts +4 -0
  376. package/packages/scrabble-solver/src/state/board/initialState.ts +1 -2
  377. package/packages/scrabble-solver/src/state/i18n/index.ts +4 -0
  378. package/packages/scrabble-solver/src/state/i18n/initialState.ts +5 -0
  379. package/packages/scrabble-solver/src/state/i18n/selectors.ts +3 -0
  380. package/packages/scrabble-solver/src/state/i18n/slice.ts +16 -0
  381. package/packages/scrabble-solver/src/state/i18n/types.ts +7 -0
  382. package/packages/scrabble-solver/src/state/index.ts +3 -0
  383. package/packages/scrabble-solver/src/state/lib.ts +1 -1
  384. package/packages/scrabble-solver/src/state/localStorage.ts +86 -29
  385. package/packages/scrabble-solver/src/state/rack/initialState.ts +1 -2
  386. package/packages/scrabble-solver/src/state/rack/slice.ts +4 -1
  387. package/packages/scrabble-solver/src/state/results/lib.ts +5 -5
  388. package/packages/scrabble-solver/src/state/results/selectors.ts +1 -1
  389. package/packages/scrabble-solver/src/state/sagas.ts +139 -13
  390. package/packages/scrabble-solver/src/state/selectors.ts +1 -1
  391. package/packages/scrabble-solver/src/state/settings/initialState.ts +7 -10
  392. package/packages/scrabble-solver/src/state/settings/selectors.ts +7 -2
  393. package/packages/scrabble-solver/src/state/settings/slice.ts +5 -2
  394. package/packages/scrabble-solver/src/state/store.ts +4 -0
  395. package/packages/scrabble-solver/src/state/types.ts +4 -0
  396. package/packages/scrabble-solver/src/state/useTypedStore.ts +6 -0
  397. package/packages/scrabble-solver/src/styles/_tokens.scss +1 -0
  398. package/packages/scrabble-solver/src/styles/global.scss +9 -0
  399. package/packages/scrabble-solver/src/styles/variables.module.scss +0 -21
  400. package/packages/scrabble-solver/src/styles/variables.module.scss.d.ts +27 -0
  401. package/packages/scrabble-solver/src/styles/variables.scss +46 -2
  402. package/packages/scrabble-solver/src/types/api.ts +1 -2
  403. package/packages/scrabble-solver/src/types/index.ts +1 -2
  404. package/packages/scrabble-solver/tsconfig.json +4 -0
  405. package/packages/scrabble-solver/tsconfig.tsbuildinfo +1 -1
  406. package/packages/solver/README.md +24 -0
  407. package/packages/solver/benchmarks/index.ts +15 -0
  408. package/packages/solver/benchmarks/lib.ts +31 -0
  409. package/packages/solver/benchmarks/renderChart.ts +165 -0
  410. package/packages/solver/benchmarks/results/chart.svg +65 -0
  411. package/packages/solver/benchmarks/runBenchmarks.ts +66 -0
  412. package/packages/solver/benchmarks/scenarios.ts +64 -0
  413. package/packages/solver/benchmarks/types.ts +16 -0
  414. package/packages/solver/benchmarks/updateReadme.ts +53 -0
  415. package/packages/solver/build/MoveGenerator.d.ts +116 -0
  416. package/packages/solver/build/MoveGenerator.js +686 -0
  417. package/packages/solver/build/index.d.ts +0 -13
  418. package/packages/solver/build/index.js +1 -27
  419. package/packages/solver/build/solve.d.ts +2 -2
  420. package/packages/solver/build/solve.js +3 -19
  421. package/packages/solver/package.json +7 -6
  422. package/packages/solver/src/MoveGenerator.test.ts +1009 -0
  423. package/packages/solver/src/MoveGenerator.ts +926 -0
  424. package/packages/solver/src/ReferenceSolver.ts +401 -0
  425. package/packages/solver/src/index.ts +0 -13
  426. package/packages/solver/src/solve.test.ts +21 -21
  427. package/packages/solver/src/solve.ts +4 -22
  428. package/packages/solver/tsconfig.json +1 -1
  429. package/packages/types/build/Cell.d.ts +1 -0
  430. package/packages/types/build/Cell.js +3 -0
  431. package/packages/types/build/Direction.d.ts +1 -0
  432. package/packages/types/build/Result.d.ts +3 -2
  433. package/packages/types/build/Result.js +11 -6
  434. package/packages/types/build/ResultJson.d.ts +5 -4
  435. package/packages/types/build/ShowCoordinates.d.ts +1 -2
  436. package/packages/types/build/TextDirection.d.ts +1 -0
  437. package/packages/types/build/index.d.ts +2 -6
  438. package/packages/types/build/index.js +1 -9
  439. package/packages/types/build/readResultCells.d.ts +5 -0
  440. package/packages/types/build/readResultCells.js +75 -0
  441. package/packages/types/package.json +4 -3
  442. package/packages/types/src/Cell.ts +4 -0
  443. package/packages/types/src/Direction.ts +1 -0
  444. package/packages/types/src/Result.ts +15 -6
  445. package/packages/types/src/ResultJson.ts +5 -5
  446. package/packages/types/src/ShowCoordinates.ts +1 -2
  447. package/packages/types/src/TextDirection.ts +1 -0
  448. package/packages/types/src/index.ts +2 -6
  449. package/packages/types/src/readResultCells.test.ts +140 -0
  450. package/packages/types/src/readResultCells.ts +90 -0
  451. package/packages/word-definitions/package.json +2 -2
  452. package/packages/word-lists/package.json +2 -2
  453. package/playwright-report/index.html +49 -0
  454. package/playwright.config.ts +30 -0
  455. package/screencast.gif +0 -0
  456. package/scripts/record-screencast.ts +347 -0
  457. package/test-results/.last-run.json +4 -0
  458. package/tsconfig.json +1 -1
  459. package/babel.config.js +0 -4
  460. package/cypress/e2e/app.spec.cy.ts +0 -123
  461. package/cypress/e2e/bugs/112-character-bonus.ts +0 -40
  462. package/cypress/e2e/bugs/129-esc-sidebar.ts +0 -23
  463. package/cypress/e2e/bugs/2-q-tile-in-english.ts +0 -33
  464. package/cypress/e2e/bugs/3-x-tile-in-polish.ts +0 -33
  465. package/cypress/e2e/bugs/30-click-inside-radio-icon.ts +0 -26
  466. package/cypress/e2e/bugs/333-disabled-radio-cursor.ts +0 -24
  467. package/cypress/e2e/bugs/342-results-sorting.ts +0 -48
  468. package/cypress/e2e/bugs/348-results-word-padding.ts +0 -74
  469. package/cypress/e2e/bugs/352-dictionary-race-condition.ts +0 -29
  470. package/cypress/e2e/bugs/363-dictionary-input-unique-words.ts +0 -41
  471. package/cypress/e2e/bugs/380-transliteration-when-pasting.ts +0 -75
  472. package/cypress/e2e/bugs/398-digraphs-in-created-words.ts +0 -38
  473. package/cypress/e2e/bugs/401-board-state-on-game-change.ts +0 -36
  474. package/cypress/e2e/bugs.spec.cy.ts +0 -13
  475. package/cypress/e2e/features/198-highlight-unreachable-cells.ts +0 -101
  476. package/cypress/e2e/features/91-hover-remaining-tile-highlights.ts +0 -90
  477. package/cypress/e2e/features.spec.cy.ts +0 -2
  478. package/cypress/support/commands.ts +0 -4
  479. package/cypress/support/e2e.ts +0 -1
  480. package/cypress/support/index.ts +0 -1
  481. package/cypress/support/lib/actions.ts +0 -85
  482. package/cypress/support/lib/selectors.ts +0 -70
  483. package/cypress/tsconfig.json +0 -10
  484. package/cypress.config.ts +0 -17
  485. package/packages/scrabble-solver/.next/server/chunks/318.js +0 -3
  486. package/packages/scrabble-solver/.next/server/chunks/791.js +0 -15
  487. package/packages/scrabble-solver/.next/static/chunks/framework-3cf15b8041c59dd3.js +0 -1
  488. package/packages/scrabble-solver/.next/static/chunks/main-852475ca502b4e49.js +0 -5
  489. package/packages/scrabble-solver/.next/static/chunks/pages/_app-a5bbe02710f13d05.js +0 -7
  490. package/packages/scrabble-solver/.next/static/chunks/pages/index-ec0f6aeeaf7be227.js +0 -1
  491. package/packages/scrabble-solver/.next/static/chunks/pages/not-found-9e076427bad69d90.js +0 -1
  492. package/packages/scrabble-solver/.next/static/chunks/webpack-1a7a166b34ed8d24.js +0 -1
  493. package/packages/scrabble-solver/.next/static/css/0af35adb4bab56f0.css +0 -2
  494. package/packages/scrabble-solver/.next/static/css/a78e04fe95452380.css +0 -1
  495. package/packages/scrabble-solver/.next/static/vYpMmuC_yEurZGcyGVnLf/_buildManifest.js +0 -1
  496. package/packages/scrabble-solver/src/app-layout/AppLayoutContext.tsx +0 -25
  497. package/packages/scrabble-solver/src/app-layout/index.ts +0 -1
  498. package/packages/scrabble-solver/src/app-layout/useAppLayoutValue.ts +0 -112
  499. package/packages/scrabble-solver/src/components/Board/hooks/useBackgroundImage.tsx +0 -279
  500. package/packages/scrabble-solver/src/components/index.ts +0 -26
  501. package/packages/scrabble-solver/src/hooks/index.ts +0 -12
  502. package/packages/scrabble-solver/src/hooks/useOnWindowResize.ts +0 -11
  503. package/packages/scrabble-solver/src/hooks/useViewportSize.ts +0 -17
  504. package/packages/scrabble-solver/src/i18n/index.ts +0 -2
  505. package/packages/scrabble-solver/src/icons/Flag.svg +0 -4
  506. package/packages/scrabble-solver/src/icons/Star.svg +0 -4
  507. package/packages/scrabble-solver/src/icons/index.ts +0 -49
  508. package/packages/scrabble-solver/src/lib/getTileSizes.ts +0 -13
  509. package/packages/scrabble-solver/src/lib/index.ts +0 -24
  510. package/packages/scrabble-solver/src/modals/index.ts +0 -7
  511. package/packages/scrabble-solver/src/sdk/getDictionary.ts +0 -9
  512. package/packages/scrabble-solver/src/service-worker/average.ts +0 -7
  513. package/packages/scrabble-solver/src/service-worker/dictionaries/constants.ts +0 -5
  514. package/packages/scrabble-solver/src/service-worker/dictionaries/getDictionary.ts +0 -20
  515. package/packages/scrabble-solver/src/service-worker/dictionaries/index.ts +0 -2
  516. package/packages/scrabble-solver/src/service-worker/dictionaries/revalidateDictionary.ts +0 -33
  517. package/packages/scrabble-solver/src/service-worker/getTrie.ts +0 -24
  518. package/packages/scrabble-solver/src/service-worker/routeSolveRequests.ts +0 -91
  519. package/packages/scrabble-solver/src/service-worker/routeVerifyRequests.ts +0 -37
  520. package/packages/solver/build/areDigraphsValid.d.ts +0 -2
  521. package/packages/solver/build/areDigraphsValid.js +0 -17
  522. package/packages/solver/build/fillPattern.d.ts +0 -6
  523. package/packages/solver/build/fillPattern.js +0 -52
  524. package/packages/solver/build/generateEndIndices.d.ts +0 -2
  525. package/packages/solver/build/generateEndIndices.js +0 -17
  526. package/packages/solver/build/generateHorizontalPatterns.d.ts +0 -2
  527. package/packages/solver/build/generateHorizontalPatterns.js +0 -16
  528. package/packages/solver/build/generatePattern.d.ts +0 -7
  529. package/packages/solver/build/generatePattern.js +0 -20
  530. package/packages/solver/build/generatePatterns.d.ts +0 -2
  531. package/packages/solver/build/generatePatterns.js +0 -11
  532. package/packages/solver/build/generateStartIndices.d.ts +0 -2
  533. package/packages/solver/build/generateStartIndices.js +0 -16
  534. package/packages/solver/build/generateVectors.d.ts +0 -7
  535. package/packages/solver/build/generateVectors.js +0 -7
  536. package/packages/solver/build/generateVerticalPatterns.d.ts +0 -2
  537. package/packages/solver/build/generateVerticalPatterns.js +0 -16
  538. package/packages/solver/build/getCellsScore.d.ts +0 -2
  539. package/packages/solver/build/getCellsScore.js +0 -18
  540. package/packages/solver/build/getPatternHash.d.ts +0 -2
  541. package/packages/solver/build/getPatternHash.js +0 -14
  542. package/packages/solver/build/getPatternScore.d.ts +0 -2
  543. package/packages/solver/build/getPatternScore.js +0 -22
  544. package/packages/solver/build/getUniquePatterns.d.ts +0 -2
  545. package/packages/solver/build/getUniquePatterns.js +0 -17
  546. package/packages/solver/src/areDigraphsValid.ts +0 -18
  547. package/packages/solver/src/fillPattern.test.ts +0 -107
  548. package/packages/solver/src/fillPattern.ts +0 -68
  549. package/packages/solver/src/generateEndIndices.test.ts +0 -23
  550. package/packages/solver/src/generateEndIndices.ts +0 -19
  551. package/packages/solver/src/generateHorizontalPatterns.test.ts +0 -31
  552. package/packages/solver/src/generateHorizontalPatterns.ts +0 -15
  553. package/packages/solver/src/generatePattern.ts +0 -33
  554. package/packages/solver/src/generatePatterns.test.ts +0 -13
  555. package/packages/solver/src/generatePatterns.ts +0 -11
  556. package/packages/solver/src/generateStartIndices.test.ts +0 -19
  557. package/packages/solver/src/generateStartIndices.ts +0 -17
  558. package/packages/solver/src/generateVectors.test.ts +0 -12
  559. package/packages/solver/src/generateVectors.ts +0 -10
  560. package/packages/solver/src/generateVerticalPatterns.test.ts +0 -32
  561. package/packages/solver/src/generateVerticalPatterns.ts +0 -15
  562. package/packages/solver/src/getCellsScore.ts +0 -21
  563. package/packages/solver/src/getPatternHash.test.ts +0 -17
  564. package/packages/solver/src/getPatternHash.ts +0 -12
  565. package/packages/solver/src/getPatternScore.test.ts +0 -204
  566. package/packages/solver/src/getPatternScore.ts +0 -23
  567. package/packages/solver/src/getUniquePatterns.ts +0 -19
  568. package/packages/types/build/CollisionJson.d.ts +0 -2
  569. package/packages/types/build/FinalPattern.d.ts +0 -6
  570. package/packages/types/build/FinalPattern.js +0 -14
  571. package/packages/types/build/HorizontalPattern.d.ts +0 -5
  572. package/packages/types/build/HorizontalPattern.js +0 -34
  573. package/packages/types/build/Pattern.d.ts +0 -20
  574. package/packages/types/build/Pattern.js +0 -50
  575. package/packages/types/build/PatternJson.d.ts +0 -6
  576. package/packages/types/build/VerticalPattern.d.ts +0 -5
  577. package/packages/types/build/VerticalPattern.js +0 -34
  578. package/packages/types/src/CollisionJson.ts +0 -3
  579. package/packages/types/src/FinalPattern.ts +0 -14
  580. package/packages/types/src/HorizontalPattern.ts +0 -37
  581. package/packages/types/src/Pattern.ts +0 -71
  582. package/packages/types/src/PatternJson.ts +0 -7
  583. package/packages/types/src/VerticalPattern.ts +0 -37
  584. /package/{cypress/support → e2e}/lib/index.ts +0 -0
  585. /package/packages/scrabble-solver/.next/static/{vYpMmuC_yEurZGcyGVnLf → FL82obwzFHRzvV6z76I-U}/_ssgManifest.js +0 -0
  586. /package/packages/scrabble-solver/src/{service-worker → solver-worker}/dictionaries/expirationManager.ts +0 -0
  587. /package/packages/scrabble-solver/src/{service-worker → solver-worker}/dictionaries/getDictionaryUrl.ts +0 -0
  588. /package/packages/types/build/{CollisionJson.js → Direction.js} +0 -0
  589. /package/packages/types/build/{PatternJson.js → TextDirection.js} +0 -0
@@ -30,8 +30,8 @@ const dictionary = async (request: NextApiRequest, response: NextApiResponse): P
30
30
  },
31
31
  });
32
32
 
33
- const trie = await dictionaries.get(locale);
34
- const results = await Promise.all(words.map((word) => getWordDefinition(locale, word, trie.has(word))));
33
+ const gaddag = await dictionaries.get(locale);
34
+ const results = await Promise.all(words.map((word) => getWordDefinition(locale, word, gaddag.has(word))));
35
35
  response.status(200).send(results.map((result) => result.toJson()));
36
36
  } catch (error) {
37
37
  const message = error instanceof Error ? error.message : 'Unknown error';
@@ -1,7 +1,10 @@
1
+ import { type Gaddag } from '@kamilmielnik/gaddag';
1
2
  import { dictionaries } from '@scrabble-solver/dictionaries';
2
3
  import { logger } from '@scrabble-solver/logger';
3
4
  import { isLocale, type Locale } from '@scrabble-solver/types';
4
5
  import { type NextApiRequest, type NextApiResponse } from 'next';
6
+ import { promisify } from 'util';
7
+ import { gzip } from 'zlib';
5
8
 
6
9
  import { getServerLoggingData } from '@/api';
7
10
 
@@ -22,8 +25,21 @@ const dictionary = async (request: NextApiRequest, response: NextApiResponse): P
22
25
  },
23
26
  });
24
27
 
25
- const trie = await dictionaries.get(locale);
26
- response.status(200).send(trie.serialize());
28
+ const gaddag = await dictionaries.get(locale);
29
+ const isGzip = acceptsGzip(request);
30
+ const body = isGzip ? await getCompressedDictionary(gaddag) : getSerializedDictionary(gaddag);
31
+
32
+ // no-cache makes clients store the payload but revalidate it, so unchanged
33
+ // re-downloads become 304s, answered by Next's built-in ETag handling.
34
+ response.setHeader('Cache-Control', 'no-cache');
35
+ response.setHeader('Content-Type', 'application/octet-stream');
36
+ response.setHeader('Vary', 'Accept-Encoding');
37
+
38
+ if (isGzip) {
39
+ response.setHeader('Content-Encoding', 'gzip');
40
+ }
41
+
42
+ response.status(200).send(body);
27
43
  } catch (error) {
28
44
  const message = error instanceof Error ? error.message : 'Unknown error';
29
45
  logger.error('dictionary - error', { error, meta });
@@ -43,9 +59,70 @@ const parseRequest = (request: NextApiRequest): RequestData => {
43
59
  };
44
60
  };
45
61
 
62
+ const acceptsGzip = (request: NextApiRequest): boolean => {
63
+ const acceptEncoding = request.headers['accept-encoding'];
64
+ const header = Array.isArray(acceptEncoding) ? acceptEncoding.join(',') : acceptEncoding;
65
+
66
+ if (typeof header !== 'string') {
67
+ return false;
68
+ }
69
+
70
+ let wildcardAccepts = false;
71
+
72
+ for (const entry of header.split(',')) {
73
+ const [encoding, ...parameters] = entry.split(';').map((token) => token.trim().toLowerCase());
74
+ const isRefused = parameters.some((parameter) => {
75
+ const [name, quality] = parameter.split('=').map((token) => token.trim());
76
+ return name === 'q' && parseFloat(quality) === 0;
77
+ });
78
+
79
+ if (encoding === 'gzip' || encoding === 'x-gzip') {
80
+ return !isRefused;
81
+ }
82
+
83
+ if (encoding === '*') {
84
+ wildcardAccepts = !isRefused;
85
+ }
86
+ }
87
+
88
+ return wildcardAccepts;
89
+ };
90
+
91
+ // Dictionaries rebuild at most daily, so each response variant is produced
92
+ // once and lives exactly as long as the in-memory dictionary it was made from.
93
+ const serializedCache = new WeakMap<Gaddag, Buffer>();
94
+ const compressedCache = new WeakMap<Gaddag, Promise<Buffer>>();
95
+
96
+ const getSerializedDictionary = (gaddag: Gaddag): Buffer => {
97
+ let serialized = serializedCache.get(gaddag);
98
+
99
+ if (!serialized) {
100
+ // serialize() returns freshly allocated bytes, so the Buffer wraps them without copying.
101
+ const bytes = gaddag.serialize();
102
+ serialized = Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
103
+ serializedCache.set(gaddag, serialized);
104
+ }
105
+
106
+ return serialized;
107
+ };
108
+
109
+ const gzipAsync = promisify(gzip);
110
+
111
+ const getCompressedDictionary = (gaddag: Gaddag): Promise<Buffer> => {
112
+ let compressed = compressedCache.get(gaddag);
113
+
114
+ if (!compressed) {
115
+ compressed = gzipAsync(gaddag.serialize());
116
+ compressedCache.set(gaddag, compressed);
117
+ compressed.catch(() => compressedCache.delete(gaddag));
118
+ }
119
+
120
+ return compressed;
121
+ };
122
+
46
123
  export const config = {
47
124
  api: {
48
- responseLimit: '25mb',
125
+ responseLimit: '50mb',
49
126
  },
50
127
  };
51
128
 
@@ -16,7 +16,7 @@ import {
16
16
  import { type NextApiRequest, type NextApiResponse } from 'next';
17
17
 
18
18
  import { getServerLoggingData, isBoardValid, isCharacterValid } from '@/api';
19
- import { isStringArray } from '@/lib';
19
+ import { isStringArray } from '@/lib/isStringArray';
20
20
 
21
21
  interface RequestData {
22
22
  board: Board;
@@ -45,9 +45,9 @@ const solve = async (request: NextApiRequest, response: NextApiResponse): Promis
45
45
  },
46
46
  });
47
47
 
48
- const trie = await dictionaries.get(locale);
48
+ const gaddag = await dictionaries.get(locale);
49
49
  const tiles = characters.map((character) => new Tile({ character, isBlank: character === BLANK }));
50
- const results = solveScrabble(trie, config, board, tiles);
50
+ const results = solveScrabble(gaddag, config, board, tiles);
51
51
  response.status(200).send(results);
52
52
  } catch (error) {
53
53
  const message = error instanceof Error ? error.message : 'Unknown error';
@@ -30,10 +30,19 @@ const verify = async (request: NextApiRequest, response: NextApiResponse): Promi
30
30
  },
31
31
  });
32
32
 
33
- const trie = await dictionaries.get(locale);
33
+ const gaddag = await dictionaries.get(locale);
34
34
  const words = board.getWords().sort((a, b) => a.localeCompare(b, locale));
35
- const invalidWords = words.filter((word) => !trie.has(word));
36
- const validWords = words.filter((word) => trie.has(word));
35
+ const invalidWords: string[] = [];
36
+ const validWords: string[] = [];
37
+
38
+ for (const word of words) {
39
+ if (gaddag.has(word)) {
40
+ validWords.push(word);
41
+ } else {
42
+ invalidWords.push(word);
43
+ }
44
+ }
45
+
37
46
  response.status(200).send({ invalidWords, validWords });
38
47
  } catch (error) {
39
48
  const message = error instanceof Error ? error.message : 'Unknown error';
@@ -22,6 +22,7 @@
22
22
 
23
23
  .logo {
24
24
  height: var(--logo--height);
25
+ width: auto;
25
26
  user-select: none;
26
27
  }
27
28
 
@@ -0,0 +1,11 @@
1
+ // Generated by scripts/generate-scss-types.ts - do not edit.
2
+ declare const styles: {
3
+ readonly logo: string;
4
+ readonly logoContainer: string;
5
+ readonly nav: string;
6
+ readonly navContent: string;
7
+ readonly navLogo: string;
8
+ readonly solver: string;
9
+ };
10
+
11
+ export default styles;
@@ -1,31 +1,53 @@
1
- /* eslint-disable max-statements */
1
+ /* eslint-disable max-lines, max-statements */
2
2
 
3
+ import { games } from '@scrabble-solver/configs';
3
4
  import { isObject } from '@scrabble-solver/types';
4
5
  import { execSync } from 'child_process';
5
6
  import fs from 'fs';
7
+ import dynamic from 'next/dynamic';
6
8
  import path from 'path';
7
- import { type FunctionComponent, useCallback, useState } from 'react';
8
- import ReactModal from 'react-modal';
9
+ import { type FunctionComponent, useCallback, useEffect, useState } from 'react';
9
10
  import { useDispatch } from 'react-redux';
10
11
 
11
- import { Logo, NavButtons, Solver } from '@/components';
12
- import { useDirection, useEffectOnce, useLanguage, useLocalStorage } from '@/hooks';
13
- import { LOCALE_FEATURES } from '@/i18n';
14
- import {
15
- DictionaryModal,
16
- KeyMapModal,
17
- MenuModal,
18
- RemainingTilesModal,
19
- ResultsModal,
20
- SettingsModal,
21
- WordsModal,
22
- } from '@/modals';
12
+ import { Logo } from '@/components/Logo';
13
+ import { NavButtons } from '@/components/NavButtons';
14
+ import { Solver } from '@/components/Solver';
15
+ import { useDirection } from '@/hooks/useDirection';
16
+ import { useEffectOnce } from '@/hooks/useEffectOnce';
17
+ import { useLanguage } from '@/hooks/useLanguage';
18
+ import { useLocalStorage } from '@/hooks/useLocalStorage';
19
+ import { LOCALE_FEATURES } from '@/i18n/constants';
20
+ import { schedulePreloadModals } from '@/modals/preload';
21
+ import { CONFIG_PENDING_CLASS } from '@/parameters';
23
22
  import { registerServiceWorker } from '@/serviceWorkerManager';
24
- import { initialize, reset, selectConfig, selectLocale, useTypedSelector } from '@/state';
23
+ import { initialize, reset, selectConfig, selectIsHydrated, selectLocale, useTypedSelector } from '@/state';
25
24
 
26
25
  import styles from './index.module.scss';
27
26
 
28
- ReactModal.setAppElement('#__next');
27
+ const DictionaryModal = dynamic(() => import('@/modals/DictionaryModal').then((module) => module.DictionaryModal), {
28
+ ssr: false,
29
+ });
30
+ const KeyMapModal = dynamic(() => import('@/modals/KeyMapModal').then((module) => module.KeyMapModal), {
31
+ ssr: false,
32
+ });
33
+ const MenuModal = dynamic(() => import('@/modals/MenuModal').then((module) => module.MenuModal), {
34
+ ssr: false,
35
+ });
36
+ const RemainingTilesModal = dynamic(
37
+ () => import('@/modals/RemainingTilesModal').then((module) => module.RemainingTilesModal),
38
+ {
39
+ ssr: false,
40
+ },
41
+ );
42
+ const ResultsModal = dynamic(() => import('@/modals/ResultsModal').then((module) => module.ResultsModal), {
43
+ ssr: false,
44
+ });
45
+ const SettingsModal = dynamic(() => import('@/modals/SettingsModal').then((module) => module.SettingsModal), {
46
+ ssr: false,
47
+ });
48
+ const WordsModal = dynamic(() => import('@/modals/WordsModal').then((module) => module.WordsModal), {
49
+ ssr: false,
50
+ });
29
51
 
30
52
  interface Props {
31
53
  version: string;
@@ -37,7 +59,7 @@ const Index: FunctionComponent<Props> = ({ version }) => {
37
59
  const dispatch = useDispatch();
38
60
  const config = useTypedSelector(selectConfig);
39
61
  const locale = useTypedSelector(selectLocale);
40
- const [isClient, setIsClient] = useState(false);
62
+ const isHydrated = useTypedSelector(selectIsHydrated);
41
63
  const [modals, setModals] = useState<Record<Modal, boolean>>({
42
64
  dictionary: false,
43
65
  keyMap: false,
@@ -47,9 +69,26 @@ const Index: FunctionComponent<Props> = ({ version }) => {
47
69
  settings: false,
48
70
  words: false,
49
71
  });
72
+ const [mountedModals, setMountedModals] = useState<Partial<Record<Modal, boolean>>>({});
50
73
 
51
74
  const patchModals = useCallback((patch: Partial<Record<Modal, boolean>>) => {
52
75
  setModals((current) => ({ ...current, ...patch }));
76
+ setMountedModals((current) => {
77
+ const newModals = Object.keys(patch) as Modal[];
78
+ const newOpenedModals = newModals.filter((modal) => patch[modal] && !current[modal]);
79
+
80
+ if (newOpenedModals.length === 0) {
81
+ return current;
82
+ }
83
+
84
+ const mounted = { ...current };
85
+
86
+ for (const modal of newOpenedModals) {
87
+ mounted[modal] = true;
88
+ }
89
+
90
+ return mounted;
91
+ });
53
92
  }, []);
54
93
 
55
94
  const handleClear = useCallback(() => dispatch(reset()), [dispatch]);
@@ -73,20 +112,39 @@ const Index: FunctionComponent<Props> = ({ version }) => {
73
112
  useLanguage(locale);
74
113
  useLocalStorage();
75
114
 
115
+ useEffect(() => {
116
+ const root = document.documentElement;
117
+ const variables = [
118
+ { name: '--board-cols', value: config.boardWidth, defaultValue: games.scrabble.boardWidth },
119
+ { name: '--board-rows', value: config.boardHeight, defaultValue: games.scrabble.boardHeight },
120
+ { name: '--rack-size', value: config.rackSize, defaultValue: games.scrabble.rackSize },
121
+ ];
122
+
123
+ for (const { name, value, defaultValue } of variables) {
124
+ const current = root.style.getPropertyValue(name) || String(defaultValue);
125
+
126
+ if (current !== String(value)) {
127
+ root.style.setProperty(name, String(value));
128
+ }
129
+ }
130
+ }, [config.boardHeight, config.boardWidth, config.rackSize]);
131
+
132
+ useEffect(() => {
133
+ if (isHydrated) {
134
+ document.documentElement.classList.remove(CONFIG_PENDING_CLASS);
135
+ }
136
+ }, [isHydrated]);
137
+
76
138
  useEffectOnce(() => {
77
139
  if (process.env.NODE_ENV === 'production') {
78
140
  // eslint-disable-next-line @typescript-eslint/no-floating-promises
79
141
  registerServiceWorker();
80
142
  }
81
143
 
82
- setIsClient(true);
83
- dispatch(initialize());
144
+ dispatch(initialize({ version }));
145
+ schedulePreloadModals();
84
146
  });
85
147
 
86
- if (!isClient) {
87
- return null;
88
- }
89
-
90
148
  return (
91
149
  <>
92
150
  <nav className={styles.nav}>
@@ -112,28 +170,30 @@ const Index: FunctionComponent<Props> = ({ version }) => {
112
170
  <Solver className={styles.solver} onShowResults={handleShowResults} />
113
171
  </main>
114
172
 
115
- <MenuModal
116
- isOpen={modals.menu}
117
- onClose={handleCloseMenu}
118
- onShowDictionary={handleShowDictionary}
119
- onShowRemainingTiles={handleShowRemainingTiles}
120
- onShowSettings={handleShowSettings}
121
- onShowWords={handleShowWords}
122
- />
173
+ {mountedModals.menu && (
174
+ <MenuModal
175
+ isOpen={modals.menu}
176
+ onClose={handleCloseMenu}
177
+ onShowDictionary={handleShowDictionary}
178
+ onShowRemainingTiles={handleShowRemainingTiles}
179
+ onShowSettings={handleShowSettings}
180
+ onShowWords={handleShowWords}
181
+ />
182
+ )}
123
183
 
124
- <SettingsModal isOpen={modals.settings} onClose={handleCloseSettings} />
184
+ {mountedModals.settings && <SettingsModal isOpen={modals.settings} onClose={handleCloseSettings} />}
125
185
 
126
- <KeyMapModal isOpen={modals.keyMap} onClose={handleCloseKeyMap} />
186
+ {mountedModals.keyMap && <KeyMapModal isOpen={modals.keyMap} onClose={handleCloseKeyMap} />}
127
187
 
128
- <WordsModal isOpen={modals.words} onClose={handleCloseWords} />
188
+ {mountedModals.words && <WordsModal isOpen={modals.words} onClose={handleCloseWords} />}
129
189
 
130
- {config.supportsRemainingTiles && (
190
+ {config.supportsRemainingTiles && mountedModals.remainingTiles && (
131
191
  <RemainingTilesModal isOpen={modals.remainingTiles} onClose={handleCloseRemainingTiles} />
132
192
  )}
133
193
 
134
- <ResultsModal isOpen={modals.results} onClose={handleCloseResults} />
194
+ {mountedModals.results && <ResultsModal isOpen={modals.results} onClose={handleCloseResults} />}
135
195
 
136
- <DictionaryModal isOpen={modals.dictionary} onClose={handleCloseDictionary} />
196
+ {mountedModals.dictionary && <DictionaryModal isOpen={modals.dictionary} onClose={handleCloseDictionary} />}
137
197
  </>
138
198
  );
139
199
  };
@@ -1,5 +1,5 @@
1
1
  'use-client';
2
2
 
3
- import { NotFound } from '@/components';
3
+ import { NotFound } from '@/components/NotFound';
4
4
 
5
5
  export default NotFound;
@@ -1,5 +1,4 @@
1
1
  import variables from '@/styles/variables.module.scss';
2
- import { ResultColumnId } from '@/types';
3
2
 
4
3
  export const BREAKPOINTS = {
5
4
  xs: Number(variables.breakpointXs),
@@ -9,97 +8,52 @@ export const BREAKPOINTS = {
9
8
  xl: Number(variables.breakpointXl),
10
9
  };
11
10
 
12
- export const TRANSITION = 'var(--transition)';
13
-
14
11
  export const GITHUB_PROJECT_URL = 'https://github.com/kamilmielnik/scrabble-solver';
15
12
 
16
- export const TRANSITION_DURATION = Number(variables.transitionDuration);
13
+ // Must match the class name in global.scss
14
+ export const CONFIG_PENDING_CLASS = 'config-pending';
15
+
17
16
  export const TRANSITION_DURATION_LONG = Number(variables.transitionDurationLong);
18
17
 
19
- export const COLOR_BLUE = variables.colorBlue;
20
- export const COLOR_GREEN = variables.colorGreen;
21
- export const COLOR_RED = variables.colorRed;
22
- export const COLOR_YELLOW = variables.colorYellow;
23
-
24
- export const COLOR_BONUS_CHARACTER_1 = variables.colorYellowLight;
25
- export const COLOR_BONUS_CHARACTER_2 = variables.colorGreenLight;
26
- export const COLOR_BONUS_CHARACTER_3 = variables.colorBlueLight;
27
- export const COLOR_BONUS_CHARACTER_5 = variables.colorRedLight;
28
- export const COLOR_BONUS_CHARACTER_MULTIPLIER_2 = variables.colorBonusCharacterMultiplier2;
29
- export const COLOR_BONUS_CHARACTER_MULTIPLIER_3 = variables.colorBonusCharacterMultiplier3;
30
- export const COLOR_BONUS_CHARACTER_MULTIPLIER_4 = variables.colorBonusCharacterMultiplier4;
31
- export const COLOR_BONUS_START = variables.colorVioletLight;
32
- export const COLOR_BONUS_WORD_MULTIPLIER_2 = variables.colorBonusWordMultiplier2;
33
- export const COLOR_BONUS_WORD_MULTIPLIER_3 = variables.colorBonusWordMultiplier3;
34
- export const COLOR_BONUS_WORD_MULTIPLIER_4 = variables.colorBonusWordMultiplier4;
35
- export const COLOR_FILTERED = variables.colorForegroundSecondary;
18
+ export const COLOR_BLUE = 'var(--color--blue)';
19
+ export const COLOR_GREEN = 'var(--color--green)';
20
+ export const COLOR_RED = 'var(--color--red)';
21
+ export const COLOR_YELLOW = 'var(--color--yellow)';
22
+
36
23
  export const COLOR_BACKGROUND = variables.colorBackground;
24
+ export const COLOR_BONUS_START = variables.colorVioletLight;
37
25
 
38
26
  export const COLOR_BONUS_CHARACTER: Record<number, string> = {
39
- 1: COLOR_BONUS_CHARACTER_1,
40
- 2: COLOR_BONUS_CHARACTER_2,
41
- 3: COLOR_BONUS_CHARACTER_3,
42
- 5: COLOR_BONUS_CHARACTER_5,
27
+ 1: variables.colorYellowLight,
28
+ 2: variables.colorGreenLight,
29
+ 3: variables.colorBlueLight,
30
+ 5: variables.colorRedLight,
43
31
  };
44
32
 
45
33
  export const COLOR_BONUS_CHARACTER_MULTIPLIER: Record<number, string> = {
46
- 2: COLOR_BONUS_CHARACTER_MULTIPLIER_2,
47
- 3: COLOR_BONUS_CHARACTER_MULTIPLIER_3,
48
- 4: COLOR_BONUS_CHARACTER_MULTIPLIER_4,
34
+ 2: variables.colorBonusCharacterMultiplier2,
35
+ 3: variables.colorBonusCharacterMultiplier3,
36
+ 4: variables.colorBonusCharacterMultiplier4,
49
37
  };
50
38
 
51
39
  export const COLOR_BONUS_WORD: Record<number, string> = {
52
- 2: COLOR_BONUS_WORD_MULTIPLIER_2,
53
- 3: COLOR_BONUS_WORD_MULTIPLIER_3,
54
- 4: COLOR_BONUS_WORD_MULTIPLIER_4,
40
+ 2: variables.colorBonusWordMultiplier2,
41
+ 3: variables.colorBonusWordMultiplier3,
42
+ 4: variables.colorBonusWordMultiplier4,
55
43
  };
56
44
 
57
- export const SPACING_XS = Number(variables.spacingXs);
58
- export const SPACING_S = Number(variables.spacingS);
59
- export const SPACING_M = Number(variables.spacingM);
60
- export const SPACING_L = Number(variables.spacingL);
61
- export const SPACING_XL = Number(variables.spacingXl);
62
-
63
- export const COMPONENTS_SPACING = SPACING_XL;
64
- export const COMPONENTS_SPACING_SMALL = SPACING_L;
65
-
66
- export const RACK_TILE_SIZE_MAX = 80;
67
-
68
45
  export const BOARD_CELL_ACTIONS_OFFSET = 3;
69
- export const BOARD_CELL_BORDER_WIDTH = 1;
70
- export const BOARD_TILE_FONT_SIZE_MIN = 14;
71
- export const BOARD_TILE_FONT_SIZE_POINTS_MIN = 10;
72
- export const BOARD_TILE_SIZE_MAX = RACK_TILE_SIZE_MAX;
73
46
 
74
- export const BORDER_COLOR = variables.borderColor;
75
47
  export const BORDER_COLOR_LIGHT = variables.borderColorLight;
76
- export const BORDER_RADIUS = Number(variables.borderRadius);
77
48
  export const BORDER_WIDTH = Number(variables.borderWidth);
78
49
 
79
- export const BUTTON_ICON_SIZE = Number(variables.buttonIconSize);
80
- export const BUTTON_PADDING_VERTICAL = SPACING_M;
81
- export const BUTTON_HEIGHT = BUTTON_ICON_SIZE + 2 * BUTTON_PADDING_VERTICAL + 2 * BORDER_WIDTH;
82
-
83
- export const DICTIONARY_HEIGHT = Number(variables.dictionaryHeight);
84
- export const DICTIONARY_HEIGHT_MOBILE = Number(variables.dictionaryHeightMobile);
85
-
86
- export const LOGO_ASPECT_RATIO = 682 / 166;
87
- export const LOGO_HEIGHT = Number(variables.logoHeight);
88
- export const LOGO_HEIGHT_SMALL = Number(variables.logoHeightSmall);
50
+ export const LOGO_HEIGHT = 166;
89
51
  export const LOGO_SRC = '/logo.svg';
52
+ export const LOGO_WIDTH = 682;
90
53
 
91
- export const MODAL_WIDTH = Number(variables.modalWidth);
92
- export const MODAL_HEADER_HEIGHT = 45;
93
-
94
- export const NAV_PADDING = SPACING_L;
95
-
96
- export const TILE_SIZE = 80;
97
-
98
- export const TOOLTIP_DURATION = TRANSITION_DURATION;
54
+ export const TOOLTIP_DURATION = Number(variables.transitionDuration);
99
55
 
100
56
  export const PLAIN_TILES_COLOR_DEFAULT = COLOR_GREEN;
101
- export const PLAIN_TILES_PADDING_HORIZONTAL = 0;
102
- export const PLAIN_TILES_PADDING_VERTICAL = 0;
103
57
  export const PLAIN_TILES_POINTS_COLORS: Record<number, string> = {
104
58
  1: COLOR_YELLOW,
105
59
  2: COLOR_GREEN,
@@ -113,31 +67,8 @@ export const PLAIN_TILES_POINTS_COLORS: Record<number, string> = {
113
67
  10: COLOR_RED,
114
68
  };
115
69
  export const PLAIN_TILES_TILE_MARGIN = 6;
116
- export const PLAIN_TILES_TILE_MAX_ROTATE = 0;
117
- export const PLAIN_TILES_TILE_MAX_SCATTER = 0;
118
70
  export const PLAIN_TILES_TILE_SIZE = 80;
119
- export const PLAIN_TILES_VERSION_TILE_COLOR = COLOR_GREEN;
120
- export const PLAIN_TILES_VERSION_TILE_SIZE = TILE_SIZE;
121
-
122
- export const PROGRESS_COLOR_VALUE = 'var(--color--violet--light)';
123
- export const PROGRESS_COLOR_BACKGROUND = 'var(--color--inactive)';
124
-
125
- export const REMAINING_TILES_TILE_SIZE = 50;
126
-
127
- export const RESULTS_COLUMN_WIDTH: Record<ResultColumnId, number | undefined> = {
128
- [ResultColumnId.BlanksCount]: 55,
129
- [ResultColumnId.ConsonantsCount]: 55,
130
- [ResultColumnId.Coordinates]: 55,
131
- [ResultColumnId.Points]: 80,
132
- [ResultColumnId.TilesCount]: 55,
133
- [ResultColumnId.VowelsCount]: 55,
134
- [ResultColumnId.Word]: undefined,
135
- [ResultColumnId.WordsCount]: 55,
136
- };
137
- export const RESULTS_ITEM_HEIGHT = Number(variables.resultsItemHeight);
138
71
 
139
- export const RESULTS_HEADER_HEIGHT = RESULTS_ITEM_HEIGHT;
140
-
141
- export const SOLVER_COLUMN_WIDTH = Number(variables.solverColumnWidth);
72
+ export const RESULTS_ITEM_HEIGHT = Number(variables.resultsItemHeight);
142
73
 
143
- export const TEXT_INPUT_HEIGHT = Number(variables.textInputHeight);
74
+ export const RESULTS_OVERSCAN_COUNT = 10;
@@ -1,19 +1,25 @@
1
- import { type BoardJson, type Locale, Result, type ResultJson } from '@scrabble-solver/types';
1
+ import { Board, type BoardJson, type Game, type Locale, Result, type ResultJson } from '@scrabble-solver/types';
2
+
3
+ import { solveLocally } from '@/solver-worker';
2
4
 
3
5
  import { fetchJson } from './fetchJson';
4
6
 
5
7
  interface Payload {
6
8
  board: BoardJson;
7
9
  characters: string[];
8
- game: string;
10
+ game: Game;
9
11
  locale: Locale;
10
12
  }
11
13
 
12
14
  export const solve = async ({ board, characters, game, locale }: Payload): Promise<Result[]> => {
13
- const json = await fetchJson<ResultJson[]>('/api/solve', {
14
- method: 'POST',
15
- body: JSON.stringify({ board, characters, game, locale }),
16
- });
15
+ const payload = { board, characters, game, locale };
16
+ const json =
17
+ (await solveLocally(payload)) ??
18
+ (await fetchJson<ResultJson[]>('/api/solve', {
19
+ method: 'POST',
20
+ body: JSON.stringify(payload),
21
+ }));
17
22
 
18
- return json.map(Result.fromJson);
23
+ const decodedBoard = Board.fromJson(board);
24
+ return json.map((result) => Result.fromJson(result, decodedBoard));
19
25
  };
@@ -1,10 +1,12 @@
1
- import { type BoardJson, type Locale } from '@scrabble-solver/types';
1
+ import { type BoardJson, type Game, type Locale } from '@scrabble-solver/types';
2
+
3
+ import { verifyLocally } from '@/solver-worker';
2
4
 
3
5
  import { fetchJson } from './fetchJson';
4
6
 
5
7
  interface Payload {
6
8
  board: BoardJson;
7
- game: string;
9
+ game: Game;
8
10
  locale: Locale;
9
11
  }
10
12
 
@@ -14,8 +16,12 @@ interface Response {
14
16
  }
15
17
 
16
18
  export const verify = async ({ board, game, locale }: Payload): Promise<Response> => {
17
- return fetchJson<Response>('/api/verify', {
18
- method: 'POST',
19
- body: JSON.stringify({ board, game, locale }),
20
- });
19
+ const payload = { board, game, locale };
20
+ return (
21
+ (await verifyLocally(payload)) ??
22
+ fetchJson<Response>('/api/verify', {
23
+ method: 'POST',
24
+ body: JSON.stringify(payload),
25
+ })
26
+ );
21
27
  };