scrabble-solver 2.10.7 → 2.10.9
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/babel.config.js +1 -1
- package/lerna.json +1 -1
- package/package.json +3 -3
- package/packages/configs/package-lock.json +4 -4
- package/packages/configs/package.json +3 -3
- package/packages/constants/package-lock.json +2 -2
- package/packages/constants/package.json +1 -1
- package/packages/dictionaries/package-lock.json +2 -2
- package/packages/dictionaries/package.json +4 -4
- package/packages/logger/package-lock.json +2 -2
- package/packages/logger/package.json +1 -1
- package/packages/scrabble-solver/.next/BUILD_ID +1 -1
- package/packages/scrabble-solver/.next/build-manifest.json +15 -21
- package/packages/scrabble-solver/.next/cache/.tsbuildinfo +1 -1
- package/packages/scrabble-solver/.next/cache/eslint/.cache_8dgz12 +1 -1
- package/packages/scrabble-solver/.next/cache/next-server.js.nft.json +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/edge-server-production/0.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack +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/images-manifest.json +1 -1
- package/packages/scrabble-solver/.next/next-server.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/prerender-manifest.json +1 -1
- package/packages/scrabble-solver/.next/required-server-files.json +1 -1
- package/packages/scrabble-solver/.next/routes-manifest.json +1 -1
- package/packages/scrabble-solver/.next/server/chunks/176.js +4603 -395
- package/packages/scrabble-solver/.next/server/chunks/664.js +27 -2414
- package/packages/scrabble-solver/.next/server/chunks/859.js +29 -1
- package/packages/scrabble-solver/.next/server/font-loader-manifest.js +1 -0
- package/packages/scrabble-solver/.next/server/font-loader-manifest.json +6 -0
- package/packages/scrabble-solver/.next/server/middleware-build-manifest.js +1 -1
- package/packages/scrabble-solver/.next/server/pages/404.html +2 -2
- package/packages/scrabble-solver/.next/server/pages/404.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/500.html +1 -12
- package/packages/scrabble-solver/.next/server/pages/_app.js +176 -13
- package/packages/scrabble-solver/.next/server/pages/_app.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/_document.js +1 -1
- package/packages/scrabble-solver/.next/server/pages/_document.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/_error.js +133 -17
- package/packages/scrabble-solver/.next/server/pages/_error.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/solve.js +16 -0
- package/packages/scrabble-solver/.next/server/pages/index.html +1 -9
- package/packages/scrabble-solver/.next/server/pages/index.js +52 -165
- 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-manifest.json +1 -1
- package/packages/scrabble-solver/.next/static/chunks/main-74c4d6b2b5c362f3.js +1 -0
- package/packages/scrabble-solver/.next/static/chunks/pages/{404-67383848027ec49b.js → 404-d5ff00df1c687977.js} +1 -1
- package/packages/scrabble-solver/.next/static/chunks/pages/_app-52cb288dc680bdfe.js +28 -0
- package/packages/scrabble-solver/.next/static/chunks/pages/index-5c2544930e46c5ce.js +1 -0
- package/packages/scrabble-solver/.next/static/chunks/webpack-6ef43a8d4a395f49.js +1 -0
- package/packages/scrabble-solver/.next/static/css/ec4e47a6b1866fe5.css +1 -0
- package/packages/scrabble-solver/.next/static/css/f65b7b2a74f57c1c.css +2 -0
- package/packages/scrabble-solver/.next/static/fZRsz4P0gQ8Wgb9jP8eap/_buildManifest.js +1 -0
- package/packages/scrabble-solver/.next/trace +55 -55
- package/packages/scrabble-solver/package-lock.json +255 -122
- package/packages/scrabble-solver/package.json +11 -9
- package/packages/scrabble-solver/src/components/Badge/Badge.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Board/Board.module.scss +14 -0
- package/packages/scrabble-solver/src/components/Board/Board.tsx +117 -19
- package/packages/scrabble-solver/src/components/Board/BoardPure.tsx +7 -15
- package/packages/scrabble-solver/src/components/Board/components/Actions/Actions.module.scss +64 -0
- package/packages/scrabble-solver/src/components/Board/components/Actions/Actions.tsx +68 -0
- package/packages/scrabble-solver/src/components/Board/components/Actions/index.ts +1 -0
- package/packages/scrabble-solver/src/components/Board/components/Cell/Cell.module.scss +22 -165
- package/packages/scrabble-solver/src/components/Board/components/Cell/Cell.tsx +0 -37
- package/packages/scrabble-solver/src/components/Board/components/Cell/CellPure.tsx +5 -75
- package/packages/scrabble-solver/src/components/Board/components/index.ts +1 -0
- package/packages/scrabble-solver/src/components/Board/hooks/useGrid.ts +16 -16
- package/packages/scrabble-solver/src/components/Button/Button.module.scss +3 -3
- package/packages/scrabble-solver/src/components/Checkbox/Checkbox.tsx +1 -4
- package/packages/scrabble-solver/src/components/Dictionary/Dictionary.tsx +28 -30
- package/packages/scrabble-solver/src/components/DictionaryInput/DictionaryInput.tsx +3 -0
- package/packages/scrabble-solver/src/components/Key/Key.module.scss +1 -1
- package/packages/scrabble-solver/src/components/LogoSplashScreen/LogoSplashScreen.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Modal/Modal.module.scss +4 -2
- package/packages/scrabble-solver/src/components/Rack/Rack.module.scss +5 -0
- package/packages/scrabble-solver/src/components/Radio/Radio.tsx +1 -4
- package/packages/scrabble-solver/src/components/Results/Results.module.scss +2 -2
- package/packages/scrabble-solver/src/components/SeoMessage/SeoMessage.tsx +19 -0
- package/packages/scrabble-solver/src/components/SeoMessage/index.ts +1 -0
- package/packages/scrabble-solver/src/components/Solver/Solver.module.scss +0 -5
- package/packages/scrabble-solver/src/components/Solver/Solver.tsx +1 -1
- package/packages/scrabble-solver/src/components/Solver/components/EmptyState/EmptyState.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.module.scss +9 -2
- package/packages/scrabble-solver/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.tsx +2 -1
- package/packages/scrabble-solver/src/components/Tile/Tile.module.scss +23 -11
- package/packages/scrabble-solver/src/components/Tile/Tile.tsx +26 -9
- package/packages/scrabble-solver/src/components/Tile/TilePure.tsx +9 -4
- package/packages/scrabble-solver/src/components/Tooltip/Tooltip.module.scss +7 -7
- package/packages/scrabble-solver/src/components/index.ts +1 -0
- package/packages/scrabble-solver/src/hooks/useLocalStorage/useLocalStorageBoard.ts +6 -3
- package/packages/scrabble-solver/src/hooks/useLocalStorage/useLocalStorageConfigId.ts +6 -3
- package/packages/scrabble-solver/src/hooks/useLocalStorage/useLocalStorageLocale.ts +6 -3
- package/packages/scrabble-solver/src/hooks/useLocalStorage/useLocalStorageRack.ts +6 -3
- package/packages/scrabble-solver/src/i18n/de.json +1 -0
- package/packages/scrabble-solver/src/i18n/en.json +1 -0
- package/packages/scrabble-solver/src/i18n/es.json +1 -0
- package/packages/scrabble-solver/src/i18n/fa.json +1 -0
- package/packages/scrabble-solver/src/i18n/fr.json +1 -0
- package/packages/scrabble-solver/src/i18n/pl.json +1 -0
- package/packages/scrabble-solver/src/icons/Flag.svg +2 -2
- package/packages/scrabble-solver/src/icons/FlagFill.svg +4 -0
- package/packages/scrabble-solver/src/icons/Square.svg +4 -0
- package/packages/scrabble-solver/src/icons/SquareFill.svg +4 -0
- package/packages/scrabble-solver/src/icons/index.ts +3 -0
- 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/AutoGroupTilesSetting/AutoGroupTilesSetting.tsx +1 -2
- package/packages/scrabble-solver/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.module.scss +1 -1
- package/packages/scrabble-solver/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.tsx +1 -2
- package/packages/scrabble-solver/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.module.scss +14 -24
- package/packages/scrabble-solver/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.tsx +1 -2
- package/packages/scrabble-solver/src/pages/_app.tsx +9 -5
- package/packages/scrabble-solver/src/pages/index.module.scss +1 -2
- package/packages/scrabble-solver/src/pages/index.tsx +10 -8
- package/packages/scrabble-solver/src/parameters/index.ts +12 -0
- package/packages/scrabble-solver/src/state/slices/boardSlice.ts +5 -5
- package/packages/scrabble-solver/src/styles/animations.scss +10 -0
- package/packages/scrabble-solver/src/styles/global.scss +2 -2
- package/packages/scrabble-solver/src/styles/mixins.scss +60 -3
- package/packages/scrabble-solver/src/styles/variables.scss +43 -33
- package/packages/scrabble-solver/src/types/index.ts +1 -0
- package/packages/solver/package-lock.json +2 -2
- package/packages/solver/package.json +5 -5
- package/packages/types/package-lock.json +3 -3
- package/packages/types/package.json +2 -2
- package/packages/word-definitions/package-lock.json +2 -2
- package/packages/word-definitions/package.json +2 -2
- package/packages/word-lists/package-lock.json +2 -2
- package/packages/word-lists/package.json +2 -2
- package/packages/scrabble-solver/.next/server/chunks/210.js +0 -122
- package/packages/scrabble-solver/.next/server/chunks/579.js +0 -3925
- package/packages/scrabble-solver/.next/server/chunks/676.js +0 -32
- package/packages/scrabble-solver/.next/static/6RggBFm8kHrh-k1-CG3um/_buildManifest.js +0 -1
- package/packages/scrabble-solver/.next/static/chunks/490-d29992f1c264d70e.js +0 -5
- package/packages/scrabble-solver/.next/static/chunks/509-6ad4482d4351452c.js +0 -1
- package/packages/scrabble-solver/.next/static/chunks/main-f11614d8aa7ee555.js +0 -1
- package/packages/scrabble-solver/.next/static/chunks/pages/_app-c58cfa832b76cc87.js +0 -24
- package/packages/scrabble-solver/.next/static/chunks/pages/index-146039f501e49c08.js +0 -1
- package/packages/scrabble-solver/.next/static/chunks/webpack-59c5c889f52620d6.js +0 -1
- package/packages/scrabble-solver/.next/static/css/4482c4a0064d3807.css +0 -1
- package/packages/scrabble-solver/.next/static/css/78e42ad01f580f64.css +0 -1
- package/packages/scrabble-solver/.next/static/css/9d1013ec684361b9.css +0 -1
- package/packages/scrabble-solver/src/components/Board/components/Cell/Button.tsx +0 -32
- /package/packages/scrabble-solver/.next/static/{6RggBFm8kHrh-k1-CG3um → fZRsz4P0gQ8Wgb9jP8eap}/_ssgManifest.js +0 -0
|
@@ -24,18 +24,20 @@
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
&.blank {
|
|
27
|
-
--background-color: white;
|
|
27
|
+
--background-color: var(--color--white);
|
|
28
28
|
|
|
29
|
+
.placeholder,
|
|
29
30
|
.character {
|
|
30
|
-
color:
|
|
31
|
+
color: var(--color--foreground);
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
&.highlighted {
|
|
35
36
|
--background-color: var(--color--primary);
|
|
36
37
|
|
|
37
|
-
color:
|
|
38
|
+
color: var(--color--primary--opposite);
|
|
38
39
|
|
|
40
|
+
.placeholder,
|
|
39
41
|
.character {
|
|
40
42
|
color: inherit;
|
|
41
43
|
}
|
|
@@ -45,12 +47,6 @@
|
|
|
45
47
|
}
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
&.invalid {
|
|
49
|
-
--background-color: var(--color--red--light);
|
|
50
|
-
|
|
51
|
-
color: var(--color--error);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
50
|
&:not(.disabled) {
|
|
55
51
|
.input::selection {
|
|
56
52
|
--background--color: transparent;
|
|
@@ -59,7 +55,8 @@
|
|
|
59
55
|
}
|
|
60
56
|
|
|
61
57
|
.input,
|
|
62
|
-
.character
|
|
58
|
+
.character,
|
|
59
|
+
.placeholder {
|
|
63
60
|
padding: 0;
|
|
64
61
|
font-weight: bold;
|
|
65
62
|
text-transform: uppercase;
|
|
@@ -77,7 +74,8 @@
|
|
|
77
74
|
font-size: 16px; // prevent iOS from automatically zooming in on focus
|
|
78
75
|
}
|
|
79
76
|
|
|
80
|
-
.character
|
|
77
|
+
.character,
|
|
78
|
+
.placeholder {
|
|
81
79
|
position: absolute;
|
|
82
80
|
top: 0;
|
|
83
81
|
right: 0;
|
|
@@ -97,6 +95,18 @@
|
|
|
97
95
|
|
|
98
96
|
.raised & {
|
|
99
97
|
box-shadow: inset -2px -2px 2px -1px rgba(34, 34, 34, 0.8);
|
|
98
|
+
|
|
99
|
+
@include media('<xs') {
|
|
100
|
+
box-shadow: inset -2px -2px 1px -1px rgba(34, 34, 34, 0.8);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.character {
|
|
106
|
+
opacity: 1;
|
|
107
|
+
|
|
108
|
+
.empty & {
|
|
109
|
+
opacity: 0;
|
|
100
110
|
}
|
|
101
111
|
}
|
|
102
112
|
|
|
@@ -130,6 +140,8 @@
|
|
|
130
140
|
position: absolute;
|
|
131
141
|
width: $size;
|
|
132
142
|
height: $size;
|
|
143
|
+
background-color: var(--color--error--opposite);
|
|
144
|
+
color: var(--color--error);
|
|
133
145
|
|
|
134
146
|
[dir='ltr'] & {
|
|
135
147
|
top: 0;
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { EMPTY_CELL } from '@scrabble-solver/constants';
|
|
2
|
+
import mergeRefs from 'merge-refs';
|
|
2
3
|
import {
|
|
3
4
|
ChangeEventHandler,
|
|
4
|
-
createRef,
|
|
5
5
|
FocusEventHandler,
|
|
6
6
|
FunctionComponent,
|
|
7
7
|
KeyboardEventHandler,
|
|
8
8
|
RefObject,
|
|
9
9
|
useEffect,
|
|
10
10
|
useMemo,
|
|
11
|
+
useRef,
|
|
11
12
|
} from 'react';
|
|
12
13
|
|
|
14
|
+
import { useMediaQuery } from 'hooks';
|
|
13
15
|
import { getTileSizes, noop } from 'lib';
|
|
16
|
+
import { EASE_OUT_CUBIC, TILE_APPEAR_DURATION, TILE_APPEAR_KEYFRAMES } from 'parameters';
|
|
14
17
|
import { selectLocale, useTypedSelector } from 'state';
|
|
15
18
|
|
|
16
19
|
import TilePure from './TilePure';
|
|
@@ -42,7 +45,7 @@ const Tile: FunctionComponent<Props> = ({
|
|
|
42
45
|
character = '',
|
|
43
46
|
disabled,
|
|
44
47
|
highlighted,
|
|
45
|
-
inputRef
|
|
48
|
+
inputRef,
|
|
46
49
|
isBlank,
|
|
47
50
|
isValid,
|
|
48
51
|
placeholder,
|
|
@@ -59,21 +62,35 @@ const Tile: FunctionComponent<Props> = ({
|
|
|
59
62
|
const style = useMemo(() => ({ height: tileSize, width: tileSize }), [tileSize]);
|
|
60
63
|
const characterStyle = useMemo(() => ({ fontSize: tileFontSize }), [tileFontSize]);
|
|
61
64
|
const pointsStyle = useMemo(() => ({ fontSize: pointsFontSize }), [pointsFontSize]);
|
|
62
|
-
const
|
|
65
|
+
const ref = useRef<HTMLInputElement>(null);
|
|
66
|
+
const mergedRef = inputRef ? mergeRefs(ref, inputRef) : ref;
|
|
63
67
|
const isEmpty = !character || character === EMPTY_CELL;
|
|
64
|
-
const
|
|
68
|
+
const isLessThanXs = useMediaQuery('<xs');
|
|
69
|
+
const canShowPoints = (isBlank || !isEmpty) && typeof points !== 'undefined' && !isLessThanXs;
|
|
65
70
|
const pointsFormatted = typeof points === 'number' ? points.toLocaleString(locale) : '';
|
|
66
71
|
|
|
67
72
|
const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = (event) => {
|
|
68
|
-
|
|
73
|
+
ref.current?.select();
|
|
69
74
|
onKeyDown(event);
|
|
70
75
|
};
|
|
71
76
|
|
|
72
77
|
useEffect(() => {
|
|
73
|
-
if (autoFocus &&
|
|
74
|
-
|
|
78
|
+
if (autoFocus && ref.current) {
|
|
79
|
+
ref.current.focus();
|
|
75
80
|
}
|
|
76
|
-
}, [autoFocus,
|
|
81
|
+
}, [autoFocus, ref]);
|
|
82
|
+
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
if (!ref.current?.parentElement || !character) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
ref.current.parentElement.animate(TILE_APPEAR_KEYFRAMES, {
|
|
89
|
+
duration: TILE_APPEAR_DURATION,
|
|
90
|
+
easing: EASE_OUT_CUBIC,
|
|
91
|
+
fill: 'forwards',
|
|
92
|
+
});
|
|
93
|
+
}, [character]);
|
|
77
94
|
|
|
78
95
|
return (
|
|
79
96
|
<TilePure
|
|
@@ -85,7 +102,7 @@ const Tile: FunctionComponent<Props> = ({
|
|
|
85
102
|
className={className}
|
|
86
103
|
disabled={disabled}
|
|
87
104
|
highlighted={highlighted}
|
|
88
|
-
inputRef={
|
|
105
|
+
inputRef={mergedRef}
|
|
89
106
|
isBlank={isBlank}
|
|
90
107
|
isValid={isValid}
|
|
91
108
|
placeholder={placeholder}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
FunctionComponent,
|
|
7
7
|
KeyboardEventHandler,
|
|
8
8
|
memo,
|
|
9
|
-
|
|
9
|
+
Ref,
|
|
10
10
|
} from 'react';
|
|
11
11
|
|
|
12
12
|
import { ExclamationSquareFill } from 'icons';
|
|
@@ -22,7 +22,7 @@ interface Props {
|
|
|
22
22
|
className?: string;
|
|
23
23
|
disabled?: boolean;
|
|
24
24
|
highlighted?: boolean;
|
|
25
|
-
inputRef:
|
|
25
|
+
inputRef: Ref<HTMLInputElement>;
|
|
26
26
|
isBlank?: boolean;
|
|
27
27
|
isValid?: boolean;
|
|
28
28
|
placeholder?: string;
|
|
@@ -66,7 +66,6 @@ const TilePure: FunctionComponent<Props> = ({
|
|
|
66
66
|
[styles.disabled]: disabled,
|
|
67
67
|
[styles.empty]: !character,
|
|
68
68
|
[styles.highlighted]: highlighted,
|
|
69
|
-
[styles.invalid]: !isValid,
|
|
70
69
|
[styles.raised]: raised,
|
|
71
70
|
[styles.points1]: points === 1,
|
|
72
71
|
[styles.points2]: points === 2,
|
|
@@ -93,8 +92,14 @@ const TilePure: FunctionComponent<Props> = ({
|
|
|
93
92
|
onKeyDown={onKeyDown}
|
|
94
93
|
/>
|
|
95
94
|
|
|
95
|
+
{placeholder && (
|
|
96
|
+
<div className={styles.placeholder} style={characterStyle} tabIndex={-1}>
|
|
97
|
+
{placeholder}
|
|
98
|
+
</div>
|
|
99
|
+
)}
|
|
100
|
+
|
|
96
101
|
<div className={styles.character} style={characterStyle} tabIndex={-1}>
|
|
97
|
-
{character
|
|
102
|
+
{character}
|
|
98
103
|
</div>
|
|
99
104
|
|
|
100
105
|
{canShowPoints && (
|
|
@@ -10,9 +10,9 @@ $arrow-size: 4px;
|
|
|
10
10
|
padding: var(--spacing--s) var(--spacing--m);
|
|
11
11
|
box-shadow: var(--box-shadow);
|
|
12
12
|
border-radius: var(--border--radius);
|
|
13
|
-
background-color: var(--tooltip--background);
|
|
14
|
-
color: var(--tooltip--foreground);
|
|
15
|
-
z-index:
|
|
13
|
+
background-color: var(--color--tooltip--background);
|
|
14
|
+
color: var(--color--tooltip--foreground);
|
|
15
|
+
z-index: var(--z-index--tooltip);
|
|
16
16
|
|
|
17
17
|
&.top {
|
|
18
18
|
.arrow {
|
|
@@ -21,7 +21,7 @@ $arrow-size: 4px;
|
|
|
21
21
|
&::after {
|
|
22
22
|
left: 0;
|
|
23
23
|
bottom: 0;
|
|
24
|
-
border-top-color: var(--tooltip--background);
|
|
24
|
+
border-top-color: var(--color--tooltip--background);
|
|
25
25
|
border-bottom: none;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -34,7 +34,7 @@ $arrow-size: 4px;
|
|
|
34
34
|
&::after {
|
|
35
35
|
left: 0;
|
|
36
36
|
top: 0;
|
|
37
|
-
border-right-color: var(--tooltip--background);
|
|
37
|
+
border-right-color: var(--color--tooltip--background);
|
|
38
38
|
border-left: none;
|
|
39
39
|
}
|
|
40
40
|
}
|
|
@@ -47,7 +47,7 @@ $arrow-size: 4px;
|
|
|
47
47
|
&::after {
|
|
48
48
|
top: 0;
|
|
49
49
|
left: 0;
|
|
50
|
-
border-bottom-color: var(--tooltip--background);
|
|
50
|
+
border-bottom-color: var(--color--tooltip--background);
|
|
51
51
|
border-top: none;
|
|
52
52
|
}
|
|
53
53
|
}
|
|
@@ -60,7 +60,7 @@ $arrow-size: 4px;
|
|
|
60
60
|
&::after {
|
|
61
61
|
right: 0;
|
|
62
62
|
top: 0;
|
|
63
|
-
border-left-color: var(--tooltip--background);
|
|
63
|
+
border-left-color: var(--color--tooltip--background);
|
|
64
64
|
border-right: none;
|
|
65
65
|
}
|
|
66
66
|
}
|
|
@@ -19,6 +19,7 @@ export { default as Rack } from './Rack';
|
|
|
19
19
|
export { default as Radio } from './Radio';
|
|
20
20
|
export { default as Results } from './Results';
|
|
21
21
|
export { default as ResultsInput } from './ResultsInput';
|
|
22
|
+
export { default as SeoMessage } from './SeoMessage';
|
|
22
23
|
export { default as Sizer } from './Sizer';
|
|
23
24
|
export { default as Solver } from './Solver';
|
|
24
25
|
export { default as SplashScreen } from './SplashScreen';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
2
|
import { useDispatch } from 'react-redux';
|
|
3
3
|
import { useEffectOnce } from 'react-use';
|
|
4
4
|
|
|
@@ -7,6 +7,7 @@ import { boardSlice, localStorage, selectBoard, useTypedSelector } from 'state';
|
|
|
7
7
|
const useLocalStorageBoard = (): void => {
|
|
8
8
|
const dispatch = useDispatch();
|
|
9
9
|
const board = useTypedSelector(selectBoard);
|
|
10
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
10
11
|
|
|
11
12
|
useEffectOnce(() => {
|
|
12
13
|
const persistedBoard = localStorage.getBoard();
|
|
@@ -14,13 +15,15 @@ const useLocalStorageBoard = (): void => {
|
|
|
14
15
|
if (persistedBoard) {
|
|
15
16
|
dispatch(boardSlice.actions.init(persistedBoard));
|
|
16
17
|
}
|
|
18
|
+
|
|
19
|
+
setIsLoaded(true);
|
|
17
20
|
});
|
|
18
21
|
|
|
19
22
|
useEffect(() => {
|
|
20
|
-
if (board) {
|
|
23
|
+
if (board && isLoaded) {
|
|
21
24
|
localStorage.setBoard(board);
|
|
22
25
|
}
|
|
23
|
-
}, [board]);
|
|
26
|
+
}, [board, isLoaded]);
|
|
24
27
|
};
|
|
25
28
|
|
|
26
29
|
export default useLocalStorageBoard;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
2
|
import { useDispatch } from 'react-redux';
|
|
3
3
|
import { useEffectOnce } from 'react-use';
|
|
4
4
|
|
|
@@ -7,6 +7,7 @@ import { localStorage, selectConfigId, settingsSlice, useTypedSelector } from 's
|
|
|
7
7
|
const useLocalStorageConfigId = (): void => {
|
|
8
8
|
const dispatch = useDispatch();
|
|
9
9
|
const configId = useTypedSelector(selectConfigId);
|
|
10
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
10
11
|
|
|
11
12
|
useEffectOnce(() => {
|
|
12
13
|
const persistedConfigId = localStorage.getConfigId();
|
|
@@ -14,13 +15,15 @@ const useLocalStorageConfigId = (): void => {
|
|
|
14
15
|
if (persistedConfigId) {
|
|
15
16
|
dispatch(settingsSlice.actions.init({ configId: persistedConfigId }));
|
|
16
17
|
}
|
|
18
|
+
|
|
19
|
+
setIsLoaded(true);
|
|
17
20
|
});
|
|
18
21
|
|
|
19
22
|
useEffect(() => {
|
|
20
|
-
if (configId) {
|
|
23
|
+
if (configId && isLoaded) {
|
|
21
24
|
localStorage.setConfigId(configId);
|
|
22
25
|
}
|
|
23
|
-
}, [configId]);
|
|
26
|
+
}, [configId, isLoaded]);
|
|
24
27
|
};
|
|
25
28
|
|
|
26
29
|
export default useLocalStorageConfigId;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
2
|
import { useDispatch } from 'react-redux';
|
|
3
3
|
import { useEffectOnce } from 'react-use';
|
|
4
4
|
|
|
@@ -8,6 +8,7 @@ import { localStorage, selectLocale, settingsSlice, useTypedSelector } from 'sta
|
|
|
8
8
|
const useLocalStorageLocale = (): void => {
|
|
9
9
|
const dispatch = useDispatch();
|
|
10
10
|
const locale = useTypedSelector(selectLocale);
|
|
11
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
11
12
|
|
|
12
13
|
useEffectOnce(() => {
|
|
13
14
|
const persistedLocale = localStorage.getLocale();
|
|
@@ -17,13 +18,15 @@ const useLocalStorageLocale = (): void => {
|
|
|
17
18
|
} else {
|
|
18
19
|
dispatch(settingsSlice.actions.init({ locale: detectLocale() }));
|
|
19
20
|
}
|
|
21
|
+
|
|
22
|
+
setIsLoaded(true);
|
|
20
23
|
});
|
|
21
24
|
|
|
22
25
|
useEffect(() => {
|
|
23
|
-
if (locale) {
|
|
26
|
+
if (locale && isLoaded) {
|
|
24
27
|
localStorage.setLocale(locale);
|
|
25
28
|
}
|
|
26
|
-
}, [locale]);
|
|
29
|
+
}, [locale, isLoaded]);
|
|
27
30
|
};
|
|
28
31
|
|
|
29
32
|
export default useLocalStorageLocale;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
2
|
import { useDispatch } from 'react-redux';
|
|
3
3
|
import { useEffectOnce } from 'react-use';
|
|
4
4
|
|
|
@@ -7,6 +7,7 @@ import { localStorage, rackSlice, selectRack, useTypedSelector } from 'state';
|
|
|
7
7
|
const useLocalStorageRack = (): void => {
|
|
8
8
|
const dispatch = useDispatch();
|
|
9
9
|
const rack = useTypedSelector(selectRack);
|
|
10
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
10
11
|
|
|
11
12
|
useEffectOnce(() => {
|
|
12
13
|
const persistedRack = localStorage.getRack();
|
|
@@ -14,13 +15,15 @@ const useLocalStorageRack = (): void => {
|
|
|
14
15
|
if (persistedRack) {
|
|
15
16
|
dispatch(rackSlice.actions.init(persistedRack));
|
|
16
17
|
}
|
|
18
|
+
|
|
19
|
+
setIsLoaded(true);
|
|
17
20
|
});
|
|
18
21
|
|
|
19
22
|
useEffect(() => {
|
|
20
|
-
if (rack) {
|
|
23
|
+
if (rack && isLoaded) {
|
|
21
24
|
localStorage.setRack(rack);
|
|
22
25
|
}
|
|
23
|
-
}, [rack]);
|
|
26
|
+
}, [isLoaded, rack]);
|
|
24
27
|
};
|
|
25
28
|
|
|
26
29
|
export default useLocalStorageRack;
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"dictionary.empty-state.not-allowed": "Dieses Wort ist nicht erlaubt.",
|
|
23
23
|
"dictionary.empty-state.uninitialized": "Die Wörterbuchdefinition des letzten markierten Wortes wird hier angezeigt.",
|
|
24
24
|
"dictionary.input.placeholder": "Durchsuche Wörterbuch...",
|
|
25
|
+
"dictionary.input.title": "Durch Kommas getrennte Wörter",
|
|
25
26
|
"empty-state.error": "Fehler",
|
|
26
27
|
"empty-state.info": "Info",
|
|
27
28
|
"empty-state.success": "Juhuu!",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"dictionary.empty-state.not-allowed": "This word is not allowed.",
|
|
23
23
|
"dictionary.empty-state.uninitialized": "Dictionary definition of the most recently highlighted word will be shown here.",
|
|
24
24
|
"dictionary.input.placeholder": "Search dictionary...",
|
|
25
|
+
"dictionary.input.title": "Comma-separated words",
|
|
25
26
|
"empty-state.error": "Error",
|
|
26
27
|
"empty-state.info": "Info",
|
|
27
28
|
"empty-state.success": "Yeah!",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"dictionary.empty-state.not-allowed": "Esta palabra no es aceptable.",
|
|
23
23
|
"dictionary.empty-state.uninitialized": "Aquí se mostrará la definición del diccionario de la última palabra resaltada.",
|
|
24
24
|
"dictionary.input.placeholder": "Busca el diccionario...",
|
|
25
|
+
"dictionary.input.title": "Palabras separadas por comas",
|
|
25
26
|
"empty-state.error": "Error",
|
|
26
27
|
"empty-state.info": "Info",
|
|
27
28
|
"empty-state.success": "Sí!",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"dictionary.empty-state.not-allowed": "این کلمه مجاز نیست.",
|
|
23
23
|
"dictionary.empty-state.uninitialized": "معنی لغت اینجا نمایش داده خواهد شد.",
|
|
24
24
|
"dictionary.input.placeholder": "جستجو در فرهنگ لغت ...",
|
|
25
|
+
"dictionary.input.title": "کلمات جدا شده با کاما",
|
|
25
26
|
"empty-state.error": "خطا",
|
|
26
27
|
"empty-state.info": "اطلاعات",
|
|
27
28
|
"empty-state.success": "حله!",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"dictionary.empty-state.not-allowed": "Ce mot n'est pas pas acceptable.",
|
|
23
23
|
"dictionary.empty-state.uninitialized": "La définition dictionaire du dernier mot surligné sera affichée ici.",
|
|
24
24
|
"dictionary.input.placeholder": "Rechercher dans le dictionnaire...",
|
|
25
|
+
"dictionary.input.title": "Mots séparées par des virgules",
|
|
25
26
|
"empty-state.error": "Erreur",
|
|
26
27
|
"empty-state.info": "Info",
|
|
27
28
|
"empty-state.success": "Ouais!",
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"dictionary.empty-state.not-allowed": "To słowo nie jest dopuszczalne w grach.",
|
|
23
23
|
"dictionary.empty-state.uninitialized": "Tu zostanie wyświetlona słownikowa definicja ostatnio podświetlonego słowa.",
|
|
24
24
|
"dictionary.input.placeholder": "Szukaj w słowniku...",
|
|
25
|
+
"dictionary.input.title": "Słowa rozdzielone przecinkiem",
|
|
25
26
|
"empty-state.error": "Błąd",
|
|
26
27
|
"empty-state.info": "Info",
|
|
27
28
|
"empty-state.success": "Hurra!",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- https://icons.getbootstrap.com/icons/flag
|
|
1
|
+
<!-- https://icons.getbootstrap.com/icons/flag/ -->
|
|
2
2
|
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
|
3
|
-
<path d="M14.778.085A.5.5 0 0 1 15 .5V8a.5.5 0 0 1-.314.464L14.5 8l.186.464-.003.001-.006.003-.023.009a12.435 12.435 0 0 1-.397.15c-.264.095-.631.223-1.047.35-.816.252-1.879.523-2.71.523-.847 0-1.548-.28-2.158-.525l-.028-.01C7.68 8.71 7.14 8.5 6.5 8.5c-.7 0-1.638.23-2.437.477A19.626 19.626 0 0 0 3 9.342V15.5a.5.5 0 0 1-1 0V.5a.5.5 0 0 1 1 0v.282c.226-.079.496-.17.79-.26C4.606.272 5.67 0 6.5 0c.84 0 1.524.277 2.121.519l.043.018C9.286.788 9.828 1 10.5 1c.7 0 1.638-.23 2.437-.477a19.587 19.587 0 0 0 1.349-.476l.019-.007.004-.002h.
|
|
3
|
+
<path d="M14.778.085A.5.5 0 0 1 15 .5V8a.5.5 0 0 1-.314.464L14.5 8l.186.464-.003.001-.006.003-.023.009a12.435 12.435 0 0 1-.397.15c-.264.095-.631.223-1.047.35-.816.252-1.879.523-2.71.523-.847 0-1.548-.28-2.158-.525l-.028-.01C7.68 8.71 7.14 8.5 6.5 8.5c-.7 0-1.638.23-2.437.477A19.626 19.626 0 0 0 3 9.342V15.5a.5.5 0 0 1-1 0V.5a.5.5 0 0 1 1 0v.282c.226-.079.496-.17.79-.26C4.606.272 5.67 0 6.5 0c.84 0 1.524.277 2.121.519l.043.018C9.286.788 9.828 1 10.5 1c.7 0 1.638-.23 2.437-.477a19.587 19.587 0 0 0 1.349-.476l.019-.007.004-.002h.001M14 1.221c-.22.078-.48.167-.766.255-.81.252-1.872.523-2.734.523-.886 0-1.592-.286-2.203-.534l-.008-.003C7.662 1.21 7.139 1 6.5 1c-.669 0-1.606.229-2.415.478A21.294 21.294 0 0 0 3 1.845v6.433c.22-.078.48-.167.766-.255C4.576 7.77 5.638 7.5 6.5 7.5c.847 0 1.548.28 2.158.525l.028.01C9.32 8.29 9.86 8.5 10.5 8.5c.668 0 1.606-.229 2.415-.478A21.317 21.317 0 0 0 14 7.655V1.222z" fill="currentColor" />
|
|
4
4
|
</svg>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<!-- https://icons.getbootstrap.com/icons/flag-fill/ -->
|
|
2
|
+
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
|
3
|
+
<path d="M14.778.085A.5.5 0 0 1 15 .5V8a.5.5 0 0 1-.314.464L14.5 8l.186.464-.003.001-.006.003-.023.009a12.435 12.435 0 0 1-.397.15c-.264.095-.631.223-1.047.35-.816.252-1.879.523-2.71.523-.847 0-1.548-.28-2.158-.525l-.028-.01C7.68 8.71 7.14 8.5 6.5 8.5c-.7 0-1.638.23-2.437.477A19.626 19.626 0 0 0 3 9.342V15.5a.5.5 0 0 1-1 0V.5a.5.5 0 0 1 1 0v.282c.226-.079.496-.17.79-.26C4.606.272 5.67 0 6.5 0c.84 0 1.524.277 2.121.519l.043.018C9.286.788 9.828 1 10.5 1c.7 0 1.638-.23 2.437-.477a19.587 19.587 0 0 0 1.349-.476l.019-.007.004-.002h.001" fill="currentColor" />
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<!-- https://icons.getbootstrap.com/icons/square/ -->
|
|
2
|
+
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
|
3
|
+
<path d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h12zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z" fill="currentColor" />
|
|
4
|
+
</svg>
|
|
@@ -19,6 +19,7 @@ export { default as Eraser } from './Eraser.svg';
|
|
|
19
19
|
export { default as ExclamationSquareFill } from './ExclamationSquareFill.svg';
|
|
20
20
|
export { default as ExclamationTriangleFill } from './ExclamationTriangleFill.svg';
|
|
21
21
|
export { default as Flag } from './Flag.svg';
|
|
22
|
+
export { default as FlagFill } from './FlagFill.svg';
|
|
22
23
|
export { default as FlagEs } from './FlagEs.svg';
|
|
23
24
|
export { default as FlagFa } from './FlagFa.svg';
|
|
24
25
|
export { default as FlagFr } from './FlagFr.svg';
|
|
@@ -34,4 +35,6 @@ export { default as Sack } from './Sack.svg';
|
|
|
34
35
|
export { default as Search } from './Search.svg';
|
|
35
36
|
export { default as SortDown } from './SortDown.svg';
|
|
36
37
|
export { default as SortUp } from './SortUp.svg';
|
|
38
|
+
export { default as Square } from './Square.svg';
|
|
39
|
+
export { default as SquareFill } from './SquareFill.svg';
|
|
37
40
|
export { default as Star } from './Star.svg';
|
|
@@ -40,12 +40,11 @@ const AutoGroupTilesSetting: FunctionComponent<Props> = ({ className, disabled }
|
|
|
40
40
|
|
|
41
41
|
return (
|
|
42
42
|
<div className={className}>
|
|
43
|
-
{options.map((option
|
|
43
|
+
{options.map((option) => (
|
|
44
44
|
<Radio
|
|
45
45
|
checked={value === parseValue(option.value)}
|
|
46
46
|
className={styles.option}
|
|
47
47
|
disabled={disabled}
|
|
48
|
-
id={`autoGroupTiles-${index}`}
|
|
49
48
|
key={option.value}
|
|
50
49
|
name="autoGroupTiles"
|
|
51
50
|
value={option.value}
|
package/packages/scrabble-solver/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.tsx
CHANGED
|
@@ -22,12 +22,11 @@ const ConfigSetting: FunctionComponent<Props> = ({ className, disabled }) => {
|
|
|
22
22
|
|
|
23
23
|
return (
|
|
24
24
|
<div className={className}>
|
|
25
|
-
{options.map((option
|
|
25
|
+
{options.map((option) => (
|
|
26
26
|
<Radio
|
|
27
27
|
checked={configId === option.value}
|
|
28
28
|
className={styles.option}
|
|
29
29
|
disabled={disabled}
|
|
30
|
-
id={`configId-${index}`}
|
|
31
30
|
key={option.value}
|
|
32
31
|
name="configId"
|
|
33
32
|
value={option.value}
|
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
@import 'styles/mixins';
|
|
2
2
|
|
|
3
3
|
.option {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
&:last-child {
|
|
7
|
-
margin-bottom: 0;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
&:hover,
|
|
11
|
-
&.checked {
|
|
12
|
-
.flag {
|
|
13
|
-
box-shadow: var(--box-shadow);
|
|
14
|
-
}
|
|
4
|
+
& + & {
|
|
5
|
+
margin-top: var(--spacing--m);
|
|
15
6
|
}
|
|
16
7
|
}
|
|
17
8
|
|
|
@@ -19,10 +10,10 @@
|
|
|
19
10
|
display: flex;
|
|
20
11
|
align-items: center;
|
|
21
12
|
gap: var(--spacing--l);
|
|
22
|
-
font-family:
|
|
13
|
+
font-family: var(--font--family--latin);
|
|
23
14
|
|
|
24
15
|
&.fa {
|
|
25
|
-
font-family:
|
|
16
|
+
font-family: var(--font--family--arabic);
|
|
26
17
|
}
|
|
27
18
|
}
|
|
28
19
|
|
|
@@ -30,17 +21,16 @@
|
|
|
30
21
|
$height: 32px;
|
|
31
22
|
|
|
32
23
|
height: $height;
|
|
33
|
-
box-shadow: var(--box-shadow--null);
|
|
34
24
|
transition: var(--transition);
|
|
35
25
|
|
|
36
|
-
&.
|
|
37
|
-
$aspect-ratio: 1.
|
|
26
|
+
&.de {
|
|
27
|
+
$aspect-ratio: 1.6;
|
|
38
28
|
|
|
39
29
|
width: $height * $aspect-ratio;
|
|
40
30
|
}
|
|
41
31
|
|
|
42
|
-
&.
|
|
43
|
-
$aspect-ratio: 1.
|
|
32
|
+
&.es {
|
|
33
|
+
$aspect-ratio: 1.5;
|
|
44
34
|
|
|
45
35
|
width: $height * $aspect-ratio;
|
|
46
36
|
}
|
|
@@ -51,6 +41,12 @@
|
|
|
51
41
|
width: $height * $aspect-ratio;
|
|
52
42
|
}
|
|
53
43
|
|
|
44
|
+
&.fr {
|
|
45
|
+
$aspect-ratio: 1.6;
|
|
46
|
+
|
|
47
|
+
width: $height * $aspect-ratio;
|
|
48
|
+
}
|
|
49
|
+
|
|
54
50
|
&.gb {
|
|
55
51
|
$aspect-ratio: 2;
|
|
56
52
|
|
|
@@ -68,10 +64,4 @@
|
|
|
68
64
|
|
|
69
65
|
width: $height * $aspect-ratio;
|
|
70
66
|
}
|
|
71
|
-
|
|
72
|
-
&.de {
|
|
73
|
-
$aspect-ratio: 1.6;
|
|
74
|
-
|
|
75
|
-
width: $height * $aspect-ratio;
|
|
76
|
-
}
|
|
77
67
|
}
|
package/packages/scrabble-solver/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.tsx
CHANGED
|
@@ -25,14 +25,13 @@ const LocaleSetting: FunctionComponent<Props> = ({ className, disabled }) => {
|
|
|
25
25
|
|
|
26
26
|
return (
|
|
27
27
|
<div className={className}>
|
|
28
|
-
{options.map(({ Icon, ...option }
|
|
28
|
+
{options.map(({ Icon, ...option }) => (
|
|
29
29
|
<Radio
|
|
30
30
|
checked={locale === option.value}
|
|
31
31
|
className={classNames(styles.option, className, {
|
|
32
32
|
[styles.checked]: locale === option.value,
|
|
33
33
|
})}
|
|
34
34
|
disabled={disabled}
|
|
35
|
-
id={`locale-${index}`}
|
|
36
35
|
key={option.value}
|
|
37
36
|
name="locale"
|
|
38
37
|
value={option.value}
|