@scrabble-solver/scrabble-solver 2.17.0 → 2.18.1

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 (331) 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/routes-manifest.json +1 -1
  21. package/.next/server/chunks/309.js +1 -0
  22. package/.next/server/chunks/{785.js → 316.js} +1 -1
  23. package/.next/server/chunks/344.js +1 -0
  24. package/.next/server/chunks/371.js +1 -0
  25. package/.next/server/chunks/465.js +1 -0
  26. package/.next/server/chunks/546.js +1 -0
  27. package/.next/server/chunks/623.js +1 -0
  28. package/.next/server/chunks/624.js +1 -0
  29. package/.next/server/chunks/641.js +1 -0
  30. package/.next/server/chunks/671.js +1 -1
  31. package/.next/server/chunks/692.js +1 -0
  32. package/.next/server/chunks/705.js +1 -0
  33. package/.next/server/chunks/712.js +1 -1
  34. package/.next/server/chunks/846.js +1 -0
  35. package/.next/server/chunks/853.js +15 -0
  36. package/.next/server/chunks/886.js +1 -0
  37. package/.next/server/chunks/916.js +1 -0
  38. package/.next/server/chunks/953.js +1 -0
  39. package/.next/server/chunks/961.js +1 -0
  40. package/.next/server/chunks/968.js +1 -0
  41. package/.next/server/dynamic-css-manifest.js +1 -1
  42. package/.next/server/middleware-build-manifest.js +1 -1
  43. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  44. package/.next/server/pages/404.html +29 -1
  45. package/.next/server/pages/500.html +29 -1
  46. package/.next/server/pages/_app.js +1 -1
  47. package/.next/server/pages/_app.js.nft.json +1 -1
  48. package/.next/server/pages/_document.js +28 -1
  49. package/.next/server/pages/_document.js.nft.json +1 -1
  50. package/.next/server/pages/_error.js +28 -1
  51. package/.next/server/pages/_error.js.nft.json +1 -1
  52. package/.next/server/pages/api/dictionary/[locale]/[word].js.nft.json +1 -1
  53. package/.next/server/pages/api/dictionary/[locale].js.nft.json +1 -1
  54. package/.next/server/pages/api/solve.js +1 -1
  55. package/.next/server/pages/api/solve.js.nft.json +1 -1
  56. package/.next/server/pages/api/verify.js.nft.json +1 -1
  57. package/.next/server/pages/api/visit.js.nft.json +1 -1
  58. package/.next/server/pages/index.html +29 -1
  59. package/.next/server/pages/index.js +30 -1
  60. package/.next/server/pages/index.js.nft.json +1 -1
  61. package/.next/server/pages/index.json +1 -1
  62. package/.next/server/pages/not-found.html +29 -1
  63. package/.next/server/pages/not-found.js.nft.json +1 -1
  64. package/.next/server/pages-manifest.json +1 -1
  65. package/.next/server/webpack-api-runtime.js +1 -1
  66. package/.next/server/webpack-runtime.js +1 -1
  67. package/.next/static/5KOWzYqfY1Z2rjrzptr8D/_buildManifest.js +1 -0
  68. package/.next/static/chunks/101-829ab8a8d310e7a0.js +3 -0
  69. package/.next/static/chunks/106.e414e88694add27f.js +1 -0
  70. package/.next/static/chunks/127.125d896a19061d71.js +1 -0
  71. package/.next/static/chunks/18.8b91e137d239e15c.js +1 -0
  72. package/.next/static/chunks/277.6785dfaf22fdb0b7.js +1 -0
  73. package/.next/static/chunks/307.67f52f13e3d60d4e.js +1 -0
  74. package/.next/static/chunks/341.79535ba85bf1986f.js +1 -0
  75. package/.next/static/chunks/363.01eed3233f92b6a4.js +1 -0
  76. package/.next/static/chunks/422.1559ae6756912ca5.js +1 -0
  77. package/.next/static/chunks/541.dcd9e8b804f88da5.js +1 -0
  78. package/.next/static/chunks/631.98d42abad0a60af6.js +1 -0
  79. package/.next/static/chunks/663.d2c9ca36b26695b8.js +1 -0
  80. package/.next/static/chunks/711.ba7b8f900dfd40d0.js +1 -0
  81. package/.next/static/chunks/744.b06c9a3de4a1d877.js +1 -0
  82. package/.next/static/chunks/820.97b82f751ca49579.js +1 -0
  83. package/.next/static/chunks/865.a9b563a45848a83c.js +1 -0
  84. package/.next/static/chunks/912.ff8037ba9d4db5c8.js +1 -0
  85. package/.next/static/chunks/939.19b33a3d3c351d73.js +1 -0
  86. package/.next/static/chunks/990.61296e5870b91f11.js +1 -0
  87. package/.next/static/chunks/framework-626cbd48ac5aca57.js +1 -0
  88. package/.next/static/chunks/main-b92e08f3fc96dd8d.js +5 -0
  89. package/.next/static/chunks/pages/_app-2e607dcd4135f340.js +1 -0
  90. package/.next/static/chunks/pages/{_error-afeda7c5231b6c3c.js → _error-f0290a98eb3ed0ec.js} +1 -1
  91. package/.next/static/chunks/pages/index-e0087247c995328d.js +1 -0
  92. package/.next/static/chunks/pages/not-found-a59f9deeeff63d17.js +1 -0
  93. package/.next/static/chunks/webpack-cfb34d175e081981.js +1 -0
  94. package/.next/static/css/2d03f0da2c678dfc.css +1 -0
  95. package/.next/static/css/4dbcacc1122ac6b9.css +2 -0
  96. package/.next/static/css/7b6724d2df70f48f.css +1 -0
  97. package/.next/static/css/b736be3bd02b5d99.css +1 -0
  98. package/.next/static/css/b74cd7de82dabcdd.css +1 -0
  99. package/.next/static/css/c403ce739a9c0d83.css +1 -0
  100. package/.next/static/css/ca311e6c030663d4.css +1 -0
  101. package/.next/static/css/dee878eb64099d92.css +1 -0
  102. package/.next/static/css/fbfdce70731d0d2b.css +1 -0
  103. package/.next/trace +21 -21
  104. package/.next/trace-build +1 -1
  105. package/empty-module.js +2 -0
  106. package/next.config.js +13 -2
  107. package/package.json +43 -17
  108. package/public/llms.txt +11 -0
  109. package/public/robots.txt +5 -0
  110. package/public/site.webmanifest +14 -0
  111. package/scripts/generate-scss-types.ts +112 -0
  112. package/src/@types/scss.d.ts +6 -9
  113. package/src/@types/svg.d.ts +1 -1
  114. package/src/components/Alert/Alert.module.scss.d.ts +13 -0
  115. package/src/components/Alert/Alert.tsx +4 -1
  116. package/src/components/Badge/Badge.module.scss.d.ts +6 -0
  117. package/src/components/Board/Board.module.scss +10 -0
  118. package/src/components/Board/Board.module.scss.d.ts +17 -0
  119. package/src/components/Board/Board.tsx +14 -26
  120. package/src/components/Board/BoardPure.tsx +54 -49
  121. package/src/components/Board/components/Actions/Actions.module.scss +18 -18
  122. package/src/components/Board/components/Actions/Actions.module.scss.d.ts +7 -0
  123. package/src/components/Board/components/Actions/Actions.tsx +6 -3
  124. package/src/components/Board/components/Actions/lib.ts +3 -1
  125. package/src/components/Board/components/Cell/Cell.module.scss.d.ts +13 -0
  126. package/src/components/Board/components/Cell/Cell.tsx +28 -33
  127. package/src/components/Board/components/InputPrompt/InputPrompt.module.scss.d.ts +10 -0
  128. package/src/components/Board/components/InputPrompt/InputPrompt.tsx +1 -1
  129. package/src/components/Board/components/ToggleDirectionButton/ToggleDirectionButton.module.scss.d.ts +8 -0
  130. package/src/components/Board/components/ToggleDirectionButton/ToggleDirectionButton.tsx +2 -2
  131. package/src/components/Board/getBoardBackground.ts +175 -0
  132. package/src/components/Board/hooks/index.ts +0 -1
  133. package/src/components/Board/hooks/useBoardStyle.ts +10 -20
  134. package/src/components/Board/hooks/useFloatingActions.ts +3 -6
  135. package/src/components/Board/hooks/useGrid.ts +6 -3
  136. package/src/components/Board/selectors.ts +1 -1
  137. package/src/components/Button/Button.module.scss.d.ts +12 -0
  138. package/src/components/Dictionary/Dictionary.module.scss +1 -0
  139. package/src/components/Dictionary/Dictionary.module.scss.d.ts +14 -0
  140. package/src/components/Dictionary/Dictionary.tsx +1 -3
  141. package/src/components/DictionaryInput/DictionaryInput.module.scss.d.ts +7 -0
  142. package/src/components/DictionaryInput/DictionaryInput.tsx +1 -1
  143. package/src/components/EmptyState/EmptyState.module.scss.d.ts +7 -0
  144. package/src/components/EmptyState/EmptyState.tsx +1 -1
  145. package/src/components/IconButton/IconButton.module.scss.d.ts +8 -0
  146. package/src/components/Key/Key.module.scss.d.ts +6 -0
  147. package/src/components/Keys/Arrows/Arrows.module.scss.d.ts +11 -0
  148. package/src/components/Keys/Arrows/Arrows.tsx +4 -1
  149. package/src/components/Keys/index.tsx +1 -1
  150. package/src/components/Loading/Loading.module.scss.d.ts +9 -0
  151. package/src/components/Loading/Loading.tsx +1 -1
  152. package/src/components/Logo/Logo.tsx +4 -9
  153. package/src/components/Logo/LogoBlueprint.tsx +1 -0
  154. package/src/components/Modal/Modal.module.scss.d.ts +15 -0
  155. package/src/components/Modal/Modal.tsx +16 -3
  156. package/src/components/Modal/components/Section/Section.module.scss.d.ts +7 -0
  157. package/src/components/NavButtons/NavButtons.module.scss +20 -0
  158. package/src/components/NavButtons/NavButtons.module.scss.d.ts +13 -0
  159. package/src/components/NavButtons/NavButtons.tsx +29 -45
  160. package/src/components/NotFound/NotFound.module.scss.d.ts +9 -0
  161. package/src/components/NotFound/NotFound.tsx +1 -1
  162. package/src/components/PlainTiles/PlainTiles.module.scss.d.ts +11 -0
  163. package/src/components/PlainTiles/PlainTiles.tsx +0 -1
  164. package/src/components/PlainTiles/Tile.tsx +3 -4
  165. package/src/components/PlainTiles/lib.ts +4 -19
  166. package/src/components/PlainTiles/types.ts +0 -1
  167. package/src/components/Progress/Progress.module.scss +7 -0
  168. package/src/components/Progress/Progress.module.scss.d.ts +6 -0
  169. package/src/components/Progress/Progress.tsx +2 -11
  170. package/src/components/Rack/Rack.module.scss +3 -0
  171. package/src/components/Rack/Rack.module.scss.d.ts +10 -0
  172. package/src/components/Rack/Rack.tsx +8 -11
  173. package/src/components/Rack/components/InputPrompt/InputPrompt.module.scss +2 -0
  174. package/src/components/Rack/components/InputPrompt/InputPrompt.module.scss.d.ts +7 -0
  175. package/src/components/Rack/components/InputPrompt/InputPrompt.tsx +1 -13
  176. package/src/components/Rack/components/InputPrompt/lib.ts +1 -1
  177. package/src/components/Rack/components/RackTile/RackTile.module.scss.d.ts +6 -0
  178. package/src/components/Rack/components/RackTile/RackTile.tsx +5 -4
  179. package/src/components/Rack/selectors.ts +1 -1
  180. package/src/components/Radio/Radio.module.scss.d.ts +12 -0
  181. package/src/components/Results/Cell.tsx +3 -12
  182. package/src/components/Results/Header.tsx +9 -18
  183. package/src/components/Results/HeaderButton.tsx +4 -5
  184. package/src/components/Results/Result.tsx +4 -12
  185. package/src/components/Results/Results.module.scss +4 -6
  186. package/src/components/Results/Results.module.scss.d.ts +27 -0
  187. package/src/components/Results/Results.tsx +4 -3
  188. package/src/components/Results/SolveButton.tsx +1 -1
  189. package/src/components/ResultsInput/ResultsInput.module.scss.d.ts +7 -0
  190. package/src/components/ResultsInput/ResultsInput.tsx +1 -1
  191. package/src/components/Solver/Solver.module.scss +6 -5
  192. package/src/components/Solver/Solver.module.scss.d.ts +20 -0
  193. package/src/components/Solver/Solver.tsx +19 -21
  194. package/src/components/Solver/components/InsertButton/InsertButton.module.scss.d.ts +7 -0
  195. package/src/components/Solver/components/InsertButton/InsertButton.tsx +1 -1
  196. package/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.module.scss.d.ts +18 -0
  197. package/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.tsx +3 -1
  198. package/src/components/Spinner/Spinner.module.scss.d.ts +10 -0
  199. package/src/components/Tile/Tile.module.scss +3 -0
  200. package/src/components/Tile/Tile.module.scss.d.ts +19 -0
  201. package/src/components/Tile/Tile.tsx +5 -14
  202. package/src/components/Tile/TilePure.tsx +2 -12
  203. package/src/components/Tooltip/Tooltip.module.scss.d.ts +7 -0
  204. package/src/components/Tooltip/Tooltip.tsx +14 -3
  205. package/src/components/Tooltip/useTooltip.ts +1 -0
  206. package/src/hooks/useColumns.ts +4 -7
  207. package/src/hooks/useDeferredRender.ts +20 -0
  208. package/src/hooks/useDirection.ts +4 -3
  209. package/src/hooks/useLanguage.ts +2 -2
  210. package/src/hooks/useLocalStorage.ts +32 -8
  211. package/src/hooks/useMedia.ts +26 -26
  212. package/src/i18n/constants.ts +2 -15
  213. package/src/i18n/i18n.ts +18 -17
  214. package/src/i18n/languages/english.json +0 -1
  215. package/src/i18n/languages/french.json +0 -1
  216. package/src/i18n/languages/german.json +0 -1
  217. package/src/i18n/languages/persian.json +0 -1
  218. package/src/i18n/languages/polish.json +0 -1
  219. package/src/i18n/languages/romanian.json +0 -1
  220. package/src/i18n/languages/spanish.json +0 -1
  221. package/src/i18n/languages/turkish.json +0 -1
  222. package/src/i18n/localeIcons.ts +24 -0
  223. package/src/lib/localeTransliterate.test.ts +5 -0
  224. package/src/lib/localeTransliterate.ts +26 -6
  225. package/src/lib/waitForIdleOrFirstIntent.ts +44 -0
  226. package/src/modals/DictionaryModal/DictionaryModal.module.scss.d.ts +8 -0
  227. package/src/modals/DictionaryModal/DictionaryModal.tsx +3 -1
  228. package/src/modals/KeyMapModal/KeyMapModal.tsx +3 -1
  229. package/src/modals/KeyMapModal/components/Mapping/Mapping.module.scss.d.ts +11 -0
  230. package/src/modals/MenuModal/MenuModal.module.scss +5 -0
  231. package/src/modals/MenuModal/MenuModal.module.scss.d.ts +10 -0
  232. package/src/modals/MenuModal/MenuModal.tsx +16 -5
  233. package/src/modals/RemainingTilesModal/RemainingTilesModal.module.scss +4 -1
  234. package/src/modals/RemainingTilesModal/RemainingTilesModal.module.scss.d.ts +9 -0
  235. package/src/modals/RemainingTilesModal/RemainingTilesModal.tsx +4 -6
  236. package/src/modals/RemainingTilesModal/components/Character/Character.module.scss +1 -0
  237. package/src/modals/RemainingTilesModal/components/Character/Character.module.scss.d.ts +12 -0
  238. package/src/modals/RemainingTilesModal/components/Character/Character.tsx +5 -12
  239. package/src/modals/ResultsModal/ResultsModal.module.scss.d.ts +8 -0
  240. package/src/modals/ResultsModal/ResultsModal.tsx +8 -4
  241. package/src/modals/SettingsModal/SettingsModal.tsx +2 -2
  242. package/src/modals/SettingsModal/components/AutoGroupTilesSetting/AutoGroupTilesSetting.module.scss.d.ts +7 -0
  243. package/src/modals/SettingsModal/components/AutoGroupTilesSetting/AutoGroupTilesSetting.tsx +1 -1
  244. package/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.module.scss.d.ts +7 -0
  245. package/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.tsx +1 -1
  246. package/src/modals/SettingsModal/components/HighlightUnreachableCellsSetting/HighlightUnreachableCellsSetting.module.scss.d.ts +7 -0
  247. package/src/modals/SettingsModal/components/HighlightUnreachableCellsSetting/HighlightUnreachableCellsSetting.tsx +1 -1
  248. package/src/modals/SettingsModal/components/InputModeSetting/InputModeSetting.module.scss.d.ts +7 -0
  249. package/src/modals/SettingsModal/components/InputModeSetting/InputModeSetting.tsx +1 -1
  250. package/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.module.scss.d.ts +8 -0
  251. package/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.tsx +24 -21
  252. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/RemoveCellFiltersSetting.module.scss.d.ts +7 -0
  253. package/src/modals/SettingsModal/components/RemoveCellFiltersSetting/RemoveCellFiltersSetting.tsx +1 -1
  254. package/src/modals/SettingsModal/components/ShowCoordinatesSetting/ShowCoordinatesSetting.module.scss.d.ts +7 -0
  255. package/src/modals/SettingsModal/components/ShowCoordinatesSetting/ShowCoordinatesSetting.tsx +1 -5
  256. package/src/modals/WordsModal/WordsModal.module.scss.d.ts +11 -0
  257. package/src/modals/WordsModal/WordsModal.tsx +4 -2
  258. package/src/modals/preload.ts +24 -0
  259. package/src/pages/_app.tsx +37 -76
  260. package/src/pages/_document.tsx +112 -24
  261. package/src/pages/api/solve.ts +1 -1
  262. package/src/pages/index.module.scss +1 -0
  263. package/src/pages/index.module.scss.d.ts +11 -0
  264. package/src/pages/index.tsx +127 -40
  265. package/src/pages/not-found.tsx +14 -3
  266. package/src/parameters/index.ts +31 -93
  267. package/src/serviceWorkerManager.ts +5 -2
  268. package/src/state/actions.ts +1 -1
  269. package/src/state/app/index.ts +4 -0
  270. package/src/state/app/initialState.ts +6 -0
  271. package/src/state/app/selectors.ts +5 -0
  272. package/src/state/app/slice.ts +20 -0
  273. package/src/state/app/types.ts +4 -0
  274. package/src/state/board/initialState.ts +1 -2
  275. package/src/state/i18n/index.ts +4 -0
  276. package/src/state/i18n/initialState.ts +5 -0
  277. package/src/state/i18n/selectors.ts +3 -0
  278. package/src/state/i18n/slice.ts +16 -0
  279. package/src/state/i18n/types.ts +7 -0
  280. package/src/state/index.ts +2 -0
  281. package/src/state/lib.ts +1 -1
  282. package/src/state/localStorage.ts +86 -29
  283. package/src/state/rack/initialState.ts +1 -2
  284. package/src/state/rack/slice.ts +4 -1
  285. package/src/state/results/lib.ts +5 -5
  286. package/src/state/results/selectors.ts +1 -1
  287. package/src/state/sagas.ts +125 -9
  288. package/src/state/selectors.ts +1 -1
  289. package/src/state/settings/initialState.ts +7 -10
  290. package/src/state/settings/selectors.ts +7 -2
  291. package/src/state/settings/slice.ts +5 -2
  292. package/src/state/store.ts +4 -0
  293. package/src/state/types.ts +4 -0
  294. package/src/styles/_tokens.scss +1 -0
  295. package/src/styles/global.scss +9 -0
  296. package/src/styles/variables.module.scss +0 -21
  297. package/src/styles/variables.module.scss.d.ts +27 -0
  298. package/src/styles/variables.scss +46 -2
  299. package/src/types/index.ts +1 -2
  300. package/tsconfig.tsbuildinfo +1 -1
  301. package/.next/server/chunks/129.js +0 -1
  302. package/.next/server/chunks/318.js +0 -3
  303. package/.next/server/chunks/791.js +0 -15
  304. package/.next/static/OLE8_ZInlGH7ENU0NIOpf/_buildManifest.js +0 -1
  305. package/.next/static/chunks/830.661816bf0de8c2f1.js +0 -1
  306. package/.next/static/chunks/framework-3cf15b8041c59dd3.js +0 -1
  307. package/.next/static/chunks/main-5b999f3f24ebfa84.js +0 -5
  308. package/.next/static/chunks/pages/_app-7024e7a27ffbb2fa.js +0 -7
  309. package/.next/static/chunks/pages/index-8b398b0a5d870773.js +0 -1
  310. package/.next/static/chunks/pages/not-found-9e076427bad69d90.js +0 -1
  311. package/.next/static/chunks/webpack-3943d624bbb47a64.js +0 -1
  312. package/.next/static/css/a78e04fe95452380.css +0 -1
  313. package/.next/static/css/aedeaada218d7280.css +0 -2
  314. package/src/app-layout/AppLayoutContext.tsx +0 -25
  315. package/src/app-layout/index.ts +0 -1
  316. package/src/app-layout/useAppLayoutValue.ts +0 -112
  317. package/src/components/Board/hooks/useBackgroundImage.tsx +0 -279
  318. package/src/components/SeoMessage/SeoMessage.tsx +0 -18
  319. package/src/components/SeoMessage/index.ts +0 -1
  320. package/src/components/index.ts +0 -26
  321. package/src/hooks/index.ts +0 -12
  322. package/src/hooks/useOnWindowResize.ts +0 -11
  323. package/src/hooks/useViewportSize.ts +0 -17
  324. package/src/i18n/index.ts +0 -2
  325. package/src/icons/Flag.svg +0 -4
  326. package/src/icons/Star.svg +0 -4
  327. package/src/icons/index.ts +0 -49
  328. package/src/lib/getTileSizes.ts +0 -13
  329. package/src/lib/index.ts +0 -24
  330. package/src/modals/index.ts +0 -7
  331. /package/.next/static/{OLE8_ZInlGH7ENU0NIOpf → 5KOWzYqfY1Z2rjrzptr8D}/_ssgManifest.js +0 -0
