scrabble-solver 2.15.25 → 2.16.0-alpha.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.
- package/.github/workflows/build.yml +3 -5
- package/.github/workflows/{npx.yml → bunx.yml} +7 -11
- package/.github/workflows/deploy.yml +2 -2
- package/.github/workflows/{cypress.yml → e2e-tests.yml} +7 -7
- package/.github/workflows/oxfmt.yml +3 -5
- package/.github/workflows/oxlint.yml +4 -6
- package/.github/workflows/{jest.yml → unit-tests.yml} +6 -8
- package/.nx/workspace-data/d/server-process.json +5 -0
- package/.nx/workspace-data/file-map.json +467 -455
- package/.nx/workspace-data/lockfile-dependencies.hash +1 -1
- package/.nx/workspace-data/lockfile-nodes.hash +1 -1
- package/.nx/workspace-data/nx_files.nxt +0 -0
- package/.nx/workspace-data/parsed-lock-file.dependencies.json +5301 -11011
- package/.nx/workspace-data/parsed-lock-file.nodes.json +16259 -7681
- package/.nx/workspace-data/project-graph.json +25619 -19944
- package/.nx/workspace-data/source-maps.json +96 -0
- package/.oxlintrc.json +0 -2
- package/CLAUDE.md +120 -0
- package/README.md +26 -20
- package/bin/scrabble-solver.js +1 -1
- package/bump-version.js +4 -4
- package/bun-test-globals.d.ts +1 -0
- package/bun.lock +3984 -0
- package/bun.test.preload.ts +21 -0
- package/bunfig.toml +2 -0
- package/lerna.json +1 -1
- package/package.json +19 -21
- package/packages/configs/package.json +3 -3
- package/packages/constants/package.json +1 -1
- package/packages/dictionaries/package.json +4 -4
- package/packages/logger/package.json +1 -1
- package/packages/scrabble-solver/.next/BUILD_ID +1 -1
- package/packages/scrabble-solver/.next/build-manifest.json +5 -5
- package/packages/scrabble-solver/.next/cache/.previewinfo +1 -1
- package/packages/scrabble-solver/.next/cache/.rscinfo +1 -1
- package/packages/scrabble-solver/.next/cache/.tsbuildinfo +1 -1
- package/packages/scrabble-solver/.next/cache/webpack/client-production/0.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack.old +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack.old +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/server-production/0.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack.old +0 -0
- package/packages/scrabble-solver/.next/prerender-manifest.json +4 -4
- package/packages/scrabble-solver/.next/required-server-files.js +2 -1
- package/packages/scrabble-solver/.next/required-server-files.json +2 -1
- package/packages/scrabble-solver/.next/routes-manifest.json +1 -1
- package/packages/scrabble-solver/.next/server/chunks/712.js +1 -1
- package/packages/scrabble-solver/.next/server/middleware-build-manifest.js +1 -1
- package/packages/scrabble-solver/.next/server/pages/404.html +1 -1
- package/packages/scrabble-solver/.next/server/pages/500.html +1 -1
- package/packages/scrabble-solver/.next/server/pages/_app.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/_error.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale]/[word].js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale].js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/solve.js +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/solve.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/verify.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/visit.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/index.html +1 -1
- package/packages/scrabble-solver/.next/server/pages/index.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/index.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/not-found.html +1 -1
- package/packages/scrabble-solver/.next/server/webpack-api-runtime.js +1 -1
- package/packages/scrabble-solver/.next/static/{FDUqldlsD7FXe6iWhIJmu → YS42EFHDGPCCe3JyeXaNi}/_buildManifest.js +1 -1
- package/packages/scrabble-solver/.next/static/chunks/pages/{_app-c0932b8ca24945cb.js → _app-9c9aaea7b6881765.js} +4 -4
- package/packages/scrabble-solver/.next/static/chunks/pages/{index-08b3b0a754095919.js → index-e9ea63e97865edcf.js} +1 -1
- package/packages/scrabble-solver/.next/static/css/{500cdc9a24075d91.css → 78726ae7cf7a5497.css} +1 -1
- package/packages/scrabble-solver/.next/trace +21 -21
- package/packages/scrabble-solver/.next/trace-build +1 -1
- package/packages/scrabble-solver/README.md +3 -3
- package/packages/scrabble-solver/next.config.js +1 -0
- package/packages/scrabble-solver/package.json +9 -8
- package/packages/scrabble-solver/public/service-worker.js +1 -1
- package/packages/scrabble-solver/src/@types/scss.d.ts +5 -0
- package/packages/scrabble-solver/src/components/Board/Board.module.scss +2 -2
- package/packages/scrabble-solver/src/components/Board/components/Actions/Actions.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Board/components/Cell/Cell.module.scss +26 -6
- package/packages/scrabble-solver/src/components/Board/components/InputPrompt/InputPrompt.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Button/Button.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Dictionary/Dictionary.module.scss +1 -1
- package/packages/scrabble-solver/src/components/DictionaryInput/DictionaryInput.module.scss +1 -1
- package/packages/scrabble-solver/src/components/IconButton/IconButton.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Loading/Loading.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Modal/Modal.module.scss +1 -1
- package/packages/scrabble-solver/src/components/NotFound/NotFound.module.scss +1 -1
- package/packages/scrabble-solver/src/components/PlainTiles/PlainTiles.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Rack/Rack.module.scss +11 -6
- package/packages/scrabble-solver/src/components/Rack/components/InputPrompt/InputPrompt.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Rack/components/RackTile/RackTile.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Radio/Radio.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Results/Results.module.scss +1 -1
- package/packages/scrabble-solver/src/components/ResultsInput/ResultsInput.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Solver/Solver.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Solver/components/InsertButton/InsertButton.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Spinner/Spinner.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Tile/Tile.module.scss +1 -1
- package/packages/scrabble-solver/src/hooks/useLocalStorage.ts +4 -52
- package/packages/scrabble-solver/src/lib/isMac.ts +1 -1
- package/packages/scrabble-solver/src/modals/MenuModal/MenuModal.module.scss +1 -1
- package/packages/scrabble-solver/src/modals/RemainingTilesModal/components/Character/Character.module.scss +1 -1
- package/packages/scrabble-solver/src/modals/ResultsModal/ResultsModal.module.scss +1 -1
- package/packages/scrabble-solver/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.module.scss +1 -1
- package/packages/scrabble-solver/src/parameters/index.ts +45 -44
- package/packages/scrabble-solver/src/state/localStorage.ts +42 -52
- package/packages/scrabble-solver/src/state/settings/initialState.ts +7 -7
- package/packages/scrabble-solver/src/styles/_tokens.scss +59 -0
- package/packages/scrabble-solver/src/styles/global.scss +3 -3
- package/packages/scrabble-solver/src/styles/mixins.scss +13 -12
- package/packages/scrabble-solver/src/styles/variables.module.scss +53 -0
- package/packages/scrabble-solver/src/styles/variables.scss +44 -41
- package/packages/scrabble-solver/tsconfig.tsbuildinfo +1 -1
- package/packages/solver/package.json +7 -6
- package/packages/types/package.json +2 -2
- package/packages/word-definitions/package.json +4 -3
- package/packages/word-definitions/src/parse.test.ts +7 -2
- package/packages/word-lists/package.json +2 -2
- package/todo.txt +3 -0
- package/tsconfig.json +1 -1
- package/jest.config.js +0 -15
- package/jest.setup.js +0 -6
- package/tsconfig.jest.json +0 -10
- /package/packages/scrabble-solver/.next/static/{FDUqldlsD7FXe6iWhIJmu → YS42EFHDGPCCe3JyeXaNi}/_ssgManifest.js +0 -0
|
@@ -1,33 +1,11 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
localStorage,
|
|
5
|
-
selectAutoGroupTiles,
|
|
6
|
-
selectBoard,
|
|
7
|
-
selectGame,
|
|
8
|
-
selectInputMode,
|
|
9
|
-
selectLocale,
|
|
10
|
-
selectRack,
|
|
11
|
-
selectShowCoordinates,
|
|
12
|
-
selectRemoveCellFilters,
|
|
13
|
-
useTypedSelector,
|
|
14
|
-
} from '@/state';
|
|
3
|
+
import { localStorage, selectBoard, selectRack, selectSettings, useTypedSelector } from '@/state';
|
|
15
4
|
|
|
16
5
|
export const useLocalStorage = () => {
|
|
17
|
-
const autoGroupTiles = useTypedSelector(selectAutoGroupTiles);
|
|
18
6
|
const board = useTypedSelector(selectBoard);
|
|
19
|
-
const game = useTypedSelector(selectGame);
|
|
20
|
-
const inputMode = useTypedSelector(selectInputMode);
|
|
21
|
-
const locale = useTypedSelector(selectLocale);
|
|
22
7
|
const rack = useTypedSelector(selectRack);
|
|
23
|
-
const
|
|
24
|
-
const removeCellFilters = useTypedSelector(selectRemoveCellFilters);
|
|
25
|
-
|
|
26
|
-
useEffect(() => {
|
|
27
|
-
if (autoGroupTiles) {
|
|
28
|
-
localStorage.setAutoGroupTiles(autoGroupTiles);
|
|
29
|
-
}
|
|
30
|
-
}, [autoGroupTiles]);
|
|
8
|
+
const settings = useTypedSelector(selectSettings);
|
|
31
9
|
|
|
32
10
|
useEffect(() => {
|
|
33
11
|
if (board) {
|
|
@@ -35,24 +13,6 @@ export const useLocalStorage = () => {
|
|
|
35
13
|
}
|
|
36
14
|
}, [board]);
|
|
37
15
|
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
if (game) {
|
|
40
|
-
localStorage.setGame(game);
|
|
41
|
-
}
|
|
42
|
-
}, [game]);
|
|
43
|
-
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
if (inputMode) {
|
|
46
|
-
localStorage.setInputMode(inputMode);
|
|
47
|
-
}
|
|
48
|
-
}, [inputMode]);
|
|
49
|
-
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
if (locale) {
|
|
52
|
-
localStorage.setLocale(locale);
|
|
53
|
-
}
|
|
54
|
-
}, [locale]);
|
|
55
|
-
|
|
56
16
|
useEffect(() => {
|
|
57
17
|
if (rack) {
|
|
58
18
|
localStorage.setRack(rack);
|
|
@@ -60,14 +20,6 @@ export const useLocalStorage = () => {
|
|
|
60
20
|
}, [rack]);
|
|
61
21
|
|
|
62
22
|
useEffect(() => {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
}, [showCoordinates]);
|
|
67
|
-
|
|
68
|
-
useEffect(() => {
|
|
69
|
-
if (removeCellFilters) {
|
|
70
|
-
localStorage.setRemoveCellFilters(removeCellFilters);
|
|
71
|
-
}
|
|
72
|
-
}, [removeCellFilters]);
|
|
23
|
+
localStorage.setSettings(settings);
|
|
24
|
+
}, [settings]);
|
|
73
25
|
};
|
|
@@ -3,5 +3,5 @@ export const isMac = (): boolean => {
|
|
|
3
3
|
return false;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
return globalThis.navigator.platform.startsWith('Mac') || globalThis.navigator.platform
|
|
6
|
+
return globalThis.navigator.platform.startsWith('Mac') || globalThis.navigator.platform.startsWith('iPhone');
|
|
7
7
|
};
|
|
@@ -1,38 +1,39 @@
|
|
|
1
|
+
import variables from '@/styles/variables.module.scss';
|
|
1
2
|
import { ResultColumnId } from '@/types';
|
|
2
3
|
|
|
3
4
|
export const BREAKPOINTS = {
|
|
4
|
-
xs:
|
|
5
|
-
s:
|
|
6
|
-
m:
|
|
7
|
-
l:
|
|
8
|
-
xl:
|
|
5
|
+
xs: Number(variables.breakpointXs),
|
|
6
|
+
s: Number(variables.breakpointS),
|
|
7
|
+
m: Number(variables.breakpointM),
|
|
8
|
+
l: Number(variables.breakpointL),
|
|
9
|
+
xl: Number(variables.breakpointXl),
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
export const TRANSITION = 'var(--transition)';
|
|
12
13
|
|
|
13
14
|
export const GITHUB_PROJECT_URL = 'https://github.com/kamilmielnik/scrabble-solver';
|
|
14
15
|
|
|
15
|
-
export const TRANSITION_DURATION =
|
|
16
|
-
export const TRANSITION_DURATION_LONG =
|
|
17
|
-
|
|
18
|
-
export const COLOR_BLUE =
|
|
19
|
-
export const COLOR_GREEN =
|
|
20
|
-
export const COLOR_RED =
|
|
21
|
-
export const COLOR_YELLOW =
|
|
22
|
-
|
|
23
|
-
export const COLOR_BONUS_CHARACTER_1 =
|
|
24
|
-
export const COLOR_BONUS_CHARACTER_2 =
|
|
25
|
-
export const COLOR_BONUS_CHARACTER_3 =
|
|
26
|
-
export const COLOR_BONUS_CHARACTER_5 =
|
|
27
|
-
export const COLOR_BONUS_CHARACTER_MULTIPLIER_2 =
|
|
28
|
-
export const COLOR_BONUS_CHARACTER_MULTIPLIER_3 =
|
|
29
|
-
export const COLOR_BONUS_CHARACTER_MULTIPLIER_4 =
|
|
30
|
-
export const COLOR_BONUS_START =
|
|
31
|
-
export const COLOR_BONUS_WORD_MULTIPLIER_2 =
|
|
32
|
-
export const COLOR_BONUS_WORD_MULTIPLIER_3 =
|
|
33
|
-
export const COLOR_BONUS_WORD_MULTIPLIER_4 =
|
|
34
|
-
export const COLOR_FILTERED =
|
|
35
|
-
export const COLOR_BACKGROUND =
|
|
16
|
+
export const TRANSITION_DURATION = Number(variables.transitionDuration);
|
|
17
|
+
export const TRANSITION_DURATION_LONG = Number(variables.transitionDurationLong);
|
|
18
|
+
|
|
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;
|
|
36
|
+
export const COLOR_BACKGROUND = variables.colorBackground;
|
|
36
37
|
|
|
37
38
|
export const COLOR_BONUS_CHARACTER: Record<number, string> = {
|
|
38
39
|
1: COLOR_BONUS_CHARACTER_1,
|
|
@@ -53,11 +54,11 @@ export const COLOR_BONUS_WORD: Record<number, string> = {
|
|
|
53
54
|
4: COLOR_BONUS_WORD_MULTIPLIER_4,
|
|
54
55
|
};
|
|
55
56
|
|
|
56
|
-
export const SPACING_XS =
|
|
57
|
-
export const SPACING_S =
|
|
58
|
-
export const SPACING_M =
|
|
59
|
-
export const SPACING_L =
|
|
60
|
-
export const SPACING_XL =
|
|
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);
|
|
61
62
|
|
|
62
63
|
export const COMPONENTS_SPACING = SPACING_XL;
|
|
63
64
|
export const COMPONENTS_SPACING_SMALL = SPACING_L;
|
|
@@ -70,24 +71,24 @@ export const BOARD_TILE_FONT_SIZE_MIN = 14;
|
|
|
70
71
|
export const BOARD_TILE_FONT_SIZE_POINTS_MIN = 10;
|
|
71
72
|
export const BOARD_TILE_SIZE_MAX = RACK_TILE_SIZE_MAX;
|
|
72
73
|
|
|
73
|
-
export const BORDER_COLOR =
|
|
74
|
-
export const BORDER_COLOR_LIGHT =
|
|
75
|
-
export const BORDER_RADIUS =
|
|
76
|
-
export const BORDER_WIDTH =
|
|
74
|
+
export const BORDER_COLOR = variables.borderColor;
|
|
75
|
+
export const BORDER_COLOR_LIGHT = variables.borderColorLight;
|
|
76
|
+
export const BORDER_RADIUS = Number(variables.borderRadius);
|
|
77
|
+
export const BORDER_WIDTH = Number(variables.borderWidth);
|
|
77
78
|
|
|
78
|
-
export const BUTTON_ICON_SIZE =
|
|
79
|
+
export const BUTTON_ICON_SIZE = Number(variables.buttonIconSize);
|
|
79
80
|
export const BUTTON_PADDING_VERTICAL = SPACING_M;
|
|
80
81
|
export const BUTTON_HEIGHT = BUTTON_ICON_SIZE + 2 * BUTTON_PADDING_VERTICAL + 2 * BORDER_WIDTH;
|
|
81
82
|
|
|
82
|
-
export const DICTIONARY_HEIGHT =
|
|
83
|
-
export const DICTIONARY_HEIGHT_MOBILE =
|
|
83
|
+
export const DICTIONARY_HEIGHT = Number(variables.dictionaryHeight);
|
|
84
|
+
export const DICTIONARY_HEIGHT_MOBILE = Number(variables.dictionaryHeightMobile);
|
|
84
85
|
|
|
85
86
|
export const LOGO_ASPECT_RATIO = 682 / 166;
|
|
86
|
-
export const LOGO_HEIGHT =
|
|
87
|
-
export const LOGO_HEIGHT_SMALL =
|
|
87
|
+
export const LOGO_HEIGHT = Number(variables.logoHeight);
|
|
88
|
+
export const LOGO_HEIGHT_SMALL = Number(variables.logoHeightSmall);
|
|
88
89
|
export const LOGO_SRC = '/logo.svg';
|
|
89
90
|
|
|
90
|
-
export const MODAL_WIDTH =
|
|
91
|
+
export const MODAL_WIDTH = Number(variables.modalWidth);
|
|
91
92
|
export const MODAL_HEADER_HEIGHT = 45;
|
|
92
93
|
|
|
93
94
|
export const NAV_PADDING = SPACING_L;
|
|
@@ -133,10 +134,10 @@ export const RESULTS_COLUMN_WIDTH: Record<ResultColumnId, number | undefined> =
|
|
|
133
134
|
[ResultColumnId.Word]: undefined,
|
|
134
135
|
[ResultColumnId.WordsCount]: 55,
|
|
135
136
|
};
|
|
136
|
-
export const RESULTS_ITEM_HEIGHT =
|
|
137
|
+
export const RESULTS_ITEM_HEIGHT = Number(variables.resultsItemHeight);
|
|
137
138
|
|
|
138
139
|
export const RESULTS_HEADER_HEIGHT = RESULTS_ITEM_HEIGHT;
|
|
139
140
|
|
|
140
|
-
export const SOLVER_COLUMN_WIDTH =
|
|
141
|
+
export const SOLVER_COLUMN_WIDTH = Number(variables.solverColumnWidth);
|
|
141
142
|
|
|
142
|
-
export const TEXT_INPUT_HEIGHT =
|
|
143
|
+
export const TEXT_INPUT_HEIGHT = Number(variables.textInputHeight);
|
|
@@ -1,28 +1,49 @@
|
|
|
1
|
-
import { Board, type BoardJson
|
|
1
|
+
import { Board, type BoardJson } from '@scrabble-solver/types';
|
|
2
2
|
import store2 from 'store2';
|
|
3
3
|
|
|
4
|
-
import type {
|
|
4
|
+
import type { Rack } from '@/types';
|
|
5
|
+
|
|
6
|
+
import type { SettingsState } from './settings/types';
|
|
5
7
|
|
|
6
|
-
const AUTO_GROUP_TILES = 'auto-group-tiles';
|
|
7
8
|
const BOARD = 'board';
|
|
8
|
-
const GAME_ID = 'config-id';
|
|
9
|
-
const INPUT_MODE = 'input-mode';
|
|
10
|
-
const REMOVE_CELL_FILTERS = 'remove-cell-filters';
|
|
11
|
-
const LOCALE = 'locale';
|
|
12
9
|
const RACK = 'rack';
|
|
13
|
-
const
|
|
10
|
+
const SETTINGS = 'settings';
|
|
11
|
+
|
|
12
|
+
const LEGACY_KEYS: Record<keyof SettingsState, string> = {
|
|
13
|
+
autoGroupTiles: 'auto-group-tiles',
|
|
14
|
+
game: 'config-id',
|
|
15
|
+
inputMode: 'input-mode',
|
|
16
|
+
locale: 'locale',
|
|
17
|
+
removeCellFilters: 'remove-cell-filters',
|
|
18
|
+
showCoordinates: 'show-coordinates',
|
|
19
|
+
};
|
|
14
20
|
|
|
15
21
|
const store = store2.namespace('scrabble-solver');
|
|
16
22
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Introduced in 2.15.26 on 2026/04/27.
|
|
25
|
+
* Life expectancy: 1y.
|
|
26
|
+
*/
|
|
27
|
+
const migrateLegacySettings = (): Partial<SettingsState> => {
|
|
28
|
+
const settings: Partial<SettingsState> = {};
|
|
29
|
+
let hasLegacy = false;
|
|
30
|
+
|
|
31
|
+
for (const [setting, legacyKey] of Object.entries(LEGACY_KEYS) as [keyof SettingsState, string][]) {
|
|
32
|
+
if (store.has(legacyKey)) {
|
|
33
|
+
settings[setting] = store.get(legacyKey);
|
|
34
|
+
store.remove(legacyKey);
|
|
35
|
+
hasLegacy = true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (hasLegacy) {
|
|
40
|
+
store.set(SETTINGS, settings, true);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return settings;
|
|
44
|
+
};
|
|
25
45
|
|
|
46
|
+
export const localStorage = {
|
|
26
47
|
getBoard(): Board | undefined {
|
|
27
48
|
const serialized = store.get(BOARD) as string | undefined;
|
|
28
49
|
return serialized ? Board.fromJson(JSON.parse(serialized) as BoardJson) : undefined;
|
|
@@ -33,30 +54,6 @@ export const localStorage = {
|
|
|
33
54
|
store.set(BOARD, serialized, true);
|
|
34
55
|
},
|
|
35
56
|
|
|
36
|
-
getGame(): Game | undefined {
|
|
37
|
-
return store.get(GAME_ID) as Game | undefined;
|
|
38
|
-
},
|
|
39
|
-
|
|
40
|
-
setGame(game: Game | undefined): void {
|
|
41
|
-
store.set(GAME_ID, game, true);
|
|
42
|
-
},
|
|
43
|
-
|
|
44
|
-
getInputMode(): InputMode | undefined {
|
|
45
|
-
return store.get(INPUT_MODE) as InputMode | undefined;
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
setInputMode(inputMode: InputMode | undefined): void {
|
|
49
|
-
store.set(INPUT_MODE, inputMode, true);
|
|
50
|
-
},
|
|
51
|
-
|
|
52
|
-
getLocale(): Locale | undefined {
|
|
53
|
-
return store.get(LOCALE) as Locale | undefined;
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
setLocale(locale: Locale | undefined): void {
|
|
57
|
-
store.set(LOCALE, locale, true);
|
|
58
|
-
},
|
|
59
|
-
|
|
60
57
|
getRack(): Rack | undefined {
|
|
61
58
|
return store.get(RACK) as Rack | undefined;
|
|
62
59
|
},
|
|
@@ -65,19 +62,12 @@ export const localStorage = {
|
|
|
65
62
|
store.set(RACK, rack, true);
|
|
66
63
|
},
|
|
67
64
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
setShowCoordinates(showCoordinates: ShowCoordinates | undefined): void {
|
|
73
|
-
store.set(SHOW_COORDINATES, showCoordinates, true);
|
|
74
|
-
},
|
|
75
|
-
|
|
76
|
-
getRemoveCellFilters(): RemoveCellFilters | undefined {
|
|
77
|
-
return store.get(REMOVE_CELL_FILTERS) as RemoveCellFilters | undefined;
|
|
65
|
+
getSettings(): Partial<SettingsState> {
|
|
66
|
+
const stored = store.get(SETTINGS) as Partial<SettingsState> | undefined;
|
|
67
|
+
return stored ?? migrateLegacySettings();
|
|
78
68
|
},
|
|
79
69
|
|
|
80
|
-
|
|
81
|
-
store.set(
|
|
70
|
+
setSettings(settings: SettingsState): void {
|
|
71
|
+
store.set(SETTINGS, settings, true);
|
|
82
72
|
},
|
|
83
73
|
};
|
|
@@ -5,14 +5,14 @@ import { localStorage } from '../localStorage';
|
|
|
5
5
|
import { guessLocale } from './lib';
|
|
6
6
|
import type { SettingsState } from './types';
|
|
7
7
|
|
|
8
|
-
const localStorageAutoGroupTiles = localStorage.getAutoGroupTiles();
|
|
9
8
|
const isTouchScreen = typeof globalThis.matchMedia !== 'undefined' && globalThis.matchMedia('(hover: none)').matches;
|
|
10
9
|
|
|
11
10
|
export const settingsInitialState: SettingsState = {
|
|
12
|
-
autoGroupTiles:
|
|
13
|
-
game:
|
|
14
|
-
inputMode:
|
|
15
|
-
locale:
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
autoGroupTiles: null,
|
|
12
|
+
game: Game.Scrabble,
|
|
13
|
+
inputMode: isTouchScreen ? 'touchscreen' : 'keyboard',
|
|
14
|
+
locale: guessLocale(),
|
|
15
|
+
removeCellFilters: 'always',
|
|
16
|
+
showCoordinates: 'hidden',
|
|
17
|
+
...localStorage.getSettings(),
|
|
18
18
|
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
@use 'sass:math';
|
|
2
|
+
|
|
3
|
+
@function strip-unit($value) {
|
|
4
|
+
@return math.div($value, $value * 0 + 1);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
$breakpoint-xs: 480px;
|
|
8
|
+
$breakpoint-s: 768px;
|
|
9
|
+
$breakpoint-m: 992px;
|
|
10
|
+
$breakpoint-l: 1200px;
|
|
11
|
+
$breakpoint-xl: 1400px;
|
|
12
|
+
|
|
13
|
+
$border-color: #cdcdcd;
|
|
14
|
+
$border-color-light: #d9d9d9;
|
|
15
|
+
$border-radius: 5px;
|
|
16
|
+
$border-width: 1px;
|
|
17
|
+
|
|
18
|
+
$color-blue: #c7d8f9;
|
|
19
|
+
$color-blue-light: #dde4f6;
|
|
20
|
+
$color-green: #bae3ba;
|
|
21
|
+
$color-green-light: #d6ebd6;
|
|
22
|
+
$color-red: #f7c2aa;
|
|
23
|
+
$color-red-light: #fbe0d4;
|
|
24
|
+
$color-violet: #78387f;
|
|
25
|
+
$color-violet-light: #b284b8;
|
|
26
|
+
$color-yellow: #efe3ae;
|
|
27
|
+
$color-yellow-light: #f7f1d6;
|
|
28
|
+
|
|
29
|
+
$color-background: #f4f4f4;
|
|
30
|
+
$color-foreground: #222;
|
|
31
|
+
$color-foreground-secondary: #444;
|
|
32
|
+
$color-inactive: #cdcdcd;
|
|
33
|
+
|
|
34
|
+
$color-bonus-character-multiplier-2: #b8d5ed;
|
|
35
|
+
$color-bonus-character-multiplier-3: #86aed1;
|
|
36
|
+
$color-bonus-character-multiplier-4: #3477b2;
|
|
37
|
+
$color-bonus-word-multiplier-2: #fbc997;
|
|
38
|
+
$color-bonus-word-multiplier-3: #f19393;
|
|
39
|
+
$color-bonus-word-multiplier-4: #ed5e5e;
|
|
40
|
+
|
|
41
|
+
$spacing-xs: 2px;
|
|
42
|
+
$spacing-s: 5px;
|
|
43
|
+
$spacing-m: 10px;
|
|
44
|
+
$spacing-l: 20px;
|
|
45
|
+
$spacing-xl: 40px;
|
|
46
|
+
$spacing-xxl: 80px;
|
|
47
|
+
|
|
48
|
+
$transition-duration: 100ms;
|
|
49
|
+
$transition-duration-long: 250ms;
|
|
50
|
+
|
|
51
|
+
$button-icon-size: 24px;
|
|
52
|
+
$dictionary-height: 260px;
|
|
53
|
+
$dictionary-height-mobile: 110px;
|
|
54
|
+
$logo-height: 60px;
|
|
55
|
+
$logo-height-small: 48px;
|
|
56
|
+
$modal-width: 370px;
|
|
57
|
+
$results-item-height: 40px;
|
|
58
|
+
$solver-column-width: 580px;
|
|
59
|
+
$text-input-height: 40px;
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
@
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
$media-expressions: (
|
|
12
|
-
|
|
1
|
+
@use 'styles/tokens' as *;
|
|
2
|
+
|
|
3
|
+
@forward 'include-media' with (
|
|
4
|
+
$breakpoints: (
|
|
5
|
+
xs: $breakpoint-xs,
|
|
6
|
+
s: $breakpoint-s,
|
|
7
|
+
m: $breakpoint-m,
|
|
8
|
+
l: $breakpoint-l,
|
|
9
|
+
xl: $breakpoint-xl,
|
|
10
|
+
),
|
|
11
|
+
$media-expressions: (
|
|
12
|
+
touch: '(hover: none)',
|
|
13
|
+
)
|
|
13
14
|
);
|
|
14
15
|
|
|
15
16
|
@mixin scrollbars {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
@use 'styles/tokens' as *;
|
|
2
|
+
|
|
3
|
+
:export {
|
|
4
|
+
breakpointXs: strip-unit($breakpoint-xs);
|
|
5
|
+
breakpointS: strip-unit($breakpoint-s);
|
|
6
|
+
breakpointM: strip-unit($breakpoint-m);
|
|
7
|
+
breakpointL: strip-unit($breakpoint-l);
|
|
8
|
+
breakpointXl: strip-unit($breakpoint-xl);
|
|
9
|
+
|
|
10
|
+
borderColor: $border-color;
|
|
11
|
+
borderColorLight: $border-color-light;
|
|
12
|
+
borderRadius: strip-unit($border-radius);
|
|
13
|
+
borderWidth: strip-unit($border-width);
|
|
14
|
+
|
|
15
|
+
colorBlue: $color-blue;
|
|
16
|
+
colorBlueLight: $color-blue-light;
|
|
17
|
+
colorGreen: $color-green;
|
|
18
|
+
colorGreenLight: $color-green-light;
|
|
19
|
+
colorRed: $color-red;
|
|
20
|
+
colorRedLight: $color-red-light;
|
|
21
|
+
colorVioletLight: $color-violet-light;
|
|
22
|
+
colorYellow: $color-yellow;
|
|
23
|
+
colorYellowLight: $color-yellow-light;
|
|
24
|
+
|
|
25
|
+
colorBackground: $color-background;
|
|
26
|
+
colorForegroundSecondary: $color-foreground-secondary;
|
|
27
|
+
|
|
28
|
+
colorBonusCharacterMultiplier2: $color-bonus-character-multiplier-2;
|
|
29
|
+
colorBonusCharacterMultiplier3: $color-bonus-character-multiplier-3;
|
|
30
|
+
colorBonusCharacterMultiplier4: $color-bonus-character-multiplier-4;
|
|
31
|
+
colorBonusWordMultiplier2: $color-bonus-word-multiplier-2;
|
|
32
|
+
colorBonusWordMultiplier3: $color-bonus-word-multiplier-3;
|
|
33
|
+
colorBonusWordMultiplier4: $color-bonus-word-multiplier-4;
|
|
34
|
+
|
|
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
|
+
transitionDuration: strip-unit($transition-duration);
|
|
42
|
+
transitionDurationLong: strip-unit($transition-duration-long);
|
|
43
|
+
|
|
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
|
+
resultsItemHeight: strip-unit($results-item-height);
|
|
51
|
+
solverColumnWidth: strip-unit($solver-column-width);
|
|
52
|
+
textInputHeight: strip-unit($text-input-height);
|
|
53
|
+
}
|