scrabble-solver 2.10.7 → 2.10.8
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 +1 -1
- 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 +7 -13
- 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/next-server.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/prerender-manifest.json +1 -1
- package/packages/scrabble-solver/.next/routes-manifest.json +1 -1
- package/packages/scrabble-solver/.next/server/chunks/176.js +4273 -214
- 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 +2 -2
- package/packages/scrabble-solver/.next/server/pages/_app.js +296 -13
- package/packages/scrabble-solver/.next/server/pages/_app.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/_document.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/solve.js +17 -0
- package/packages/scrabble-solver/.next/server/pages/index.html +1 -9
- package/packages/scrabble-solver/.next/server/pages/index.js +23 -16
- 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/Cs23uxWG6AxS72F2yrjHu/_buildManifest.js +1 -0
- package/packages/scrabble-solver/.next/static/chunks/pages/{404-67383848027ec49b.js → 404-8cab6d62fe4ead73.js} +1 -1
- package/packages/scrabble-solver/.next/static/chunks/pages/_app-dcbbb823dc93a031.js +28 -0
- package/packages/scrabble-solver/.next/static/chunks/pages/index-df1ff01aa82d2d4d.js +1 -0
- package/packages/scrabble-solver/.next/static/css/bf2e969b88c4e3dd.css +2 -0
- package/packages/scrabble-solver/.next/static/css/d1cc6b79b211b7b8.css +1 -0
- package/packages/scrabble-solver/.next/trace +55 -55
- package/packages/scrabble-solver/package-lock.json +22 -2
- package/packages/scrabble-solver/package.json +9 -8
- package/packages/scrabble-solver/src/components/Badge/Badge.module.scss +1 -1
- package/packages/scrabble-solver/src/components/Board/components/Cell/Cell.module.scss +32 -64
- package/packages/scrabble-solver/src/components/Board/components/Cell/CellPure.tsx +15 -22
- package/packages/scrabble-solver/src/components/Button/Button.module.scss +2 -2
- 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 +4 -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/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 +49 -11
- package/packages/scrabble-solver/src/components/Tile/Tile.tsx +23 -8
- package/packages/scrabble-solver/src/components/Tile/TilePure.tsx +27 -20
- 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/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.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 +10 -0
- package/packages/scrabble-solver/src/state/slices/boardSlice.ts +5 -5
- package/packages/scrabble-solver/src/styles/mixins.scss +4 -2
- package/packages/scrabble-solver/src/styles/variables.scss +39 -32
- 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/579.js +0 -3925
- 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/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/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 → Cs23uxWG6AxS72F2yrjHu}/_ssgManifest.js +0 -0
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
.resultCandidatePicker {
|
|
4
4
|
display: flex;
|
|
5
|
-
align-items: center;
|
|
6
5
|
gap: var(--spacing--l);
|
|
7
6
|
|
|
8
7
|
@include media('<xs') {
|
|
@@ -14,6 +13,14 @@
|
|
|
14
13
|
flex: 0 0 auto;
|
|
15
14
|
display: flex;
|
|
16
15
|
border-radius: var(--border--radius);
|
|
16
|
+
|
|
17
|
+
&.bothEnabled {
|
|
18
|
+
box-shadow: var(--box-shadow);
|
|
19
|
+
|
|
20
|
+
.button {
|
|
21
|
+
box-shadow: none;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
17
24
|
}
|
|
18
25
|
|
|
19
26
|
.button {
|
|
@@ -50,7 +57,7 @@
|
|
|
50
57
|
width: 100%;
|
|
51
58
|
border: var(--border);
|
|
52
59
|
border-radius: var(--border--radius);
|
|
53
|
-
background-color: white;
|
|
60
|
+
background-color: var(--color--white);
|
|
54
61
|
box-shadow: var(--box-shadow);
|
|
55
62
|
cursor: pointer;
|
|
56
63
|
|
|
@@ -34,6 +34,7 @@ const ResultCandidatePicker: FunctionComponent<Props> = ({ className, onResultCl
|
|
|
34
34
|
const disabled = isOutdated || !resultCandidate;
|
|
35
35
|
const isPreviousDisabled = index <= 0 || disabled;
|
|
36
36
|
const isNextDisabled = index >= results.length - 1 || disabled;
|
|
37
|
+
const bothEnabled = !isPreviousDisabled && !isNextDisabled;
|
|
37
38
|
|
|
38
39
|
const handleNextClick = () => {
|
|
39
40
|
if (!isNextDisabled) {
|
|
@@ -51,7 +52,7 @@ const ResultCandidatePicker: FunctionComponent<Props> = ({ className, onResultCl
|
|
|
51
52
|
|
|
52
53
|
return (
|
|
53
54
|
<div className={classNames(styles.resultCandidatePicker, className)} {...props}>
|
|
54
|
-
<div className={styles.buttons}>
|
|
55
|
+
<div className={classNames(styles.buttons, { [styles.bothEnabled]: bothEnabled })}>
|
|
55
56
|
<Button
|
|
56
57
|
aria-label={translate('common.previous')}
|
|
57
58
|
className={styles.button}
|
|
@@ -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;
|
|
@@ -58,8 +54,19 @@
|
|
|
58
54
|
}
|
|
59
55
|
}
|
|
60
56
|
|
|
57
|
+
.inputContainer {
|
|
58
|
+
position: absolute;
|
|
59
|
+
top: 0;
|
|
60
|
+
right: 0;
|
|
61
|
+
bottom: 0;
|
|
62
|
+
left: 0;
|
|
63
|
+
display: flex;
|
|
64
|
+
overflow: hidden;
|
|
65
|
+
}
|
|
66
|
+
|
|
61
67
|
.input,
|
|
62
|
-
.character
|
|
68
|
+
.character,
|
|
69
|
+
.placeholder {
|
|
63
70
|
padding: 0;
|
|
64
71
|
font-weight: bold;
|
|
65
72
|
text-transform: uppercase;
|
|
@@ -75,9 +82,26 @@
|
|
|
75
82
|
color: transparent;
|
|
76
83
|
border: none;
|
|
77
84
|
font-size: 16px; // prevent iOS from automatically zooming in on focus
|
|
85
|
+
|
|
86
|
+
// Hack for this Lighthouse warning:
|
|
87
|
+
// > Interactive elements like buttons and links should be large enough (48x48px), and have
|
|
88
|
+
// > enough space around them, to be easy enough to tap without overlapping onto other elements.
|
|
89
|
+
//
|
|
90
|
+
// .inputContainer exists only for the purpose of this hack
|
|
91
|
+
$min-tile-width: 20px;
|
|
92
|
+
$min-lighthouse-size: 48px;
|
|
93
|
+
|
|
94
|
+
position: absolute;
|
|
95
|
+
top: calc((100% - $min-lighthouse-size) / 2);
|
|
96
|
+
right: calc((100% - $min-lighthouse-size) / 2);
|
|
97
|
+
bottom: calc((100% - $min-lighthouse-size) / 2);
|
|
98
|
+
left: calc((100% - $min-lighthouse-size) / 2);
|
|
99
|
+
width: $min-lighthouse-size;
|
|
100
|
+
height: $min-lighthouse-size;
|
|
78
101
|
}
|
|
79
102
|
|
|
80
|
-
.character
|
|
103
|
+
.character,
|
|
104
|
+
.placeholder {
|
|
81
105
|
position: absolute;
|
|
82
106
|
top: 0;
|
|
83
107
|
right: 0;
|
|
@@ -97,6 +121,18 @@
|
|
|
97
121
|
|
|
98
122
|
.raised & {
|
|
99
123
|
box-shadow: inset -2px -2px 2px -1px rgba(34, 34, 34, 0.8);
|
|
124
|
+
|
|
125
|
+
@include media('<xs') {
|
|
126
|
+
box-shadow: inset -2px -2px 1px -1px rgba(34, 34, 34, 0.8);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.character {
|
|
132
|
+
opacity: 1;
|
|
133
|
+
|
|
134
|
+
.empty & {
|
|
135
|
+
opacity: 0;
|
|
100
136
|
}
|
|
101
137
|
}
|
|
102
138
|
|
|
@@ -130,6 +166,8 @@
|
|
|
130
166
|
position: absolute;
|
|
131
167
|
width: $size;
|
|
132
168
|
height: $size;
|
|
169
|
+
background-color: var(--color--error--opposite);
|
|
170
|
+
color: var(--color--error);
|
|
133
171
|
|
|
134
172
|
[dir='ltr'] & {
|
|
135
173
|
top: 0;
|
|
@@ -1,16 +1,18 @@
|
|
|
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
|
|
|
13
14
|
import { getTileSizes, noop } from 'lib';
|
|
15
|
+
import { EASE_OUT_CUBIC, TILE_APPEAR_DURATION, TILE_APPEAR_KEYFRAMES } from 'parameters';
|
|
14
16
|
import { selectLocale, useTypedSelector } from 'state';
|
|
15
17
|
|
|
16
18
|
import TilePure from './TilePure';
|
|
@@ -42,7 +44,7 @@ const Tile: FunctionComponent<Props> = ({
|
|
|
42
44
|
character = '',
|
|
43
45
|
disabled,
|
|
44
46
|
highlighted,
|
|
45
|
-
inputRef
|
|
47
|
+
inputRef,
|
|
46
48
|
isBlank,
|
|
47
49
|
isValid,
|
|
48
50
|
placeholder,
|
|
@@ -59,21 +61,34 @@ const Tile: FunctionComponent<Props> = ({
|
|
|
59
61
|
const style = useMemo(() => ({ height: tileSize, width: tileSize }), [tileSize]);
|
|
60
62
|
const characterStyle = useMemo(() => ({ fontSize: tileFontSize }), [tileFontSize]);
|
|
61
63
|
const pointsStyle = useMemo(() => ({ fontSize: pointsFontSize }), [pointsFontSize]);
|
|
62
|
-
const
|
|
64
|
+
const ref = useRef<HTMLInputElement>(null);
|
|
65
|
+
const mergedRef = inputRef ? mergeRefs(ref, inputRef) : ref;
|
|
63
66
|
const isEmpty = !character || character === EMPTY_CELL;
|
|
64
67
|
const canShowPoints = (isBlank || !isEmpty) && typeof points !== 'undefined';
|
|
65
68
|
const pointsFormatted = typeof points === 'number' ? points.toLocaleString(locale) : '';
|
|
66
69
|
|
|
67
70
|
const handleKeyDown: KeyboardEventHandler<HTMLInputElement> = (event) => {
|
|
68
|
-
|
|
71
|
+
ref.current?.select();
|
|
69
72
|
onKeyDown(event);
|
|
70
73
|
};
|
|
71
74
|
|
|
72
75
|
useEffect(() => {
|
|
73
|
-
if (autoFocus &&
|
|
74
|
-
|
|
76
|
+
if (autoFocus && ref.current) {
|
|
77
|
+
ref.current.focus();
|
|
75
78
|
}
|
|
76
|
-
}, [autoFocus,
|
|
79
|
+
}, [autoFocus, ref]);
|
|
80
|
+
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
if (!ref.current?.parentElement || !character) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
ref.current.parentElement.animate(TILE_APPEAR_KEYFRAMES, {
|
|
87
|
+
duration: TILE_APPEAR_DURATION,
|
|
88
|
+
easing: EASE_OUT_CUBIC,
|
|
89
|
+
fill: 'forwards',
|
|
90
|
+
});
|
|
91
|
+
}, [character]);
|
|
77
92
|
|
|
78
93
|
return (
|
|
79
94
|
<TilePure
|
|
@@ -85,7 +100,7 @@ const Tile: FunctionComponent<Props> = ({
|
|
|
85
100
|
className={className}
|
|
86
101
|
disabled={disabled}
|
|
87
102
|
highlighted={highlighted}
|
|
88
|
-
inputRef={
|
|
103
|
+
inputRef={mergedRef}
|
|
89
104
|
isBlank={isBlank}
|
|
90
105
|
isValid={isValid}
|
|
91
106
|
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,
|
|
@@ -76,25 +75,33 @@ const TilePure: FunctionComponent<Props> = ({
|
|
|
76
75
|
})}
|
|
77
76
|
style={style}
|
|
78
77
|
>
|
|
79
|
-
<
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
78
|
+
<div className={styles.inputContainer}>
|
|
79
|
+
<input
|
|
80
|
+
aria-label={ariaLabel}
|
|
81
|
+
autoCapitalize="none"
|
|
82
|
+
autoComplete="off"
|
|
83
|
+
autoCorrect="off"
|
|
84
|
+
autoFocus={autoFocus}
|
|
85
|
+
className={styles.input}
|
|
86
|
+
disabled={disabled}
|
|
87
|
+
ref={inputRef}
|
|
88
|
+
spellCheck={false}
|
|
89
|
+
tabIndex={tabIndex}
|
|
90
|
+
value={character || ''}
|
|
91
|
+
onChange={onChange}
|
|
92
|
+
onFocus={onFocus}
|
|
93
|
+
onKeyDown={onKeyDown}
|
|
94
|
+
/>
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
{placeholder && (
|
|
98
|
+
<div className={styles.placeholder} style={characterStyle} tabIndex={-1}>
|
|
99
|
+
{placeholder}
|
|
100
|
+
</div>
|
|
101
|
+
)}
|
|
95
102
|
|
|
96
103
|
<div className={styles.character} style={characterStyle} tabIndex={-1}>
|
|
97
|
-
{character
|
|
104
|
+
{character}
|
|
98
105
|
</div>
|
|
99
106
|
|
|
100
107
|
{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';
|
|
@@ -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), sans-serif;
|
|
23
14
|
|
|
24
15
|
&.fa {
|
|
25
|
-
font-family:
|
|
16
|
+
font-family: var(--font--family--arabic), var(--font--family), sans-serif;
|
|
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}
|
|
@@ -3,6 +3,7 @@ import Head from 'next/head';
|
|
|
3
3
|
import { FunctionComponent } from 'react';
|
|
4
4
|
import { Provider } from 'react-redux';
|
|
5
5
|
|
|
6
|
+
import { SeoMessage } from 'components';
|
|
6
7
|
import { createAppStore } from 'state';
|
|
7
8
|
|
|
8
9
|
import 'styles/global.scss';
|
|
@@ -10,10 +11,16 @@ import 'styles/global.scss';
|
|
|
10
11
|
const DESCRIPTION =
|
|
11
12
|
// eslint-disable-next-line max-len
|
|
12
13
|
'Scrabble Solver 2 - Free and open-source analysis tool for Scrabble and Literaki. Quickly find top scoring words using given letters and board state. Available in English, French, German, Polish & Spanish.';
|
|
14
|
+
|
|
13
15
|
const KEYWORDS = [
|
|
16
|
+
'Scrabble Solver',
|
|
14
17
|
'Scrabble',
|
|
15
18
|
'Solver',
|
|
19
|
+
'Board',
|
|
16
20
|
'Open-source',
|
|
21
|
+
'Open',
|
|
22
|
+
'Source',
|
|
23
|
+
'Word',
|
|
17
24
|
'Finder',
|
|
18
25
|
'Cheating',
|
|
19
26
|
'Literaki',
|
|
@@ -22,6 +29,7 @@ const KEYWORDS = [
|
|
|
22
29
|
'Français',
|
|
23
30
|
'Deutsch',
|
|
24
31
|
'Polski',
|
|
32
|
+
'فارسی',
|
|
25
33
|
'Español',
|
|
26
34
|
'SOWPODS',
|
|
27
35
|
'TWL06',
|
|
@@ -55,11 +63,7 @@ const App: FunctionComponent<AppProps> = ({ Component, pageProps }) => (
|
|
|
55
63
|
</Head>
|
|
56
64
|
|
|
57
65
|
<Provider store={store}>
|
|
58
|
-
<
|
|
59
|
-
Scrabble Solver 2 is a free and open-source analysis tool for Scrabble and Literaki. Quickly find top scoring
|
|
60
|
-
words using given letters and board state. Available in English, French, German, Polish & Spanish. Source code
|
|
61
|
-
is available on GitHub - contributions are welcome!
|
|
62
|
-
</p>
|
|
66
|
+
<SeoMessage />
|
|
63
67
|
<Component {...pageProps} />
|
|
64
68
|
</Provider>
|
|
65
69
|
</>
|