@scrabble-solver/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 (370) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +22 -20
  3. package/.next/cache/.previewinfo +1 -1
  4. package/.next/cache/.rscinfo +1 -1
  5. package/.next/cache/.tsbuildinfo +1 -1
  6. package/.next/cache/webpack/client-production/0.pack +0 -0
  7. package/.next/cache/webpack/client-production/index.pack +0 -0
  8. package/.next/cache/webpack/client-production/index.pack.old +0 -0
  9. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  10. package/.next/cache/webpack/edge-server-production/index.pack.old +0 -0
  11. package/.next/cache/webpack/server-production/0.pack +0 -0
  12. package/.next/cache/webpack/server-production/index.pack +0 -0
  13. package/.next/cache/webpack/server-production/index.pack.old +0 -0
  14. package/.next/diagnostics/framework.json +1 -1
  15. package/.next/dynamic-css-manifest.json +8 -1
  16. package/.next/next-minimal-server.js.nft.json +1 -1
  17. package/.next/next-server.js.nft.json +1 -1
  18. package/.next/prerender-manifest.json +4 -4
  19. package/.next/react-loadable-manifest.json +176 -1
  20. package/.next/required-server-files.js +3 -2
  21. package/.next/required-server-files.json +3 -2
  22. package/.next/routes-manifest.json +1 -1
  23. package/.next/server/chunks/30.js +1 -1
  24. package/.next/server/chunks/309.js +1 -0
  25. package/.next/server/chunks/316.js +1 -0
  26. package/.next/server/chunks/344.js +1 -0
  27. package/.next/server/chunks/371.js +1 -0
  28. package/.next/server/chunks/392.js +1 -1
  29. package/.next/server/chunks/465.js +1 -0
  30. package/.next/server/chunks/546.js +1 -0
  31. package/.next/server/chunks/623.js +1 -0
  32. package/.next/server/chunks/624.js +1 -0
  33. package/.next/server/chunks/641.js +1 -0
  34. package/.next/server/chunks/671.js +1 -1
  35. package/.next/server/chunks/692.js +1 -0
  36. package/.next/server/chunks/705.js +1 -0
  37. package/.next/server/chunks/712.js +1 -1
  38. package/.next/server/chunks/846.js +1 -0
  39. package/.next/server/chunks/853.js +15 -0
  40. package/.next/server/chunks/886.js +1 -0
  41. package/.next/server/chunks/916.js +1 -0
  42. package/.next/server/chunks/953.js +1 -0
  43. package/.next/server/chunks/961.js +1 -0
  44. package/.next/server/chunks/968.js +1 -0
  45. package/.next/server/dynamic-css-manifest.js +1 -1
  46. package/.next/server/middleware-build-manifest.js +1 -1
  47. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  48. package/.next/server/pages/404.html +28 -1
  49. package/.next/server/pages/500.html +28 -1
  50. package/.next/server/pages/_app.js +1 -1
  51. package/.next/server/pages/_app.js.nft.json +1 -1
  52. package/.next/server/pages/_document.js +28 -1
  53. package/.next/server/pages/_document.js.nft.json +1 -1
  54. package/.next/server/pages/_error.js +28 -1
  55. package/.next/server/pages/_error.js.nft.json +1 -1
  56. package/.next/server/pages/api/dictionary/[locale]/[word].js +1 -1
  57. package/.next/server/pages/api/dictionary/[locale]/[word].js.nft.json +1 -1
  58. package/.next/server/pages/api/dictionary/[locale].js +1 -1
  59. package/.next/server/pages/api/dictionary/[locale].js.nft.json +1 -1
  60. package/.next/server/pages/api/solve.js +1 -1
  61. package/.next/server/pages/api/solve.js.nft.json +1 -1
  62. package/.next/server/pages/api/verify.js +1 -1
  63. package/.next/server/pages/api/verify.js.nft.json +1 -1
  64. package/.next/server/pages/api/visit.js.nft.json +1 -1
  65. package/.next/server/pages/index.html +28 -1
  66. package/.next/server/pages/index.js +30 -1
  67. package/.next/server/pages/index.js.nft.json +1 -1
  68. package/.next/server/pages/index.json +1 -1
  69. package/.next/server/pages/not-found.html +28 -1
  70. package/.next/server/pages/not-found.js.nft.json +1 -1
  71. package/.next/server/pages-manifest.json +1 -1
  72. package/.next/server/webpack-api-runtime.js +1 -1
  73. package/.next/server/webpack-runtime.js +1 -1
  74. package/.next/static/FL82obwzFHRzvV6z76I-U/_buildManifest.js +1 -0
  75. package/.next/static/chunks/101-829ab8a8d310e7a0.js +3 -0
  76. package/.next/static/chunks/106.e414e88694add27f.js +1 -0
  77. package/.next/static/chunks/127.125d896a19061d71.js +1 -0
  78. package/.next/static/chunks/18.8b91e137d239e15c.js +1 -0
  79. package/.next/static/chunks/277.6785dfaf22fdb0b7.js +1 -0
  80. package/.next/static/chunks/307.67f52f13e3d60d4e.js +1 -0
  81. package/.next/static/chunks/341.79535ba85bf1986f.js +1 -0
  82. package/.next/static/chunks/363.01eed3233f92b6a4.js +1 -0
  83. package/.next/static/chunks/422.1559ae6756912ca5.js +1 -0
  84. package/.next/static/chunks/541.dcd9e8b804f88da5.js +1 -0
  85. package/.next/static/chunks/583.7a46807be14c377e.js +1 -0
  86. package/.next/static/chunks/631.98d42abad0a60af6.js +1 -0
  87. package/.next/static/chunks/663.d2c9ca36b26695b8.js +1 -0
  88. package/.next/static/chunks/711.ba7b8f900dfd40d0.js +1 -0
  89. package/.next/static/chunks/744.b06c9a3de4a1d877.js +1 -0
  90. package/.next/static/chunks/820.97b82f751ca49579.js +1 -0
  91. package/.next/static/chunks/865.a9b563a45848a83c.js +1 -0
  92. package/.next/static/chunks/912.ff8037ba9d4db5c8.js +1 -0
  93. package/.next/static/chunks/939.19b33a3d3c351d73.js +1 -0
  94. package/.next/static/chunks/990.61296e5870b91f11.js +1 -0
  95. package/.next/static/chunks/framework-626cbd48ac5aca57.js +1 -0
  96. package/.next/static/chunks/main-b92e08f3fc96dd8d.js +5 -0
  97. package/.next/static/chunks/pages/_app-ba5d628e81a15461.js +1 -0
  98. package/.next/static/chunks/pages/{_error-afeda7c5231b6c3c.js → _error-f0290a98eb3ed0ec.js} +1 -1
  99. package/.next/static/chunks/pages/index-5f9fa6ac3cd3d97b.js +1 -0
  100. package/.next/static/chunks/pages/not-found-23d61fd3ed791cad.js +1 -0
  101. package/.next/static/chunks/webpack-e34c3ae12275e978.js +1 -0
  102. package/.next/static/css/2d03f0da2c678dfc.css +1 -0
  103. package/.next/static/css/7b6724d2df70f48f.css +1 -0
  104. package/.next/static/css/abc2425d3ba607bc.css +1 -0
  105. package/.next/static/css/b736be3bd02b5d99.css +1 -0
  106. package/.next/static/css/b74cd7de82dabcdd.css +1 -0
  107. package/.next/static/css/c403ce739a9c0d83.css +1 -0
  108. package/.next/static/css/ca311e6c030663d4.css +1 -0
  109. package/.next/static/css/dee878eb64099d92.css +1 -0
  110. package/.next/static/css/fbfdce70731d0d2b.css +1 -0
  111. package/.next/trace +21 -21
  112. package/.next/trace-build +1 -1
  113. package/empty-module.js +2 -0
  114. package/next.config.js +13 -8
  115. package/package.json +35 -16
  116. package/public/llms.txt +11 -0
  117. package/public/robots.txt +4 -0
  118. package/scripts/generate-scss-types.ts +112 -0
  119. package/src/@types/scss.d.ts +6 -9
  120. package/src/@types/svg.d.ts +1 -1
  121. package/src/components/Alert/Alert.module.scss.d.ts +13 -0
  122. package/src/components/Alert/Alert.tsx +4 -1
  123. package/src/components/Badge/Badge.module.scss.d.ts +6 -0
  124. package/src/components/Board/Board.module.scss +10 -0
  125. package/src/components/Board/Board.module.scss.d.ts +17 -0
  126. package/src/components/Board/Board.tsx +14 -26
  127. package/src/components/Board/BoardPure.tsx +54 -49
  128. package/src/components/Board/components/Actions/Actions.module.scss +18 -18
  129. package/src/components/Board/components/Actions/Actions.module.scss.d.ts +7 -0
  130. package/src/components/Board/components/Actions/Actions.tsx +6 -3
  131. package/src/components/Board/components/Actions/lib.ts +3 -1
  132. package/src/components/Board/components/Cell/Cell.module.scss.d.ts +13 -0
  133. package/src/components/Board/components/Cell/Cell.tsx +32 -34
  134. package/src/components/Board/components/InputPrompt/InputPrompt.module.scss.d.ts +10 -0
  135. package/src/components/Board/components/InputPrompt/InputPrompt.tsx +1 -1
  136. package/src/components/Board/components/ToggleDirectionButton/ToggleDirectionButton.module.scss.d.ts +8 -0
  137. package/src/components/Board/components/ToggleDirectionButton/ToggleDirectionButton.tsx +2 -2
  138. package/src/components/Board/getBoardBackground.ts +175 -0
  139. package/src/components/Board/hooks/index.ts +0 -1
  140. package/src/components/Board/hooks/useBoardStyle.ts +10 -20
  141. package/src/components/Board/hooks/useFloatingActions.ts +3 -6
  142. package/src/components/Board/hooks/useGrid.ts +23 -9
  143. package/src/components/Board/selectors.ts +1 -1
  144. package/src/components/Button/Button.module.scss.d.ts +12 -0
  145. package/src/components/Dictionary/Dictionary.module.scss +8 -22
  146. package/src/components/Dictionary/Dictionary.module.scss.d.ts +14 -0
  147. package/src/components/Dictionary/Dictionary.tsx +1 -10
  148. package/src/components/DictionaryInput/DictionaryInput.module.scss.d.ts +7 -0
  149. package/src/components/DictionaryInput/DictionaryInput.tsx +1 -1
  150. package/src/components/EmptyState/EmptyState.module.scss.d.ts +7 -0
  151. package/src/components/EmptyState/EmptyState.tsx +1 -1
  152. package/src/components/IconButton/IconButton.module.scss.d.ts +8 -0
  153. package/src/components/Key/Key.module.scss.d.ts +6 -0
  154. package/src/components/Keys/Arrows/Arrows.module.scss.d.ts +11 -0
  155. package/src/components/Keys/Arrows/Arrows.tsx +4 -1
  156. package/src/components/Keys/index.tsx +1 -1
  157. package/src/components/Loading/Loading.module.scss.d.ts +9 -0
  158. package/src/components/Loading/Loading.tsx +1 -1
  159. package/src/components/Logo/Logo.tsx +4 -9
  160. package/src/components/Logo/LogoBlueprint.tsx +1 -0
  161. package/src/components/Modal/Modal.module.scss.d.ts +15 -0
  162. package/src/components/Modal/Modal.tsx +16 -3
  163. package/src/components/Modal/components/Section/Section.module.scss.d.ts +7 -0
  164. package/src/components/NavButtons/NavButtons.module.scss +20 -0
  165. package/src/components/NavButtons/NavButtons.module.scss.d.ts +13 -0
  166. package/src/components/NavButtons/NavButtons.tsx +29 -45
  167. package/src/components/NotFound/NotFound.module.scss.d.ts +9 -0
  168. package/src/components/NotFound/NotFound.tsx +1 -1
  169. package/src/components/PlainTiles/PlainTiles.module.scss.d.ts +11 -0
  170. package/src/components/PlainTiles/PlainTiles.tsx +0 -1
  171. package/src/components/PlainTiles/Tile.tsx +3 -4
  172. package/src/components/PlainTiles/lib.ts +4 -19
  173. package/src/components/PlainTiles/types.ts +0 -1
  174. package/src/components/Progress/Progress.module.scss +7 -0
  175. package/src/components/Progress/Progress.module.scss.d.ts +6 -0
  176. package/src/components/Progress/Progress.tsx +2 -11
  177. package/src/components/Rack/Rack.module.scss +3 -0
  178. package/src/components/Rack/Rack.module.scss.d.ts +10 -0
  179. package/src/components/Rack/Rack.tsx +8 -11
  180. package/src/components/Rack/components/InputPrompt/InputPrompt.module.scss +2 -0
  181. package/src/components/Rack/components/InputPrompt/InputPrompt.module.scss.d.ts +7 -0
  182. package/src/components/Rack/components/InputPrompt/InputPrompt.tsx +1 -13
  183. package/src/components/Rack/components/InputPrompt/lib.ts +1 -1
  184. package/src/components/Rack/components/RackTile/RackTile.module.scss.d.ts +6 -0
  185. package/src/components/Rack/components/RackTile/RackTile.tsx +5 -4
  186. package/src/components/Rack/selectors.ts +1 -1
  187. package/src/components/Radio/Radio.module.scss.d.ts +12 -0
  188. package/src/components/Results/Cell.tsx +3 -12
  189. package/src/components/Results/Header.tsx +9 -18
  190. package/src/components/Results/HeaderButton.tsx +4 -5
  191. package/src/components/Results/Result.tsx +4 -15
  192. package/src/components/Results/Results.module.scss +4 -7
  193. package/src/components/Results/Results.module.scss.d.ts +27 -0
  194. package/src/components/Results/Results.tsx +14 -5
  195. package/src/components/Results/SolveButton.tsx +1 -1
  196. package/src/components/Results/types.ts +3 -3
  197. package/src/components/ResultsInput/ResultsInput.module.scss.d.ts +7 -0
  198. package/src/components/ResultsInput/ResultsInput.tsx +1 -1
  199. package/src/components/Solver/Solver.module.scss +6 -5
  200. package/src/components/Solver/Solver.module.scss.d.ts +20 -0
  201. package/src/components/Solver/Solver.tsx +23 -24
  202. package/src/components/Solver/components/InsertButton/InsertButton.module.scss.d.ts +7 -0
  203. package/src/components/Solver/components/InsertButton/InsertButton.tsx +1 -1
  204. package/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.module.scss.d.ts +18 -0
  205. package/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.tsx +3 -1
  206. package/src/components/Spinner/Spinner.module.scss.d.ts +10 -0
  207. package/src/components/Tile/Tile.module.scss +3 -0
  208. package/src/components/Tile/Tile.module.scss.d.ts +19 -0
  209. package/src/components/Tile/Tile.tsx +5 -14
  210. package/src/components/Tile/TilePure.tsx +2 -12
  211. package/src/components/Tooltip/Tooltip.module.scss.d.ts +7 -0
  212. package/src/components/Tooltip/Tooltip.tsx +14 -3
  213. package/src/components/Tooltip/useTooltip.ts +2 -1
  214. package/src/hooks/useColumns.ts +4 -7
  215. package/src/hooks/useDeferredRender.ts +20 -0
  216. package/src/hooks/useDirection.ts +4 -3
  217. package/src/hooks/useLanguage.ts +2 -2
  218. package/src/hooks/useLocalStorage.ts +32 -8
  219. package/src/hooks/useMedia.ts +26 -26
  220. package/src/i18n/constants.ts +2 -15
  221. package/src/i18n/i18n.ts +18 -17
  222. package/src/i18n/languages/english.json +0 -1
  223. package/src/i18n/languages/french.json +0 -1
  224. package/src/i18n/languages/german.json +0 -1
  225. package/src/i18n/languages/persian.json +0 -1
  226. package/src/i18n/languages/polish.json +0 -1
  227. package/src/i18n/languages/romanian.json +0 -1
  228. package/src/i18n/languages/spanish.json +0 -1
  229. package/src/i18n/languages/turkish.json +0 -1
  230. package/src/i18n/localeIcons.ts +24 -0
  231. package/src/lib/localeTransliterate.test.ts +5 -0
  232. package/src/lib/localeTransliterate.ts +26 -6
  233. package/src/lib/waitForIdleOrFirstIntent.ts +33 -0
  234. package/src/modals/DictionaryModal/DictionaryModal.module.scss.d.ts +8 -0
  235. package/src/modals/DictionaryModal/DictionaryModal.tsx +3 -1
  236. package/src/modals/KeyMapModal/KeyMapModal.tsx +3 -1
  237. package/src/modals/KeyMapModal/components/Mapping/Mapping.module.scss.d.ts +11 -0
  238. package/src/modals/MenuModal/MenuModal.module.scss +5 -0
  239. package/src/modals/MenuModal/MenuModal.module.scss.d.ts +10 -0
  240. package/src/modals/MenuModal/MenuModal.tsx +16 -5
  241. package/src/modals/RemainingTilesModal/RemainingTilesModal.module.scss +4 -1
  242. package/src/modals/RemainingTilesModal/RemainingTilesModal.module.scss.d.ts +9 -0
  243. package/src/modals/RemainingTilesModal/RemainingTilesModal.tsx +4 -6
  244. package/src/modals/RemainingTilesModal/components/Character/Character.module.scss +1 -0
  245. package/src/modals/RemainingTilesModal/components/Character/Character.module.scss.d.ts +12 -0
  246. package/src/modals/RemainingTilesModal/components/Character/Character.tsx +5 -12
  247. package/src/modals/ResultsModal/ResultsModal.module.scss.d.ts +8 -0
  248. package/src/modals/ResultsModal/ResultsModal.tsx +8 -4
  249. package/src/modals/SettingsModal/SettingsModal.tsx +2 -2
  250. package/src/modals/SettingsModal/components/AutoGroupTilesSetting/AutoGroupTilesSetting.module.scss.d.ts +7 -0
  251. package/src/modals/SettingsModal/components/AutoGroupTilesSetting/AutoGroupTilesSetting.tsx +1 -1
  252. package/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.module.scss.d.ts +7 -0
  253. package/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.tsx +1 -1
  254. package/src/modals/SettingsModal/components/HighlightUnreachableCellsSetting/HighlightUnreachableCellsSetting.module.scss.d.ts +7 -0
  255. package/src/modals/SettingsModal/components/HighlightUnreachableCellsSetting/HighlightUnreachableCellsSetting.tsx +1 -1
  256. package/src/modals/SettingsModal/components/InputModeSetting/InputModeSetting.module.scss.d.ts +7 -0
  257. package/src/modals/SettingsModal/components/InputModeSetting/InputModeSetting.tsx +1 -1
  258. package/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.module.scss.d.ts +8 -0
  259. package/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.tsx +24 -21
  260. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/RemoveCellFiltersSetting.module.scss.d.ts +7 -0
  261. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/RemoveCellFiltersSetting.tsx +1 -1
  262. package/src/modals/SettingsModal/components/ShowCoordinatesSetting/ShowCoordinatesSetting.module.scss.d.ts +7 -0
  263. package/src/modals/SettingsModal/components/ShowCoordinatesSetting/ShowCoordinatesSetting.tsx +1 -5
  264. package/src/modals/WordsModal/WordsModal.module.scss.d.ts +11 -0
  265. package/src/modals/WordsModal/WordsModal.tsx +4 -2
  266. package/src/modals/preload.ts +24 -0
  267. package/src/pages/_app.tsx +5 -8
  268. package/src/pages/_document.tsx +91 -5
  269. package/src/pages/api/dictionary/[locale]/[word].ts +2 -2
  270. package/src/pages/api/dictionary/[locale]/index.ts +80 -3
  271. package/src/pages/api/solve.ts +3 -3
  272. package/src/pages/api/verify.ts +12 -3
  273. package/src/pages/index.module.scss +1 -0
  274. package/src/pages/index.module.scss.d.ts +11 -0
  275. package/src/pages/index.tsx +98 -38
  276. package/src/pages/not-found.tsx +1 -1
  277. package/src/parameters/index.ts +24 -93
  278. package/src/sdk/solve.ts +13 -7
  279. package/src/sdk/verify.ts +12 -6
  280. package/src/service-worker/appShell.test.ts +86 -0
  281. package/src/service-worker/appShell.ts +39 -0
  282. package/src/service-worker/index.ts +4 -5
  283. package/src/serviceWorkerManager.ts +5 -19
  284. package/src/solver-worker/client.test.ts +151 -0
  285. package/src/solver-worker/client.ts +106 -0
  286. package/src/solver-worker/dictionaries/constants.ts +9 -0
  287. package/src/solver-worker/dictionaries/getDictionary.ts +21 -0
  288. package/src/solver-worker/dictionaries/index.ts +2 -0
  289. package/src/solver-worker/dictionaries/revalidateDictionary.test.ts +199 -0
  290. package/src/solver-worker/dictionaries/revalidateDictionary.ts +86 -0
  291. package/src/solver-worker/dictionaries/revalidatedAt.ts +43 -0
  292. package/src/solver-worker/getGaddag.test.ts +109 -0
  293. package/src/solver-worker/getGaddag.ts +62 -0
  294. package/src/solver-worker/index.ts +1 -0
  295. package/src/solver-worker/index.worker.ts +124 -0
  296. package/src/solver-worker/messages.ts +20 -0
  297. package/src/state/actions.ts +1 -1
  298. package/src/state/app/index.ts +4 -0
  299. package/src/state/app/initialState.ts +6 -0
  300. package/src/state/app/selectors.ts +5 -0
  301. package/src/state/app/slice.ts +20 -0
  302. package/src/state/app/types.ts +4 -0
  303. package/src/state/board/initialState.ts +1 -2
  304. package/src/state/i18n/index.ts +4 -0
  305. package/src/state/i18n/initialState.ts +5 -0
  306. package/src/state/i18n/selectors.ts +3 -0
  307. package/src/state/i18n/slice.ts +16 -0
  308. package/src/state/i18n/types.ts +7 -0
  309. package/src/state/index.ts +3 -0
  310. package/src/state/lib.ts +1 -1
  311. package/src/state/localStorage.ts +86 -29
  312. package/src/state/rack/initialState.ts +1 -2
  313. package/src/state/rack/slice.ts +4 -1
  314. package/src/state/results/lib.ts +5 -5
  315. package/src/state/results/selectors.ts +1 -1
  316. package/src/state/sagas.ts +139 -13
  317. package/src/state/selectors.ts +1 -1
  318. package/src/state/settings/initialState.ts +7 -10
  319. package/src/state/settings/selectors.ts +7 -2
  320. package/src/state/settings/slice.ts +5 -2
  321. package/src/state/store.ts +4 -0
  322. package/src/state/types.ts +4 -0
  323. package/src/state/useTypedStore.ts +6 -0
  324. package/src/styles/_tokens.scss +1 -0
  325. package/src/styles/global.scss +9 -0
  326. package/src/styles/variables.module.scss +0 -21
  327. package/src/styles/variables.module.scss.d.ts +27 -0
  328. package/src/styles/variables.scss +46 -2
  329. package/src/types/api.ts +1 -2
  330. package/src/types/index.ts +1 -2
  331. package/tsconfig.json +4 -0
  332. package/tsconfig.tsbuildinfo +1 -1
  333. package/.next/server/chunks/318.js +0 -3
  334. package/.next/server/chunks/791.js +0 -15
  335. package/.next/static/chunks/framework-3cf15b8041c59dd3.js +0 -1
  336. package/.next/static/chunks/main-852475ca502b4e49.js +0 -5
  337. package/.next/static/chunks/pages/_app-a5bbe02710f13d05.js +0 -7
  338. package/.next/static/chunks/pages/index-ec0f6aeeaf7be227.js +0 -1
  339. package/.next/static/chunks/pages/not-found-9e076427bad69d90.js +0 -1
  340. package/.next/static/chunks/webpack-1a7a166b34ed8d24.js +0 -1
  341. package/.next/static/css/0af35adb4bab56f0.css +0 -2
  342. package/.next/static/css/a78e04fe95452380.css +0 -1
  343. package/.next/static/vYpMmuC_yEurZGcyGVnLf/_buildManifest.js +0 -1
  344. package/src/app-layout/AppLayoutContext.tsx +0 -25
  345. package/src/app-layout/index.ts +0 -1
  346. package/src/app-layout/useAppLayoutValue.ts +0 -112
  347. package/src/components/Board/hooks/useBackgroundImage.tsx +0 -279
  348. package/src/components/index.ts +0 -26
  349. package/src/hooks/index.ts +0 -12
  350. package/src/hooks/useOnWindowResize.ts +0 -11
  351. package/src/hooks/useViewportSize.ts +0 -17
  352. package/src/i18n/index.ts +0 -2
  353. package/src/icons/Flag.svg +0 -4
  354. package/src/icons/Star.svg +0 -4
  355. package/src/icons/index.ts +0 -49
  356. package/src/lib/getTileSizes.ts +0 -13
  357. package/src/lib/index.ts +0 -24
  358. package/src/modals/index.ts +0 -7
  359. package/src/sdk/getDictionary.ts +0 -9
  360. package/src/service-worker/average.ts +0 -7
  361. package/src/service-worker/dictionaries/constants.ts +0 -5
  362. package/src/service-worker/dictionaries/getDictionary.ts +0 -20
  363. package/src/service-worker/dictionaries/index.ts +0 -2
  364. package/src/service-worker/dictionaries/revalidateDictionary.ts +0 -33
  365. package/src/service-worker/getTrie.ts +0 -24
  366. package/src/service-worker/routeSolveRequests.ts +0 -91
  367. package/src/service-worker/routeVerifyRequests.ts +0 -37
  368. /package/.next/static/{vYpMmuC_yEurZGcyGVnLf → FL82obwzFHRzvV6z76I-U}/_ssgManifest.js +0 -0
  369. /package/src/{service-worker → solver-worker}/dictionaries/expirationManager.ts +0 -0
  370. /package/src/{service-worker → solver-worker}/dictionaries/getDictionaryUrl.ts +0 -0