@@ -1,13 +1,20 @@
1
- import { Board, type BoardJson } from '@scrabble-solver/types';
1
+ import { Board, type BoardJson, isObject, type Locale } from '@scrabble-solver/types';
2
2
  import store2 from 'store2';
3
3
 
4
- import type { Rack } from '@/types';
4
+ import type { Rack, Translations } from '@/types';
5
5
 
6
6
  import type { SettingsState } from './settings/types';
7
7
 
8
8
  const BOARD = 'board';
9
9
  const RACK = 'rack';
10
10
  const SETTINGS = 'settings';
11
+ const TRANSLATIONS = 'translations';
12
+
13
+ interface PersistedTranslations {
14
+ locale: Locale;
15
+ translations: Translations;
16
+ version: string;
17
+ }
11
18
 
12
19
  const LEGACY_KEYS: Record<keyof SettingsState, string> = {
13
20
  autoGroupTiles: 'auto-group-tiles',
@@ -21,33 +28,15 @@ const LEGACY_KEYS: Record<keyof SettingsState, string> = {
21
28
 
22
29
  const store = store2.namespace('scrabble-solver');
23
30
 
24
- /**
25
- * Introduced in 2.15.26 on 2026/04/27.
26
- * Life expectancy: 1y.
27
- */
28
- const migrateLegacySettings = (): Partial<SettingsState> => {
29
- const settings: Partial<SettingsState> = {};
30
- let hasLegacy = false;
31
-
32
- for (const [setting, legacyKey] of Object.entries(LEGACY_KEYS) as [keyof SettingsState, string][]) {
33
- if (store.has(legacyKey)) {
34
- settings[setting] = store.get(legacyKey);
35
- store.remove(legacyKey);
36
- hasLegacy = true;
37
- }
38
- }
39
-
40
- if (hasLegacy) {
41
- store.set(SETTINGS, settings, true);
42
- }
43
-
44
- return settings;
45
- };
46
-
47
31
  export const localStorage = {
48
32
  getBoard(): Board | undefined {
49
- const serialized = store.get(BOARD) as string | undefined;
50
- return serialized ? Board.fromJson(JSON.parse(serialized) as BoardJson) : undefined;
33
+ try {
34
+ const serialized = store.get(BOARD) as string | undefined;
35
+ return serialized ? Board.fromJson(JSON.parse(serialized) as BoardJson) : undefined;
36
+ } catch {
37
+ store.remove(BOARD);
38
+ return undefined;
39
+ }
51
40
  },
52
41
 
53
42
  setBoard(board: Board | undefined): void {
@@ -56,7 +45,14 @@ export const localStorage = {
56
45
  },
57
46
 
58
47
  getRack(): Rack | undefined {
59
- return store.get(RACK) as Rack | undefined;
48
+ const rack = store.get(RACK) as Rack | undefined;
49
+
50
+ if (rack !== undefined && !Array.isArray(rack)) {
51
+ store.remove(RACK);
52
+ return undefined;
53
+ }
54
+
55
+ return rack;
60
56
  },
61
57
 
62
58
  setRack(rack: Rack | undefined): void {
@@ -65,10 +61,71 @@ export const localStorage = {
65
61
 
66
62
  getSettings(): Partial<SettingsState> {
67
63
  const stored = store.get(SETTINGS) as Partial<SettingsState> | undefined;
68
- return stored ?? migrateLegacySettings();
64
+
65
+ if (stored !== undefined && !isObject(stored)) {
66
+ store.remove(SETTINGS);
67
+ }
68
+
69
+ return migrateHiddenShowCoordinates(isObject(stored) ? stored : migrateLegacySettings());
69
70
  },
70
71
 
71
72
  setSettings(settings: SettingsState): void {
72
73
  store.set(SETTINGS, settings, true);
73
74
  },
75
+
76
+ getTranslations(locale: Locale, version: string): Translations | undefined {
77
+ const stored = store.get(TRANSLATIONS) as PersistedTranslations | undefined;
78
+
79
+ if (typeof stored === 'undefined') {
80
+ return undefined;
81
+ }
82
+
83
+ if (!isObject(stored) || stored.locale !== locale || stored.version !== version || !isObject(stored.translations)) {
84
+ store.remove(TRANSLATIONS);
85
+ return undefined;
86
+ }
87
+
88
+ return stored.translations;
89
+ },
90
+
91
+ setTranslations(locale: Locale, version: string, translations: Translations): void {
92
+ store.set(TRANSLATIONS, { locale, translations, version } satisfies PersistedTranslations, true);
93
+ },
74
94
  };
95
+
96
+ /**
97
+ * Introduced in 2.15.26 on 2026/04/27.
98
+ * Life expectancy: 1y.
99
+ */
100
+ function migrateLegacySettings(): Partial<SettingsState> {
101
+ const settings: Partial<SettingsState> = {};
102
+ let hasLegacy = false;
103
+
104
+ for (const [setting, legacyKey] of Object.entries(LEGACY_KEYS) as [keyof SettingsState, string][]) {
105
+ if (store.has(legacyKey)) {
106
+ settings[setting] = store.get(legacyKey);
107
+ store.remove(legacyKey);
108
+ hasLegacy = true;
109
+ }
110
+ }
111
+
112
+ if (hasLegacy) {
113
+ store.set(SETTINGS, settings, true);
114
+ }
115
+
116
+ return settings;
117
+ }
118
+
119
+ /**
120
+ * The 'hidden' showCoordinates option was removed on 2026/08/13.
121
+ * Life expectancy: 1y.
122
+ */
123
+ function migrateHiddenShowCoordinates(settings: Partial<SettingsState>): Partial<SettingsState> {
124
+ if (String(settings.showCoordinates) !== 'hidden') {
125
+ return settings;
126
+ }
127
+
128
+ const migrated: Partial<SettingsState> = { ...settings, showCoordinates: 'original' };
129
+ store.set(SETTINGS, migrated, true);
130
+ return migrated;
131
+ }
@@ -1,6 +1,5 @@
1
1
  import { getConfig } from '@scrabble-solver/configs';
2
2
 
3
- import { localStorage } from '../localStorage';
4
3
  import { settingsInitialState } from '../settings';
5
4
 
6
5
  import type { RackState } from './types';
@@ -9,4 +8,4 @@ const defaultConfig = getConfig(settingsInitialState.game, settingsInitialState.
9
8
 
10
9
  export const rackDefaultState: RackState = Array(defaultConfig.rackSize).fill(null);
11
10
 
12
- export const rackInitialState: RackState = localStorage.getRack() ?? rackDefaultState;
11
+ export const rackInitialState: RackState = rackDefaultState;
@@ -1,7 +1,10 @@
1
1
  import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
2
2
  import { type Tile } from '@scrabble-solver/types';
3
3
 
4
- import { arrayEquals, createNullMovingComparator, inverseDirection, zipCharactersAndTiles } from '@/lib';
4
+ import { arrayEquals } from '@/lib/arrayEquals';
5
+ import { createNullMovingComparator } from '@/lib/createNullMovingComparator';
6
+ import { inverseDirection } from '@/lib/inverseDirection';
7
+ import { zipCharactersAndTiles } from '@/lib/zipCharactersAndTiles';
5
8
  import { type AutoGroupTiles, type Rack } from '@/types';
6
9
 
7
10
  import { rackDefaultState, rackInitialState } from './initialState';
@@ -1,6 +1,10 @@
1
1
  import { type Result, type ShowCoordinates } from '@scrabble-solver/types';
2
2
 
3
- import { createKeyComparator, createRegExp, createStringComparator, getCoordinate, reverseComparator } from '@/lib';
3
+ import { createKeyComparator } from '@/lib/createKeyComparator';
4
+ import { createRegExp } from '@/lib/createRegExp';
5
+ import { createStringComparator } from '@/lib/createStringComparator';
6
+ import { getCoordinate } from '@/lib/getCoordinate';
7
+ import { reverseComparator } from '@/lib/reverseComparator';
4
8
  import {
5
9
  type CellFilter,
6
10
  type Comparator,
@@ -11,10 +15,6 @@ import {
11
15
  } from '@/types';
12
16
 
13
17
  export const getCoordinates = (result: Result, showCoordinates: ShowCoordinates): string => {
14
- if (showCoordinates === 'hidden') {
15
- return '';
16
- }
17
-
18
18
  const firstCell = result.cells[0];
19
19
  const x = getCoordinate(firstCell.x, showCoordinates === 'original' ? 'letter' : 'number');
20
20
  const y = getCoordinate(firstCell.y, showCoordinates === 'original' ? 'number' : 'letter');
@@ -1,6 +1,6 @@
1
1
  import { createSelector } from '@reduxjs/toolkit';
2
2
 
3
- import { createRegExp } from '@/lib';
3
+ import { createRegExp } from '@/lib/createRegExp';
4
4
 
5
5
  import { selectCellFilters } from '../cellFilters';
6
6
  import { selectLocale, selectShowCoordinates } from '../settings';
@@ -5,18 +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';
8
+ import { Board, Locale, type Result } from '@scrabble-solver/types';
9
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 { waitForFirstIntent, waitForIdleOrFirstIntent } from '@/lib/waitForIdleOrFirstIntent';
13
15
  import { findWordDefinitions, solve, verify, visit } from '@/sdk';
14
16
  import { prefetchDictionary } from '@/solver-worker';
15
17
 
16
18
  import { initialize, reset } from './actions';
19
+ import { appSlice, selectVersion } from './app';
17
20
  import { boardSlice, selectBoard } from './board';
18
21
  import { cellFiltersSlice, selectCellFilter } from './cellFilters';
19
22
  import { dictionarySlice, selectDictionary } from './dictionary';
23
+ import { i18nSlice, selectLoadedTranslations } from './i18n';
24
+ import { localStorage } from './localStorage';
20
25
  import { rackSlice, selectCharacters, selectRack } from './rack';
21
26
  import { resultsSlice } from './results';
22
27
  import {
@@ -25,8 +30,11 @@ import {
25
30
  selectLocale,
26
31
  selectLocaleAutoGroupTiles,
27
32
  selectRemoveCellFilters,
33
+ settingsInitialState,
28
34
  settingsSlice,
35
+ type SettingsState,
29
36
  } from './settings';
37
+ import { guessLocale } from './settings/lib';
30
38
  import { solveSlice } from './solve';
31
39
  import { verifySlice } from './verify';
32
40
 
@@ -119,13 +127,22 @@ function* onDictionarySubmit(): AnyGenerator {
119
127
  }
120
128
  }
121
129
 
122
- 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
+
123
139
  const board = yield select(selectBoard);
124
140
  const locale = yield select(selectLocale);
125
141
 
126
- yield spawn(prefetchDictionary, locale);
127
- // Detached: offline, a failed visit would otherwise tear down the whole root saga.
128
- yield spawn(visit);
142
+ yield spawn(prefetchDictionaryOnFirstIntent);
143
+ yield spawn(loadLocaleTranslations, locale);
144
+ yield spawn(preloadTranslationsWhenIdle);
145
+ yield spawn(visitWhenIdle);
129
146
 
130
147
  if (!board.isEmpty()) {
131
148
  yield* resetRack();
@@ -133,6 +150,100 @@ function* onInitialize(): AnyGenerator {
133
150
  }
134
151
  }
135
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* prefetchDictionaryOnFirstIntent(): AnyGenerator {
206
+ yield call(waitForFirstIntent);
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
+
136
247
  function* onReset(): AnyGenerator {
137
248
  const config = yield select(selectConfig);
138
249
 
@@ -146,7 +257,9 @@ function* onReset(): AnyGenerator {
146
257
  }
147
258
 
148
259
  function* onLocaleChange({ payload: locale }: PayloadAction<Locale>): AnyGenerator {
260
+ yield spawn(loadLocaleTranslations, locale);
149
261
  yield spawn(prefetchDictionary, locale);
262
+ yield* persistTranslationsCache(locale);
150
263
 
151
264
  const game = yield select(selectGame);
152
265
 
@@ -176,11 +289,14 @@ function* onResultCandidateChange({ payload: result }: PayloadAction<Result | nu
176
289
  return;
177
290
  }
178
291
 
179
- yield delay(SUBMIT_DELAY);
180
-
181
292
  const locale: Locale = yield select(selectLocale);
182
293
  const uniqueWords = Array.from(new Set(result.words));
183
294
  const input = uniqueWords.join(LOCALE_FEATURES[locale].separator);
295
+
296
+ if (!memoizedFindWordDefinitions.hasCache(locale, input)) {
297
+ yield delay(SUBMIT_DELAY);
298
+ }
299
+
184
300
  yield put(dictionarySlice.actions.changeInput(input));
185
301
  yield put(dictionarySlice.actions.submit());
186
302
  }
@@ -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;
@@ -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;