scrabble-solver 2.8.7 → 2.8.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/.eslintrc.prettier-only.js +1 -1
- package/.prettierignore +3 -0
- package/.prettierrc +3 -3
- package/README.md +8 -8
- package/babel.config.js +1 -1
- package/lerna.json +1 -1
- package/package.json +6 -6
- package/packages/configs/package.json +3 -3
- 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 +10 -10
- 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/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/413.js +257 -55
- package/packages/scrabble-solver/.next/server/chunks/44.js +802 -0
- package/packages/scrabble-solver/.next/server/chunks/515.js +452 -104
- package/packages/scrabble-solver/.next/server/chunks/911.js +53 -23
- 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.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/_document.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/solve.js +193 -927
- package/packages/scrabble-solver/.next/server/pages/api/solve.js.nft.json +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/verify.js +217 -0
- package/packages/scrabble-solver/.next/server/pages/api/verify.js.nft.json +1 -0
- package/packages/scrabble-solver/.next/server/pages/index.html +3 -3
- package/packages/scrabble-solver/.next/server/pages/index.js +7 -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-manifest.json +1 -0
- package/packages/scrabble-solver/.next/static/chunks/317-a33dd38e9b9a17ed.js +1 -0
- package/packages/scrabble-solver/.next/static/chunks/pages/{404-30c06e61d256c5b2.js → 404-90c624da3c83fd17.js} +1 -1
- package/packages/scrabble-solver/.next/static/chunks/pages/_app-f8f360878e1c2aff.js +1 -0
- package/packages/scrabble-solver/.next/static/chunks/pages/index-ecea697d3e5d8a6f.js +1 -0
- package/packages/scrabble-solver/.next/static/css/64dc2ce1811912f1.css +1 -0
- package/packages/scrabble-solver/.next/static/css/{cdbc9e0afcff5473.css → ad2a08918868cad8.css} +1 -1
- package/packages/scrabble-solver/.next/static/yCxjzzYpw5JjJE53PO_s6/_buildManifest.js +1 -0
- package/packages/scrabble-solver/.next/static/{z_0_lqfmiI_ISokr6NNRq → yCxjzzYpw5JjJE53PO_s6}/_ssgManifest.js +0 -0
- package/packages/scrabble-solver/.next/trace +42 -40
- package/packages/scrabble-solver/package-lock.json +2 -2
- package/packages/scrabble-solver/package.json +8 -8
- package/packages/scrabble-solver/src/components/Badge/Badge.module.scss +13 -0
- package/packages/scrabble-solver/src/components/Badge/Badge.tsx +15 -0
- package/packages/scrabble-solver/src/components/Badge/index.ts +1 -0
- package/packages/scrabble-solver/src/components/Board/components/Cell/Cell.module.scss +34 -9
- package/packages/scrabble-solver/src/components/Board/components/Cell/Cell.tsx +23 -4
- package/packages/scrabble-solver/src/components/Board/components/Cell/CellPure.tsx +29 -1
- package/packages/scrabble-solver/src/components/Board/hooks/useGrid.ts +1 -0
- package/packages/scrabble-solver/src/components/NavButtons/NavButtons.tsx +33 -14
- package/packages/scrabble-solver/src/components/RemainingTiles/RemainingTiles.module.scss +8 -7
- package/packages/scrabble-solver/src/components/RemainingTiles/RemainingTiles.tsx +13 -4
- package/packages/scrabble-solver/src/components/Sidebar/Sidebar.tsx +2 -2
- package/packages/scrabble-solver/src/components/Sidebar/components/Section/Section.module.scss +0 -1
- package/packages/scrabble-solver/src/components/Sidebar/components/Section/Section.tsx +1 -1
- package/packages/scrabble-solver/src/components/SquareButton/SquareButton.module.scss +5 -0
- package/packages/scrabble-solver/src/components/Words/Words.module.scss +35 -0
- package/packages/scrabble-solver/src/components/Words/Words.tsx +57 -0
- package/packages/scrabble-solver/src/components/Words/index.ts +1 -0
- package/packages/scrabble-solver/src/components/index.ts +2 -0
- package/packages/scrabble-solver/src/i18n/de.json +5 -1
- package/packages/scrabble-solver/src/i18n/en.json +5 -1
- package/packages/scrabble-solver/src/i18n/es.json +5 -1
- package/packages/scrabble-solver/src/i18n/fr.json +5 -1
- package/packages/scrabble-solver/src/i18n/pl.json +5 -1
- package/packages/scrabble-solver/src/icons/BookHalf.svg +4 -0
- package/packages/scrabble-solver/src/icons/Check.svg +4 -0
- package/packages/scrabble-solver/src/icons/Cross.svg +2 -2
- package/packages/scrabble-solver/src/icons/CrossFill.svg +4 -0
- package/packages/scrabble-solver/src/icons/Flag.svg +4 -0
- package/packages/scrabble-solver/src/icons/Star.svg +4 -0
- package/packages/scrabble-solver/src/icons/index.ts +5 -0
- package/packages/scrabble-solver/src/pages/api/solve.ts +2 -3
- package/packages/scrabble-solver/src/pages/api/verify.ts +71 -0
- package/packages/scrabble-solver/src/pages/index.tsx +5 -0
- package/packages/scrabble-solver/src/sdk/index.ts +1 -0
- package/packages/scrabble-solver/src/sdk/verify.ts +24 -0
- package/packages/scrabble-solver/src/state/rootReducer.ts +12 -1
- package/packages/scrabble-solver/src/state/sagas.ts +54 -7
- package/packages/scrabble-solver/src/state/selectors.ts +49 -11
- package/packages/scrabble-solver/src/state/slices/cellFilterInitialState.ts +7 -0
- package/packages/scrabble-solver/src/state/slices/cellFilterSlice.ts +24 -0
- package/packages/scrabble-solver/src/state/slices/index.ts +4 -0
- package/packages/scrabble-solver/src/state/slices/verifyInitialState.ts +12 -0
- package/packages/scrabble-solver/src/state/slices/verifySlice.ts +31 -0
- package/packages/scrabble-solver/src/styles/variables.scss +2 -1
- package/packages/scrabble-solver/src/types/index.ts +5 -1
- package/packages/solver/build/fillPattern.d.ts +5 -0
- package/packages/solver/build/fillPattern.js +52 -0
- package/packages/solver/build/generateEndIndices.d.ts +3 -0
- package/packages/solver/build/generateEndIndices.js +9 -0
- package/packages/solver/build/generateHorizontalPatterns.d.ts +3 -0
- package/packages/solver/build/generateHorizontalPatterns.js +18 -0
- package/packages/solver/build/generatePattern.d.ts +8 -0
- package/packages/solver/build/generatePattern.js +22 -0
- package/packages/solver/build/generatePatterns.d.ts +3 -0
- package/packages/solver/build/generatePatterns.js +13 -0
- package/packages/solver/build/generateStartIndices.d.ts +3 -0
- package/packages/solver/build/generateStartIndices.js +9 -0
- package/packages/solver/build/generateVectors.d.ts +6 -0
- package/packages/solver/build/generateVectors.js +8 -0
- package/packages/solver/build/generateVerticalPatterns.d.ts +3 -0
- package/packages/solver/build/generateVerticalPatterns.js +18 -0
- package/packages/solver/build/getCellsScore.d.ts +3 -0
- package/packages/solver/build/getCellsScore.js +16 -0
- package/packages/solver/build/getPatternHash.d.ts +3 -0
- package/packages/solver/build/getPatternHash.js +13 -0
- package/packages/solver/build/getPatternScore.d.ts +3 -0
- package/packages/solver/build/getPatternScore.js +15 -0
- package/packages/solver/build/getUniquePatterns.js +5 -11
- package/packages/solver/build/index.d.ts +1 -1
- package/packages/solver/build/index.js +3 -3
- package/packages/solver/build/solve.d.ts +4 -0
- package/packages/solver/build/solve.js +23 -0
- package/packages/solver/package-lock.json +2 -2
- package/packages/solver/package.json +5 -5
- package/packages/solver/src/fillPattern.test.ts +107 -0
- package/packages/solver/src/fillPattern.ts +70 -0
- package/packages/solver/src/generateEndIndices.test.ts +18 -0
- package/packages/solver/src/generateEndIndices.ts +10 -0
- package/packages/solver/src/generateHorizontalPatterns.test.ts +31 -0
- package/packages/solver/src/generateHorizontalPatterns.ts +17 -0
- package/packages/solver/src/generatePattern.ts +35 -0
- package/packages/solver/src/generatePatterns.ts +13 -0
- package/packages/solver/src/generateStartIndices.test.ts +14 -0
- package/packages/solver/src/generateStartIndices.ts +10 -0
- package/packages/solver/src/generateVectors.test.ts +12 -0
- package/packages/solver/src/generateVectors.ts +15 -0
- package/packages/solver/src/generateVerticalPatterns.test.ts +32 -0
- package/packages/solver/src/generateVerticalPatterns.ts +17 -0
- package/packages/solver/src/getCellsScore.ts +22 -0
- package/packages/solver/src/getPatternHash.test.ts +17 -0
- package/packages/solver/src/getPatternHash.ts +14 -0
- package/packages/solver/src/getPatternScore.test.ts +60 -0
- package/packages/solver/src/getPatternScore.ts +15 -0
- package/packages/solver/src/getUniquePatterns.ts +1 -10
- package/packages/solver/src/index.ts +1 -1
- package/packages/solver/src/{Solver.test.ts → solve.test.ts} +14 -13
- package/packages/solver/src/solve.ts +25 -0
- package/packages/types/build/Board.d.ts +1 -0
- package/packages/types/build/Board.js +17 -1
- package/packages/types/build/Config.js +1 -1
- package/packages/types/build/FinalPattern.d.ts +7 -0
- package/packages/types/build/FinalPattern.js +16 -0
- package/packages/types/build/HorizontalPattern.js +2 -5
- package/packages/types/build/Pattern.d.ts +1 -4
- package/packages/types/build/Pattern.js +2 -5
- package/packages/types/build/Result.js +3 -5
- package/packages/types/build/Tile.d.ts +2 -2
- package/packages/types/build/VerticalPattern.js +2 -5
- package/packages/types/build/index.d.ts +1 -0
- package/packages/types/build/index.js +3 -1
- package/packages/types/package.json +2 -2
- package/packages/types/src/Board.ts +23 -1
- package/packages/types/src/Config.ts +1 -1
- package/packages/types/src/FinalPattern.ts +16 -0
- package/packages/types/src/HorizontalPattern.ts +5 -5
- package/packages/types/src/Pattern.ts +5 -5
- package/packages/types/src/Result.ts +3 -5
- package/packages/types/src/Tile.ts +2 -2
- package/packages/types/src/VerticalPattern.ts +5 -5
- package/packages/types/src/index.ts +1 -0
- package/packages/word-definitions/package-lock.json +8 -8
- 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/static/chunks/56-cf37c430261bbea5.js +0 -1
- package/packages/scrabble-solver/.next/static/chunks/pages/_app-0b12a65bea70a0df.js +0 -1
- package/packages/scrabble-solver/.next/static/chunks/pages/index-fcb69802550afb81.js +0 -1
- package/packages/scrabble-solver/.next/static/css/1f39b55d50f5b30b.css +0 -1
- package/packages/scrabble-solver/.next/static/z_0_lqfmiI_ISokr6NNRq/_buildManifest.js +0 -1
- package/packages/solver/build/PatternsFiller.d.ts +0 -12
- package/packages/solver/build/PatternsFiller.js +0 -70
- package/packages/solver/build/PatternsGenerator.d.ts +0 -32
- package/packages/solver/build/PatternsGenerator.js +0 -66
- package/packages/solver/build/ScoresCalculator.d.ts +0 -17
- package/packages/solver/build/ScoresCalculator.js +0 -37
- package/packages/solver/build/Solver.d.ts +0 -10
- package/packages/solver/build/Solver.js +0 -30
- package/packages/solver/src/PatternsFiller.test.ts +0 -92
- package/packages/solver/src/PatternsFiller.ts +0 -91
- package/packages/solver/src/PatternsGenerator.test.ts +0 -89
- package/packages/solver/src/PatternsGenerator.ts +0 -103
- package/packages/solver/src/ScoresCalculator.test.ts +0 -70
- package/packages/solver/src/ScoresCalculator.ts +0 -52
- package/packages/solver/src/Solver.ts +0 -39
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scrabble-solver/scrabble-solver",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.9",
|
|
4
4
|
"lockfileVersion": 2,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@scrabble-solver/scrabble-solver",
|
|
9
|
-
"version": "2.8.
|
|
9
|
+
"version": "2.8.9",
|
|
10
10
|
"license": "CC BY-NC-ND 4.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@popperjs/core": "^2.11.6",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scrabble-solver/scrabble-solver",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.9",
|
|
4
4
|
"description": "Scrabble Solver 2 - App",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=16"
|
|
@@ -30,13 +30,13 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@popperjs/core": "^2.11.6",
|
|
32
32
|
"@reduxjs/toolkit": "^1.8.5",
|
|
33
|
-
"@scrabble-solver/configs": "^2.8.
|
|
34
|
-
"@scrabble-solver/constants": "^2.8.
|
|
35
|
-
"@scrabble-solver/dictionaries": "^2.8.
|
|
36
|
-
"@scrabble-solver/logger": "^2.8.
|
|
37
|
-
"@scrabble-solver/solver": "^2.8.
|
|
38
|
-
"@scrabble-solver/types": "^2.8.
|
|
39
|
-
"@scrabble-solver/word-definitions": "^2.8.
|
|
33
|
+
"@scrabble-solver/configs": "^2.8.9",
|
|
34
|
+
"@scrabble-solver/constants": "^2.8.9",
|
|
35
|
+
"@scrabble-solver/dictionaries": "^2.8.9",
|
|
36
|
+
"@scrabble-solver/logger": "^2.8.9",
|
|
37
|
+
"@scrabble-solver/solver": "^2.8.9",
|
|
38
|
+
"@scrabble-solver/types": "^2.8.9",
|
|
39
|
+
"@scrabble-solver/word-definitions": "^2.8.9",
|
|
40
40
|
"classnames": "^2.3.2",
|
|
41
41
|
"next": "^12.3.1",
|
|
42
42
|
"normalize.css": "^8.0.1",
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
.badge {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
justify-content: center;
|
|
5
|
+
padding: var(--spacing--xs) var(--spacing--s);
|
|
6
|
+
border-radius: var(--border--radius);
|
|
7
|
+
background-color: var(--color--violet--light);
|
|
8
|
+
box-shadow: va(--box-shadow);
|
|
9
|
+
line-height: var(--line-height);
|
|
10
|
+
font-size: var(--font--size--s);
|
|
11
|
+
font-weight: bold;
|
|
12
|
+
color: white;
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import { FunctionComponent, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
import styles from './Badge.module.scss';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const Badge: FunctionComponent<Props> = ({ children, className }) => (
|
|
12
|
+
<div className={classNames(styles.badge, className)}>{children}</div>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export default Badge;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './Badge';
|
|
@@ -13,7 +13,6 @@ $icon-size: 16px;
|
|
|
13
13
|
transition: var(--transition);
|
|
14
14
|
background-clip: padding-box;
|
|
15
15
|
|
|
16
|
-
&.bonusStart,
|
|
17
16
|
&.bonusWord2,
|
|
18
17
|
&.bonusWord3 {
|
|
19
18
|
position: relative;
|
|
@@ -33,12 +32,7 @@ $icon-size: 16px;
|
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
&.bonusStart {
|
|
36
|
-
background-color: var(--color--
|
|
37
|
-
|
|
38
|
-
&:before {
|
|
39
|
-
content: '★';
|
|
40
|
-
color: var(--color--foreground--secondary);
|
|
41
|
-
}
|
|
35
|
+
background-color: var(--color--violet--light);
|
|
42
36
|
}
|
|
43
37
|
|
|
44
38
|
&.bonusCharacter1 {
|
|
@@ -168,6 +162,7 @@ $icon-size: 16px;
|
|
|
168
162
|
}
|
|
169
163
|
|
|
170
164
|
&,
|
|
165
|
+
.filterCell,
|
|
171
166
|
.toggleDirection {
|
|
172
167
|
width: $icon-size;
|
|
173
168
|
height: $icon-size;
|
|
@@ -180,8 +175,6 @@ $icon-size: 16px;
|
|
|
180
175
|
}
|
|
181
176
|
|
|
182
177
|
.toggleDirection {
|
|
183
|
-
transition: var(--transition);
|
|
184
|
-
|
|
185
178
|
&.right {
|
|
186
179
|
transform: rotate(-90deg);
|
|
187
180
|
}
|
|
@@ -194,3 +187,35 @@ $icon-size: 16px;
|
|
|
194
187
|
font-weight: bold;
|
|
195
188
|
}
|
|
196
189
|
}
|
|
190
|
+
|
|
191
|
+
.filterCell {
|
|
192
|
+
color: var(--color--inactive);
|
|
193
|
+
|
|
194
|
+
&.filtered {
|
|
195
|
+
color: var(--color--foreground--secondary);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.iconContainer {
|
|
200
|
+
position: absolute;
|
|
201
|
+
top: 0;
|
|
202
|
+
right: 0;
|
|
203
|
+
bottom: 0;
|
|
204
|
+
left: 0;
|
|
205
|
+
display: flex;
|
|
206
|
+
align-items: center;
|
|
207
|
+
justify-content: center;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.flagContainer {
|
|
211
|
+
background-color: var(--color--primary);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.flag,
|
|
215
|
+
.star {
|
|
216
|
+
$size: 24px;
|
|
217
|
+
|
|
218
|
+
width: $size;
|
|
219
|
+
height: $size;
|
|
220
|
+
color: white;
|
|
221
|
+
}
|
|
@@ -4,7 +4,15 @@ import { FunctionComponent, RefObject, useCallback, useMemo } from 'react';
|
|
|
4
4
|
import { useDispatch } from 'react-redux';
|
|
5
5
|
|
|
6
6
|
import { getTileSizes } from 'lib';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
boardSlice,
|
|
9
|
+
cellFilterSlice,
|
|
10
|
+
selectCellBonus,
|
|
11
|
+
selectCellIsFiltered,
|
|
12
|
+
selectTilePoints,
|
|
13
|
+
useTranslate,
|
|
14
|
+
useTypedSelector,
|
|
15
|
+
} from 'state';
|
|
8
16
|
|
|
9
17
|
import CellPure from './CellPure';
|
|
10
18
|
|
|
@@ -34,10 +42,19 @@ const Cell: FunctionComponent<Props> = ({
|
|
|
34
42
|
const translate = useTranslate();
|
|
35
43
|
const bonus = useTypedSelector((state) => selectCellBonus(state, cell));
|
|
36
44
|
const points = useTypedSelector((state) => selectTilePoints(state, cell.tile));
|
|
45
|
+
const isFiltered = useTypedSelector((state) => selectCellIsFiltered(state, cell));
|
|
37
46
|
const { tileFontSize } = getTileSizes(size);
|
|
38
47
|
const isEmpty = tile.character === EMPTY_CELL;
|
|
39
48
|
const style = useMemo(() => ({ fontSize: tileFontSize }), [tileFontSize]);
|
|
40
49
|
|
|
50
|
+
const handleDirectionToggleClick = useCallback(() => {
|
|
51
|
+
if (inputRef.current) {
|
|
52
|
+
inputRef.current.focus();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
onDirectionToggle();
|
|
56
|
+
}, [onDirectionToggle]);
|
|
57
|
+
|
|
41
58
|
const handleFocus = useCallback(() => onFocus(x, y), [x, y, onFocus]);
|
|
42
59
|
|
|
43
60
|
const handleToggleBlankClick = useCallback(() => {
|
|
@@ -48,13 +65,13 @@ const Cell: FunctionComponent<Props> = ({
|
|
|
48
65
|
dispatch(boardSlice.actions.toggleCellIsBlank({ x, y }));
|
|
49
66
|
}, [dispatch, x, y]);
|
|
50
67
|
|
|
51
|
-
const
|
|
68
|
+
const handleToggleFilterCellClick = useCallback(() => {
|
|
52
69
|
if (inputRef.current) {
|
|
53
70
|
inputRef.current.focus();
|
|
54
71
|
}
|
|
55
72
|
|
|
56
|
-
|
|
57
|
-
}, [
|
|
73
|
+
dispatch(cellFilterSlice.actions.toggle({ x, y }));
|
|
74
|
+
}, [dispatch, x, y]);
|
|
58
75
|
|
|
59
76
|
return (
|
|
60
77
|
<CellPure
|
|
@@ -65,6 +82,7 @@ const Cell: FunctionComponent<Props> = ({
|
|
|
65
82
|
inputRef={inputRef}
|
|
66
83
|
isCenter={isCenter}
|
|
67
84
|
isEmpty={isEmpty}
|
|
85
|
+
isFiltered={isFiltered}
|
|
68
86
|
points={points}
|
|
69
87
|
size={size}
|
|
70
88
|
style={style}
|
|
@@ -73,6 +91,7 @@ const Cell: FunctionComponent<Props> = ({
|
|
|
73
91
|
onDirectionToggleClick={handleDirectionToggleClick}
|
|
74
92
|
onFocus={handleFocus}
|
|
75
93
|
onToggleBlankClick={handleToggleBlankClick}
|
|
94
|
+
onToggleFilterCellClick={handleToggleFilterCellClick}
|
|
76
95
|
/>
|
|
77
96
|
);
|
|
78
97
|
};
|
|
@@ -2,7 +2,7 @@ import { Bonus, Cell, Tile as TileModel } from '@scrabble-solver/types';
|
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import { CSSProperties, FocusEventHandler, FunctionComponent, memo, MouseEventHandler, RefObject } from 'react';
|
|
4
4
|
|
|
5
|
-
import { ArrowDown } from 'icons';
|
|
5
|
+
import { ArrowDown, Flag, Star } from 'icons';
|
|
6
6
|
import { Translate } from 'types';
|
|
7
7
|
|
|
8
8
|
import Tile from '../../../Tile';
|
|
@@ -19,6 +19,7 @@ interface Props {
|
|
|
19
19
|
inputRef: RefObject<HTMLInputElement>;
|
|
20
20
|
isCenter: boolean;
|
|
21
21
|
isEmpty: boolean;
|
|
22
|
+
isFiltered: boolean;
|
|
22
23
|
points?: number;
|
|
23
24
|
size: number;
|
|
24
25
|
style?: CSSProperties;
|
|
@@ -27,6 +28,7 @@ interface Props {
|
|
|
27
28
|
onDirectionToggleClick: MouseEventHandler<HTMLButtonElement>;
|
|
28
29
|
onFocus: FocusEventHandler<HTMLInputElement>;
|
|
29
30
|
onToggleBlankClick: MouseEventHandler<HTMLButtonElement>;
|
|
31
|
+
onToggleFilterCellClick: MouseEventHandler<HTMLButtonElement>;
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
const CellPure: FunctionComponent<Props> = ({
|
|
@@ -37,6 +39,7 @@ const CellPure: FunctionComponent<Props> = ({
|
|
|
37
39
|
inputRef,
|
|
38
40
|
isCenter,
|
|
39
41
|
isEmpty,
|
|
42
|
+
isFiltered,
|
|
40
43
|
points,
|
|
41
44
|
size,
|
|
42
45
|
style,
|
|
@@ -45,6 +48,7 @@ const CellPure: FunctionComponent<Props> = ({
|
|
|
45
48
|
onDirectionToggleClick,
|
|
46
49
|
onFocus,
|
|
47
50
|
onToggleBlankClick,
|
|
51
|
+
onToggleFilterCellClick,
|
|
48
52
|
}) => (
|
|
49
53
|
<div
|
|
50
54
|
className={classNames(styles.cell, getBonusClassname(cell, bonus, isCenter), className, {
|
|
@@ -52,6 +56,18 @@ const CellPure: FunctionComponent<Props> = ({
|
|
|
52
56
|
})}
|
|
53
57
|
style={style}
|
|
54
58
|
>
|
|
59
|
+
{isCenter && (
|
|
60
|
+
<div className={classNames(styles.iconContainer)}>
|
|
61
|
+
<Star className={styles.star} />
|
|
62
|
+
</div>
|
|
63
|
+
)}
|
|
64
|
+
|
|
65
|
+
{isFiltered && (
|
|
66
|
+
<div className={classNames(styles.iconContainer, styles.flagContainer)}>
|
|
67
|
+
<Flag className={styles.flag} />
|
|
68
|
+
</div>
|
|
69
|
+
)}
|
|
70
|
+
|
|
55
71
|
<Tile
|
|
56
72
|
className={styles.tile}
|
|
57
73
|
character={isEmpty ? undefined : tile.character}
|
|
@@ -74,6 +90,18 @@ const CellPure: FunctionComponent<Props> = ({
|
|
|
74
90
|
/>
|
|
75
91
|
</Button>
|
|
76
92
|
|
|
93
|
+
{isEmpty && (
|
|
94
|
+
<Button
|
|
95
|
+
className={classNames(styles.filterCell, {
|
|
96
|
+
[styles.filtered]: isFiltered,
|
|
97
|
+
})}
|
|
98
|
+
tooltip={translate('cell.filter-cell')}
|
|
99
|
+
onClick={onToggleFilterCellClick}
|
|
100
|
+
>
|
|
101
|
+
<Flag />
|
|
102
|
+
</Button>
|
|
103
|
+
)}
|
|
104
|
+
|
|
77
105
|
{!isEmpty && (
|
|
78
106
|
<Button
|
|
79
107
|
className={classNames(styles.blank, {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import classNames from 'classnames';
|
|
2
2
|
import { FunctionComponent } from 'react';
|
|
3
3
|
|
|
4
|
-
import { Cog, Eraser, Github, Keyboard, Sack } from 'icons';
|
|
4
|
+
import { BookHalf, Cog, Eraser, Github, Keyboard, Sack } from 'icons';
|
|
5
5
|
import { GITHUB_PROJECT_URL } from 'parameters';
|
|
6
|
-
import { selectHasOverusedTiles, useTranslate, useTypedSelector } from 'state';
|
|
6
|
+
import { selectHasInvalidWords, selectHasOverusedTiles, useTranslate, useTypedSelector } from 'state';
|
|
7
7
|
|
|
8
8
|
import SquareButton from '../SquareButton';
|
|
9
9
|
|
|
@@ -14,27 +14,26 @@ interface Props {
|
|
|
14
14
|
onShowKeyMap: () => void;
|
|
15
15
|
onShowRemainingTiles: () => void;
|
|
16
16
|
onShowSettings: () => void;
|
|
17
|
+
onShowWords: () => void;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
const NavButtons: FunctionComponent<Props> = ({
|
|
20
|
+
const NavButtons: FunctionComponent<Props> = ({
|
|
21
|
+
onClear,
|
|
22
|
+
onShowKeyMap,
|
|
23
|
+
onShowRemainingTiles,
|
|
24
|
+
onShowSettings,
|
|
25
|
+
onShowWords,
|
|
26
|
+
}) => {
|
|
20
27
|
const translate = useTranslate();
|
|
21
28
|
const hasOverusedTiles = useTypedSelector(selectHasOverusedTiles);
|
|
29
|
+
const hasInvalidWords = useTypedSelector(selectHasInvalidWords);
|
|
22
30
|
|
|
23
31
|
return (
|
|
24
32
|
<div className={styles.navButtons}>
|
|
25
|
-
<SquareButton.
|
|
26
|
-
className={styles.button}
|
|
27
|
-
href={GITHUB_PROJECT_URL}
|
|
28
|
-
Icon={Github}
|
|
29
|
-
rel="noopener noreferrer"
|
|
30
|
-
target="_blank"
|
|
31
|
-
tooltip={translate('github')}
|
|
32
|
-
/>
|
|
33
|
+
<SquareButton className={styles.button} Icon={Eraser} tooltip={translate('common.clear')} onClick={onClear} />
|
|
33
34
|
|
|
34
35
|
<div className={styles.separator} />
|
|
35
36
|
|
|
36
|
-
<SquareButton className={styles.button} Icon={Keyboard} tooltip={translate('keyMap')} onClick={onShowKeyMap} />
|
|
37
|
-
|
|
38
37
|
<SquareButton
|
|
39
38
|
className={classNames(styles.button, {
|
|
40
39
|
[styles.error]: hasOverusedTiles,
|
|
@@ -44,9 +43,29 @@ const NavButtons: FunctionComponent<Props> = ({ onClear, onShowKeyMap, onShowRem
|
|
|
44
43
|
onClick={onShowRemainingTiles}
|
|
45
44
|
/>
|
|
46
45
|
|
|
46
|
+
<SquareButton
|
|
47
|
+
className={classNames(styles.button, {
|
|
48
|
+
[styles.error]: hasInvalidWords,
|
|
49
|
+
})}
|
|
50
|
+
Icon={BookHalf}
|
|
51
|
+
tooltip={translate('words')}
|
|
52
|
+
onClick={onShowWords}
|
|
53
|
+
/>
|
|
54
|
+
|
|
47
55
|
<div className={styles.separator} />
|
|
48
56
|
|
|
49
|
-
<SquareButton
|
|
57
|
+
<SquareButton.Link
|
|
58
|
+
className={styles.button}
|
|
59
|
+
href={GITHUB_PROJECT_URL}
|
|
60
|
+
Icon={Github}
|
|
61
|
+
rel="noopener noreferrer"
|
|
62
|
+
target="_blank"
|
|
63
|
+
tooltip={translate('github')}
|
|
64
|
+
/>
|
|
65
|
+
|
|
66
|
+
<div className={styles.separator} />
|
|
67
|
+
|
|
68
|
+
<SquareButton className={styles.button} Icon={Keyboard} tooltip={translate('keyMap')} onClick={onShowKeyMap} />
|
|
50
69
|
|
|
51
70
|
<SquareButton className={styles.button} Icon={Cog} tooltip={translate('settings')} onClick={onShowSettings} />
|
|
52
71
|
</div>
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
.group {
|
|
2
|
-
margin-bottom: var(--spacing--l);
|
|
3
|
-
}
|
|
4
|
-
|
|
5
1
|
.title {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
display: flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
justify-content: space-between;
|
|
5
|
+
flex-wrap: wrap;
|
|
9
6
|
}
|
|
10
7
|
|
|
11
8
|
.content {
|
|
@@ -13,3 +10,7 @@
|
|
|
13
10
|
grid-template-columns: repeat(5, 1fr);
|
|
14
11
|
gap: var(--spacing--m);
|
|
15
12
|
}
|
|
13
|
+
|
|
14
|
+
.badge {
|
|
15
|
+
margin-left: var(--spacing--m);
|
|
16
|
+
}
|
|
@@ -2,6 +2,7 @@ import { FunctionComponent } from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { selectRemainingTilesGroups, useTranslate, useTypedSelector } from 'state';
|
|
4
4
|
|
|
5
|
+
import Badge from '../Badge';
|
|
5
6
|
import Sidebar from '../Sidebar';
|
|
6
7
|
|
|
7
8
|
import Character from './Character';
|
|
@@ -20,15 +21,23 @@ const RemainingTiles: FunctionComponent<Props> = ({ className, isOpen, onClose }
|
|
|
20
21
|
return (
|
|
21
22
|
<Sidebar className={className} isOpen={isOpen} title={translate('remaining-tiles')} onClose={onClose}>
|
|
22
23
|
{groups.map(({ remainingCount, tiles, translationKey, totalCount }) => (
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
<Sidebar.Section
|
|
25
|
+
key={translationKey}
|
|
26
|
+
title={
|
|
27
|
+
<span className={styles.title}>
|
|
28
|
+
<span>{translate(translationKey)}</span>
|
|
29
|
+
<Badge className={styles.badge}>
|
|
30
|
+
{remainingCount} / {totalCount}
|
|
31
|
+
</Badge>
|
|
32
|
+
</span>
|
|
33
|
+
}
|
|
34
|
+
>
|
|
26
35
|
<div className={styles.content}>
|
|
27
36
|
{tiles.map((tile) => {
|
|
28
37
|
return <Character key={tile.character} tile={tile} />;
|
|
29
38
|
})}
|
|
30
39
|
</div>
|
|
31
|
-
</
|
|
40
|
+
</Sidebar.Section>
|
|
32
41
|
))}
|
|
33
42
|
</Sidebar>
|
|
34
43
|
);
|
|
@@ -2,7 +2,7 @@ import classNames from 'classnames';
|
|
|
2
2
|
import { FunctionComponent, ReactNode } from 'react';
|
|
3
3
|
import Modal from 'react-modal';
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { CrossFill } from 'icons';
|
|
6
6
|
import { TRANSITION_DURATION_LONG } from 'parameters';
|
|
7
7
|
import { useTranslate } from 'state';
|
|
8
8
|
|
|
@@ -41,7 +41,7 @@ const Sidebar: FunctionComponent<Props> = ({ children, className, isOpen, title,
|
|
|
41
41
|
|
|
42
42
|
<SquareButton
|
|
43
43
|
className={styles.closeButton}
|
|
44
|
-
Icon={
|
|
44
|
+
Icon={CrossFill}
|
|
45
45
|
tooltip={translate('common.close')}
|
|
46
46
|
onClick={onClose}
|
|
47
47
|
/>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
.title {
|
|
2
|
+
display: flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
justify-content: space-between;
|
|
5
|
+
flex-wrap: wrap;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.badge {
|
|
9
|
+
margin-left: var(--spacing--m);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.word {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: center;
|
|
15
|
+
|
|
16
|
+
& + & {
|
|
17
|
+
margin-top: var(--spacing--s);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.invalid {
|
|
22
|
+
color: var(--color--error);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.valid {
|
|
26
|
+
color: var(--color--success);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.icon {
|
|
30
|
+
$size: 24px;
|
|
31
|
+
|
|
32
|
+
width: $size;
|
|
33
|
+
height: $size;
|
|
34
|
+
margin-right: var(--spacing--s);
|
|
35
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import { FunctionComponent } from 'react';
|
|
3
|
+
|
|
4
|
+
import { Check, Cross } from 'icons';
|
|
5
|
+
import { selectVerify, useTranslate, useTypedSelector } from 'state';
|
|
6
|
+
|
|
7
|
+
import Badge from '../Badge';
|
|
8
|
+
import Sidebar from '../Sidebar';
|
|
9
|
+
|
|
10
|
+
import styles from './Words.module.scss';
|
|
11
|
+
|
|
12
|
+
interface Props {
|
|
13
|
+
className?: string;
|
|
14
|
+
isOpen: boolean;
|
|
15
|
+
onClose: () => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const Words: FunctionComponent<Props> = ({ className, isOpen, onClose }) => {
|
|
19
|
+
const translate = useTranslate();
|
|
20
|
+
const { invalidWords, validWords } = useTypedSelector(selectVerify);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Sidebar className={className} isOpen={isOpen} title={translate('words')} onClose={onClose}>
|
|
24
|
+
<Sidebar.Section
|
|
25
|
+
title={
|
|
26
|
+
<span className={styles.title}>
|
|
27
|
+
<span>{translate('words.invalid')}</span>
|
|
28
|
+
<Badge className={styles.badge}>{invalidWords.length}</Badge>
|
|
29
|
+
</span>
|
|
30
|
+
}
|
|
31
|
+
>
|
|
32
|
+
{invalidWords.map((word, index) => (
|
|
33
|
+
<div className={styles.word} key={index}>
|
|
34
|
+
<Cross className={classNames(styles.icon, styles.invalid)} /> {word}
|
|
35
|
+
</div>
|
|
36
|
+
))}
|
|
37
|
+
</Sidebar.Section>
|
|
38
|
+
|
|
39
|
+
<Sidebar.Section
|
|
40
|
+
title={
|
|
41
|
+
<span className={styles.title}>
|
|
42
|
+
<span>{translate('words.valid')}</span>
|
|
43
|
+
<Badge className={styles.badge}>{validWords.length}</Badge>
|
|
44
|
+
</span>
|
|
45
|
+
}
|
|
46
|
+
>
|
|
47
|
+
{validWords.map((word, index) => (
|
|
48
|
+
<div className={styles.word} key={index}>
|
|
49
|
+
<Check className={classNames(styles.icon, styles.valid)} /> {word}
|
|
50
|
+
</div>
|
|
51
|
+
))}
|
|
52
|
+
</Sidebar.Section>
|
|
53
|
+
</Sidebar>
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export default Words;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './Words';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { default as Badge } from './Badge';
|
|
1
2
|
export { default as Board } from './Board';
|
|
2
3
|
export { default as Button } from './Button';
|
|
3
4
|
export { default as Checkbox } from './Checkbox';
|
|
@@ -25,3 +26,4 @@ export { default as SvgFontCss } from './SvgFontCss';
|
|
|
25
26
|
export { default as Tile } from './Tile';
|
|
26
27
|
export { useTooltip } from './Tooltip';
|
|
27
28
|
export { default as Well } from './Well';
|
|
29
|
+
export { default as Words } from './Words';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
+
"cell.filter-cell": "Zielort - klicken zum Wechseln",
|
|
2
3
|
"cell.set-blank": "Als Blanko markieren",
|
|
3
4
|
"cell.set-not-blank": "Nicht als Blanko markieren",
|
|
4
5
|
"cell.toggle-direction": "Schreibrichtung - klicken zum Wechseln",
|
|
@@ -48,5 +49,8 @@
|
|
|
48
49
|
"settings.autoGroupTiles.right": "Rechte Seite",
|
|
49
50
|
"settings.autoGroupTiles.null": "Nicht gruppieren",
|
|
50
51
|
"settings.game": "Spiel",
|
|
51
|
-
"settings.language": "Sprache"
|
|
52
|
+
"settings.language": "Sprache",
|
|
53
|
+
"words": "Gebildete Wörter",
|
|
54
|
+
"words.invalid": "Falsch",
|
|
55
|
+
"words.valid": "Korrekt"
|
|
52
56
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
+
"cell.filter-cell": "Target destination - click to toggle",
|
|
2
3
|
"cell.set-blank": "Mark it a blank",
|
|
3
4
|
"cell.set-not-blank": "Mark it not a blank",
|
|
4
5
|
"cell.toggle-direction": "Typing direction - click to toggle",
|
|
@@ -48,5 +49,8 @@
|
|
|
48
49
|
"settings.autoGroupTiles.right": "On the right",
|
|
49
50
|
"settings.autoGroupTiles.null": "Do not group",
|
|
50
51
|
"settings.game": "Game",
|
|
51
|
-
"settings.language": "Language"
|
|
52
|
+
"settings.language": "Language",
|
|
53
|
+
"words": "Created words",
|
|
54
|
+
"words.invalid": "Invalid",
|
|
55
|
+
"words.valid": "Valid"
|
|
52
56
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
+
"cell.filter-cell": "Destino objetivo: haga clic para alternar",
|
|
2
3
|
"cell.set-blank": "Marcar como en blanco",
|
|
3
4
|
"cell.set-not-blank": "Marcar como no en blanco",
|
|
4
5
|
"cell.toggle-direction": "Dirección de escritura: haga clic para alternar",
|
|
@@ -48,5 +49,8 @@
|
|
|
48
49
|
"settings.autoGroupTiles.right": "A la derecha",
|
|
49
50
|
"settings.autoGroupTiles.null": "No agrupar",
|
|
50
51
|
"settings.game": "Juego",
|
|
51
|
-
"settings.language": "Idioma"
|
|
52
|
+
"settings.language": "Idioma",
|
|
53
|
+
"words": "Palabras creadas",
|
|
54
|
+
"words.invalid": "Incorrecto",
|
|
55
|
+
"words.valid": "Correcto"
|
|
52
56
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
+
"cell.filter-cell": "Destination cible - cliquer pour changer",
|
|
2
3
|
"cell.set-blank": "Marquer comme vide",
|
|
3
4
|
"cell.set-not-blank": "Marquer comme non vide",
|
|
4
5
|
"cell.toggle-direction": "Direction d'écriture - cliquer pour changer",
|
|
@@ -48,5 +49,8 @@
|
|
|
48
49
|
"settings.autoGroupTiles.right": "Vers la gauche",
|
|
49
50
|
"settings.autoGroupTiles.null": "Ne pas grouper",
|
|
50
51
|
"settings.game": "Jeu",
|
|
51
|
-
"settings.language": "Langue"
|
|
52
|
+
"settings.language": "Langue",
|
|
53
|
+
"words": "Mots créés",
|
|
54
|
+
"words.invalid": "Incorrect",
|
|
55
|
+
"words.valid": "Corriger"
|
|
52
56
|
}
|