@@ -5,17 +5,23 @@
5
5
 
6
6
  import { type PayloadAction } from '@reduxjs/toolkit';
7
7
  import { hasConfig, languages } from '@scrabble-solver/configs';
8
- import { Board, type Locale, type Result } from '@scrabble-solver/types';
9
- import { call, delay, put, select, takeEvery, takeLatest } from 'redux-saga/effects';
8
+ import { Board, Locale, type Result } from '@scrabble-solver/types';
9
+ import { call, delay, put, select, spawn, takeEvery, takeLatest } from 'redux-saga/effects';
10
10
 
11
- import { LOCALE_FEATURES } from '@/i18n';
12
- import { memoize } from '@/lib';
11
+ import { LOCALE_FEATURES } from '@/i18n/constants';
12
+ import { loadTranslations } from '@/i18n/i18n';
13
+ import { memoize } from '@/lib/memoize';
14
+ import { waitForIdleOrFirstIntent } from '@/lib/waitForIdleOrFirstIntent';
13
15
  import { findWordDefinitions, solve, verify, visit } from '@/sdk';
16
+ import { prefetchDictionary } from '@/solver-worker';
14
17
 
15
18
  import { initialize, reset } from './actions';
19
+ import { appSlice, selectVersion } from './app';
16
20
  import { boardSlice, selectBoard } from './board';
17
21
  import { cellFiltersSlice, selectCellFilter } from './cellFilters';
18
22
  import { dictionarySlice, selectDictionary } from './dictionary';
23
+ import { i18nSlice, selectLoadedTranslations } from './i18n';
24
+ import { localStorage } from './localStorage';
19
25
  import { rackSlice, selectCharacters, selectRack } from './rack';
20
26
  import { resultsSlice } from './results';
21
27
  import {
@@ -24,8 +30,11 @@ import {
24
30
  selectLocale,
25
31
  selectLocaleAutoGroupTiles,
26
32
  selectRemoveCellFilters,
33
+ settingsInitialState,
27
34
  settingsSlice,
35
+ type SettingsState,
28
36
  } from './settings';
37
+ import { guessLocale } from './settings/lib';
29
38
  import { solveSlice } from './solve';
30
39
  import { verifySlice } from './verify';
31
40
 
@@ -41,7 +50,7 @@ export function* rootSaga(): AnyGenerator {
41
50
  yield takeEvery(boardSlice.actions.changeCellValue.type, onCellValueChange);
42
51
  yield takeEvery([rackSlice.actions.changeCharacter.type, rackSlice.actions.changeCharacters.type], onRackValueChange);
43
52
  yield takeEvery(resultsSlice.actions.applyResult.type, onApplyResult);
44
- yield takeEvery(resultsSlice.actions.changeResultCandidate.type, onResultCandidateChange);
53
+ yield takeLatest(resultsSlice.actions.changeResultCandidate.type, onResultCandidateChange);
45
54
  yield takeEvery(settingsSlice.actions.changeGame.type, onGameChange);
46
55
  yield takeEvery(settingsSlice.actions.changeLocale.type, onLocaleChange);
47
56
  yield takeLatest(dictionarySlice.actions.submit.type, onDictionarySubmit);
@@ -118,10 +127,22 @@ function* onDictionarySubmit(): AnyGenerator {
118
127
  }
119
128
  }
120
129
 
121
- function* onInitialize(): AnyGenerator {
130
+ function* onInitialize({ payload }: PayloadAction<{ version: string }>): AnyGenerator {
131
+ try {
132
+ yield* hydratePersistedState(payload.version);
133
+ // oxlint-disable-next-line no-empty
134
+ } catch {
135
+ } finally {
136
+ yield put(appSlice.actions.hydrated());
137
+ }
138
+
122
139
  const board = yield select(selectBoard);
140
+ const locale = yield select(selectLocale);
123
141
 
124
- yield call(visit);
142
+ yield spawn(prefetchDictionaryWhenIdle);
143
+ yield spawn(loadLocaleTranslations, locale);
144
+ yield spawn(preloadTranslationsWhenIdle);
145
+ yield spawn(visitWhenIdle);
125
146
 
126
147
  if (!board.isEmpty()) {
127
148
  yield* resetRack();
@@ -129,6 +150,100 @@ function* onInitialize(): AnyGenerator {
129
150
  }
130
151
  }
131
152
 
153
+ function* hydratePersistedState(version: string): AnyGenerator {
154
+ const isTouchScreen = globalThis.matchMedia?.('(hover: none)').matches ?? false;
155
+ const settings: Pick<SettingsState, 'game' | 'inputMode' | 'locale'> & Partial<SettingsState> = {
156
+ game: settingsInitialState.game,
157
+ inputMode: isTouchScreen ? ('touchscreen' as const) : ('keyboard' as const),
158
+ locale: guessLocale(),
159
+ ...localStorage.getSettings(),
160
+ };
161
+
162
+ if (!hasConfig(settings.game, settings.locale)) {
163
+ const localeDefault = Object.values(languages).find((config) => config.locale === settings.locale);
164
+ settings.game = localeDefault?.game ?? settingsInitialState.game;
165
+ settings.locale = localeDefault?.locale ?? guessLocale();
166
+ }
167
+
168
+ yield put(settingsSlice.actions.init(settings));
169
+ yield* hydratePersistedTranslations(settings.locale, version);
170
+
171
+ const config = yield select(selectConfig);
172
+ const currentBoard: Board = yield select(selectBoard);
173
+ const board = localStorage.getBoard();
174
+
175
+ if (board) {
176
+ yield put(boardSlice.actions.init(board));
177
+ } else if (currentBoard.rows.length !== config.boardHeight || currentBoard.rows[0].length !== config.boardWidth) {
178
+ yield put(boardSlice.actions.init(Board.create(config.boardWidth, config.boardHeight)));
179
+ }
180
+
181
+ const currentRack = yield select(selectRack);
182
+ const rack = localStorage.getRack();
183
+
184
+ if (rack) {
185
+ yield put(rackSlice.actions.init(rack));
186
+ } else if (currentRack.length !== config.rackSize) {
187
+ yield put(rackSlice.actions.init(Array(config.rackSize).fill(null)));
188
+ }
189
+ }
190
+
191
+ // Applied synchronously so the first post-hydration paint is already translated
192
+ function* hydratePersistedTranslations(locale: Locale, version: string): AnyGenerator {
193
+ const translations = localStorage.getTranslations(locale, version);
194
+
195
+ if (translations) {
196
+ yield put(i18nSlice.actions.loaded({ locale, translations }));
197
+ }
198
+ }
199
+
200
+ function* visitWhenIdle(): AnyGenerator {
201
+ yield call(waitForIdleOrFirstIntent);
202
+ yield call(visit);
203
+ }
204
+
205
+ function* prefetchDictionaryWhenIdle(): AnyGenerator {
206
+ yield call(waitForIdleOrFirstIntent);
207
+ const locale = yield select(selectLocale);
208
+ yield call(prefetchDictionary, locale);
209
+ }
210
+
211
+ function* loadLocaleTranslations(locale: Locale): AnyGenerator {
212
+ const loaded = yield select(selectLoadedTranslations);
213
+
214
+ if (loaded[locale]) {
215
+ return;
216
+ }
217
+
218
+ const translations = yield call(loadTranslations, locale);
219
+ yield put(i18nSlice.actions.loaded({ locale, translations }));
220
+
221
+ const activeLocale = yield select(selectLocale);
222
+
223
+ if (locale === activeLocale) {
224
+ const version = yield select(selectVersion);
225
+ localStorage.setTranslations(locale, version, translations);
226
+ }
227
+ }
228
+
229
+ // The cache makes the next boot's first paint translated without waiting for a chunk download
230
+ function* persistTranslationsCache(locale: Locale): AnyGenerator {
231
+ const loaded = yield select(selectLoadedTranslations);
232
+ const version = yield select(selectVersion);
233
+
234
+ if (loaded[locale]) {
235
+ localStorage.setTranslations(locale, version, loaded[locale]);
236
+ }
237
+ }
238
+
239
+ function* preloadTranslationsWhenIdle(): AnyGenerator {
240
+ yield call(waitForIdleOrFirstIntent);
241
+
242
+ for (const locale of Object.values(Locale)) {
243
+ yield spawn(loadLocaleTranslations, locale);
244
+ }
245
+ }
246
+
132
247
  function* onReset(): AnyGenerator {
133
248
  const config = yield select(selectConfig);
134
249
 
@@ -142,6 +257,10 @@ function* onReset(): AnyGenerator {
142
257
  }
143
258
 
144
259
  function* onLocaleChange({ payload: locale }: PayloadAction<Locale>): AnyGenerator {
260
+ yield spawn(loadLocaleTranslations, locale);
261
+ yield spawn(prefetchDictionary, locale);
262
+ yield* persistTranslationsCache(locale);
263
+
145
264
  const game = yield select(selectGame);
146
265
 
147
266
  if (!hasConfig(game, locale)) {
@@ -166,13 +285,20 @@ function* onLocaleChange({ payload: locale }: PayloadAction<Locale>): AnyGenerat
166
285
  }
167
286
 
168
287
  function* onResultCandidateChange({ payload: result }: PayloadAction<Result | null>): AnyGenerator {
169
- if (result) {
170
- const locale: Locale = yield select(selectLocale);
171
- const uniqueWords = Array.from(new Set(result.words));
172
- const input = uniqueWords.join(LOCALE_FEATURES[locale].separator);
173
- yield put(dictionarySlice.actions.changeInput(input));
174
- yield put(dictionarySlice.actions.submit());
288
+ if (!result) {
289
+ return;
290
+ }
291
+
292
+ const locale: Locale = yield select(selectLocale);
293
+ const uniqueWords = Array.from(new Set(result.words));
294
+ const input = uniqueWords.join(LOCALE_FEATURES[locale].separator);
295
+
296
+ if (!memoizedFindWordDefinitions.hasCache(locale, input)) {
297
+ yield delay(SUBMIT_DELAY);
175
298
  }
299
+
300
+ yield put(dictionarySlice.actions.changeInput(input));
301
+ yield put(dictionarySlice.actions.submit());
176
302
  }
177
303
 
178
304
  function* onSolve(): AnyGenerator {
@@ -1,6 +1,6 @@
1
1
  import { createSelector } from '@reduxjs/toolkit';
2
2
 
3
- import { unorderedArraysEqual } from '@/lib';
3
+ import { unorderedArraysEqual } from '@/lib/unorderedArraysEqual';
4
4
 
5
5
  import { selectBoard } from './board';
6
6
  import { getRemainingTiles } from './lib';
@@ -1,19 +1,16 @@
1
- import { Game } from '@scrabble-solver/types';
1
+ import { Game, Locale } from '@scrabble-solver/types';
2
2
 
3
- import { localStorage } from '../localStorage';
4
-
5
- import { guessLocale } from './lib';
6
3
  import type { SettingsState } from './types';
7
4
 
8
- const isTouchScreen = typeof globalThis.matchMedia !== 'undefined' && globalThis.matchMedia('(hover: none)').matches;
9
-
5
+ /**
6
+ * Deterministic defaults shared by the server render and the client's hydration render.
7
+ */
10
8
  export const settingsInitialState: SettingsState = {
11
9
  autoGroupTiles: null,
12
10
  game: Game.Scrabble,
13
11
  highlightUnreachableCells: false,
14
- inputMode: isTouchScreen ? 'touchscreen' : 'keyboard',
15
- locale: guessLocale(),
12
+ inputMode: 'keyboard',
13
+ locale: Locale.EN_US,
16
14
  removeCellFilters: 'always',
17
- showCoordinates: 'hidden',
18
- ...localStorage.getSettings(),
15
+ showCoordinates: 'original',
19
16
  };
@@ -3,8 +3,10 @@ import { getConfig } from '@scrabble-solver/configs';
3
3
  import { BLANK } from '@scrabble-solver/constants';
4
4
  import { type Cell, type Tile } from '@scrabble-solver/types';
5
5
 
6
- import { i18n, LOCALE_FEATURES } from '@/i18n';
6
+ import { LOCALE_FEATURES } from '@/i18n/constants';
7
+ import { englishTranslations } from '@/i18n/i18n';
7
8
 
9
+ import { selectLoadedTranslations } from '../i18n';
8
10
  import type { RootState } from '../types';
9
11
 
10
12
  const selectCell = (_: unknown, cell: Cell): Cell => cell;
@@ -68,6 +70,9 @@ export const selectCellIsValid = createSelector([selectConfig, selectCell], (con
68
70
  return config.tiles.some((tile) => tile.character === cell.tile.character);
69
71
  });
70
72
 
71
- export const selectTranslations = createSelector([selectLocale], (locale) => i18n[locale]);
73
+ export const selectTranslations = createSelector(
74
+ [selectLocale, selectLoadedTranslations],
75
+ (locale, translations) => translations[locale] ?? englishTranslations,
76
+ );
72
77
 
73
78
  export const selectRemoveCellFilters = createSelector([selectSettings], (settings) => settings.removeCellFilters);
@@ -44,8 +44,11 @@ export const settingsSlice = createSlice({
44
44
  return { ...state, removeCellFilters };
45
45
  },
46
46
 
47
- init: (state, action: PayloadAction<Partial<Pick<typeof settingsInitialState, 'game' | 'locale'>>>) => {
48
- return { ...state, ...action.payload };
47
+ init: (state, action: PayloadAction<Partial<typeof settingsInitialState>>) => {
48
+ const settings = { ...state, ...action.payload };
49
+ const keys = Object.keys(settings) as (keyof typeof settingsInitialState)[];
50
+ const hasDiff = keys.some((key) => settings[key] !== state[key]);
51
+ return hasDiff ? settings : state;
49
52
  },
50
53
  },
51
54
  });
@@ -1,10 +1,12 @@
1
1
  import { configureStore } from '@reduxjs/toolkit';
2
2
  import reduxSaga from 'redux-saga';
3
3
 
4
+ import { appSlice } from './app';
4
5
  import { boardSlice } from './board';
5
6
  import { cellFiltersSlice } from './cellFilters';
6
7
  import { dictionarySlice } from './dictionary';
7
8
  import { hoveredTileSlice } from './hoveredTile';
9
+ import { i18nSlice } from './i18n';
8
10
  import { rackSlice } from './rack';
9
11
  import { resultsSlice } from './results';
10
12
  import { rootSaga } from './sagas';
@@ -16,10 +18,12 @@ const sagaMiddleware = reduxSaga();
16
18
 
17
19
  export const store = configureStore({
18
20
  reducer: {
21
+ app: appSlice.reducer,
19
22
  board: boardSlice.reducer,
20
23
  cellFilters: cellFiltersSlice.reducer,
21
24
  dictionary: dictionarySlice.reducer,
22
25
  hoveredTile: hoveredTileSlice.reducer,
26
+ i18n: i18nSlice.reducer,
23
27
  rack: rackSlice.reducer,
24
28
  results: resultsSlice.reducer,
25
29
  settings: settingsSlice.reducer,
@@ -1,7 +1,9 @@
1
+ import type { AppState } from './app';
1
2
  import type { BoardState } from './board';
2
3
  import type { CellFiltersState } from './cellFilters';
3
4
  import type { DictionaryState } from './dictionary';
4
5
  import type { HoveredTileState } from './hoveredTile';
6
+ import type { I18nState } from './i18n';
5
7
  import type { RackState } from './rack';
6
8
  import type { ResultsState } from './results';
7
9
  import type { SettingsState } from './settings';
@@ -9,10 +11,12 @@ import type { SolveState } from './solve';
9
11
  import type { VerifyState } from './verify';
10
12
 
11
13
  export type RootState = {
14
+ app: AppState;
12
15
  board: BoardState;
13
16
  cellFilters: CellFiltersState;
14
17
  dictionary: DictionaryState;
15
18
  hoveredTile: HoveredTileState;
19
+ i18n: I18nState;
16
20
  rack: RackState;
17
21
  results: ResultsState;
18
22
  settings: SettingsState;
@@ -0,0 +1,6 @@
1
+ import { type Store } from '@reduxjs/toolkit';
2
+ import { useStore } from 'react-redux';
3
+
4
+ import type { RootState } from './types';
5
+
6
+ export const useTypedStore = (): Store<RootState> => useStore<RootState>();
@@ -57,3 +57,4 @@ $modal-width: 370px;
57
57
  $results-item-height: 40px;
58
58
  $solver-column-width: 580px;
59
59
  $text-input-height: 40px;
60
+ $tile-size-max: 80px;
@@ -50,3 +50,12 @@ h4 {
50
50
  nextjs-portal {
51
51
  display: none;
52
52
  }
53
+
54
+ /**
55
+ * Added pre-paint by _document's inline script when the persisted game differs from the
56
+ * prerendered default board; removed after hydration applies the persisted config.
57
+ * The class name must match CONFIG_PENDING_CLASS in parameters/index.ts.
58
+ */
59
+ html.config-pending main {
60
+ visibility: hidden;
61
+ }
@@ -7,23 +7,16 @@
7
7
  breakpointL: strip-unit($breakpoint-l);
8
8
  breakpointXl: strip-unit($breakpoint-xl);
9
9
 
10
- borderColor: $border-color;
11
10
  borderColorLight: $border-color-light;
12
- borderRadius: strip-unit($border-radius);
13
11
  borderWidth: strip-unit($border-width);
14
12
 
15
- colorBlue: $color-blue;
16
13
  colorBlueLight: $color-blue-light;
17
- colorGreen: $color-green;
18
14
  colorGreenLight: $color-green-light;
19
- colorRed: $color-red;
20
15
  colorRedLight: $color-red-light;
21
16
  colorVioletLight: $color-violet-light;
22
- colorYellow: $color-yellow;
23
17
  colorYellowLight: $color-yellow-light;
24
18
 
25
19
  colorBackground: $color-background;
26
- colorForegroundSecondary: $color-foreground-secondary;
27
20
 
28
21
  colorBonusCharacterMultiplier2: $color-bonus-character-multiplier-2;
29
22
  colorBonusCharacterMultiplier3: $color-bonus-character-multiplier-3;
@@ -32,22 +25,8 @@
32
25
  colorBonusWordMultiplier3: $color-bonus-word-multiplier-3;
33
26
  colorBonusWordMultiplier4: $color-bonus-word-multiplier-4;
34
27
 
35
- spacingXs: strip-unit($spacing-xs);
36
- spacingS: strip-unit($spacing-s);
37
- spacingM: strip-unit($spacing-m);
38
- spacingL: strip-unit($spacing-l);
39
- spacingXl: strip-unit($spacing-xl);
40
-
41
28
  transitionDuration: strip-unit($transition-duration);
42
29
  transitionDurationLong: strip-unit($transition-duration-long);
43
30
 
44
- buttonIconSize: strip-unit($button-icon-size);
45
- dictionaryHeight: strip-unit($dictionary-height);
46
- dictionaryHeightMobile: strip-unit($dictionary-height-mobile);
47
- logoHeight: strip-unit($logo-height);
48
- logoHeightSmall: strip-unit($logo-height-small);
49
- modalWidth: strip-unit($modal-width);
50
31
  resultsItemHeight: strip-unit($results-item-height);
51
- solverColumnWidth: strip-unit($solver-column-width);
52
- textInputHeight: strip-unit($text-input-height);
53
32
  }
@@ -0,0 +1,27 @@
1
+ // Generated by scripts/generate-scss-types.ts - do not edit.
2
+ declare const styles: {
3
+ readonly borderColorLight: string;
4
+ readonly borderWidth: string;
5
+ readonly breakpointL: string;
6
+ readonly breakpointM: string;
7
+ readonly breakpointS: string;
8
+ readonly breakpointXl: string;
9
+ readonly breakpointXs: string;
10
+ readonly colorBackground: string;
11
+ readonly colorBlueLight: string;
12
+ readonly colorBonusCharacterMultiplier2: string;
13
+ readonly colorBonusCharacterMultiplier3: string;
14
+ readonly colorBonusCharacterMultiplier4: string;
15
+ readonly colorBonusWordMultiplier2: string;
16
+ readonly colorBonusWordMultiplier3: string;
17
+ readonly colorBonusWordMultiplier4: string;
18
+ readonly colorGreenLight: string;
19
+ readonly colorRedLight: string;
20
+ readonly colorVioletLight: string;
21
+ readonly colorYellowLight: string;
22
+ readonly resultsItemHeight: string;
23
+ readonly transitionDuration: string;
24
+ readonly transitionDurationLong: string;
25
+ };
26
+
27
+ export default styles;
@@ -61,10 +61,12 @@ $easeOutSine: cubic-bezier(0.61, 1, 0.88, 1);
61
61
  --color--bonus--word-multiplier--2: #{$color-bonus-word-multiplier-2};
62
62
  --color--bonus--word-multiplier--3: #{$color-bonus-word-multiplier-3};
63
63
  --color--bonus--word-multiplier--4: #{$color-bonus-word-multiplier-4};
64
+ --color--progress: var(--color--primary--light);
65
+ --color--progress--background: var(--color--inactive);
64
66
  --color--tooltip--background: #{$color-foreground-secondary};
65
67
  --color--tooltip--foreground: var(--color--white);
66
68
 
67
- --font--family: system-ui, sans-serif;
69
+ --font--family: Ubuntu, system-ui, sans-serif;
68
70
  --font--family--monospace:
69
71
  ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono', monospace;
70
72
  --font--size--h1: 30px;
@@ -101,13 +103,14 @@ $easeOutSine: cubic-bezier(0.61, 1, 0.88, 1);
101
103
  --z-index--tooltip: 102;
102
104
 
103
105
  --button--icon--size: #{$button-icon-size};
106
+ --button--height: calc(var(--button--icon--size) + 2 * var(--spacing--m) + 2 * var(--border--width));
104
107
  --dictionary--height: #{$dictionary-height};
105
108
  --dictionary--height--mobile: #{$dictionary-height-mobile};
106
109
  --key--height: 36px;
107
110
  --key--icon--size: 16px;
108
111
  --logo--height: #{$logo-height};
109
112
  --modal--width: #{$modal-width};
110
- --nav--height: calc(var(--logo--height) + var(--nav--padding));
113
+ --nav--height: calc(2 * var(--nav--padding) + var(--logo--height));
111
114
  --nav--padding: var(--spacing--l);
112
115
  --results--icon--size: 18px;
113
116
  --results--item--height: #{$results-item-height};
@@ -116,9 +119,50 @@ $easeOutSine: cubic-bezier(0.61, 1, 0.88, 1);
116
119
  --text-input--height: #{$text-input-height};
117
120
  --tooltip--max-width: 500px;
118
121
 
122
+ /**
123
+ * Sizes of everything visible before hydration.
124
+ * Defaults are of classic Scrabble config.
125
+ */
126
+ --board-cols: 15;
127
+ --board-rows: 15;
128
+ --rack-size: 7;
129
+
130
+ --components-spacing: var(--spacing--xl);
131
+ --solver-column-total: calc(var(--solver-column--width) + var(--components-spacing));
132
+ --candidate-picker-height: 0px;
133
+ --max-board-width: calc(100vw - var(--solver-column-total) - 2 * var(--components-spacing));
134
+ --rack-tile-size: min(
135
+ calc((var(--max-board-width) - 2 * var(--border--width)) / var(--rack-size)),
136
+ #{$tile-size-max}
137
+ );
138
+ --bottom-container-height: calc(
139
+ var(--candidate-picker-height) + var(--rack-tile-size) + 2 * var(--components-spacing)
140
+ );
141
+ --max-board-height: max(calc(100dvh - var(--nav--height) - var(--bottom-container-height)), 0px);
142
+ --cell-from-width: calc(
143
+ (var(--max-board-width) - (var(--board-cols) + 2) * var(--border--width)) / (var(--board-cols) + 0.5)
144
+ );
145
+ --cell-from-height: calc(
146
+ (var(--max-board-height) - (var(--board-rows) + 2) * var(--border--width)) / (var(--board-rows) + 0.5)
147
+ );
148
+ --cell-size: min(var(--cell-from-width), var(--cell-from-height), #{$tile-size-max});
149
+ --coordinate-size: calc(0.5 * var(--cell-size));
150
+ --controls-max-width: calc(var(--rack-size) * var(--rack-tile-size) + 2 * var(--border--width));
151
+
152
+ @include media('<xl') {
153
+ --components-spacing: var(--spacing--l);
154
+ }
155
+
119
156
  @include media('<l') {
120
157
  --dictionary--height: var(--dictionary--height--mobile);
121
158
  --logo--height: #{$logo-height-small};
159
+ --solver-column-total: 0px;
160
+ --candidate-picker-height: calc(var(--button--height) + var(--components-spacing));
161
+ }
162
+
163
+ @include media('<m') {
164
+ // Full-width board: height no longer constrains the cell size.
165
+ --cell-size: min(var(--cell-from-width), #{$tile-size-max});
122
166
  }
123
167
 
124
168
  @include media('<s') {
package/src/types/api.ts CHANGED
@@ -1,9 +1,8 @@
1
- import { type BoardJson, type ConfigJson, type Game, type Locale } from '@scrabble-solver/types';
1
+ import { type BoardJson, type Game, type Locale } from '@scrabble-solver/types';
2
2
 
3
3
  export interface SolveRequestPayload {
4
4
  board: BoardJson;
5
5
  characters: string[];
6
- config: ConfigJson;
7
6
  game: Game;
8
7
  locale: Locale;
9
8
  }
@@ -15,7 +15,7 @@ export type CellFilter = {
15
15
 
16
16
  export type RemoveCellFilters = 'always' | 'never' | null;
17
17
 
18
- export type Direction = 'horizontal' | 'vertical';
18
+ export { type Direction } from '@scrabble-solver/types';
19
19
 
20
20
  export type InputMode = 'keyboard' | 'touchscreen';
21
21
 
@@ -152,7 +152,6 @@ export type TranslationKey =
152
152
  | 'settings.language'
153
153
  | 'settings.showCoordinates'
154
154
  | 'settings.showCoordinates.alternative'
155
- | 'settings.showCoordinates.hidden'
156
155
  | 'settings.showCoordinates.original'
157
156
  | 'words'
158
157
  | 'words.invalid'
package/tsconfig.json CHANGED
@@ -7,6 +7,10 @@
7
7
  "isolatedModules": true,
8
8
  "jsx": "preserve",
9
9
  "lib": ["dom", "dom.iterable", "esnext"],
10
+ // Webpack bundles this package (import.meta worker URLs need an ES module
11
+ // target), unlike the nodenext library packages.
12
+ "module": "esnext",
13
+ "moduleResolution": "bundler",
10
14
  "noEmit": true,
11
15
  "paths": {
12
16
  "@/*": ["./src/*"]