@scrabble-solver/scrabble-solver 2.11.5 → 2.11.7
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/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +11 -11
- package/.next/cache/.tsbuildinfo +1 -1
- package/.next/cache/eslint/.cache_8dgz12 +1 -1
- package/.next/cache/next-server.js.nft.json +1 -1
- package/.next/cache/webpack/client-production/0.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/edge-server-production/0.pack +0 -0
- package/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/0.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +1 -1
- package/.next/routes-manifest.json +1 -1
- package/.next/server/chunks/277.js +778 -746
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/pages/404.html +1 -5
- package/.next/server/pages/404.js.nft.json +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/pages/_app.js +9 -2
- package/.next/server/pages/_app.js.nft.json +1 -1
- package/.next/server/pages/api/solve.js +29 -1
- package/.next/server/pages/index.html +1 -1
- package/.next/server/pages/index.js +10 -4
- package/.next/server/pages/index.js.nft.json +1 -1
- package/.next/server/pages/index.json +1 -1
- package/.next/static/chunks/framework-2c5cac93e8c637b5.js +49 -0
- package/.next/static/chunks/pages/{404-d30fe85d005ce32b.js → 404-ca203fa27afc37d8.js} +1 -1
- package/.next/static/chunks/pages/_app-e89a3c225b87516a.js +28 -0
- package/.next/static/chunks/pages/index-58744f49bf6b891f.js +1 -0
- package/.next/static/css/34adfcf12a7d9bb6.css +1 -0
- package/.next/static/css/edaeaa48321b4cf2.css +2 -0
- package/.next/static/uhB6d-q63uRC6RubwepLq/_buildManifest.js +1 -0
- package/.next/trace +50 -50
- package/package.json +9 -9
- package/src/components/Board/Board.module.scss +2 -59
- package/src/components/Board/Board.tsx +22 -10
- package/src/components/Board/BoardPure.tsx +13 -8
- package/src/components/Board/components/Cell/Cell.module.scss +8 -144
- package/src/components/Board/components/Cell/Cell.tsx +18 -37
- package/src/components/Board/hooks/index.ts +1 -0
- package/src/components/Board/hooks/useBackgroundImage.tsx +170 -0
- package/src/components/Board/lib/getBonusColor.ts +18 -0
- package/src/components/Board/lib/index.ts +1 -0
- package/src/components/Dictionary/Dictionary.module.scss +0 -1
- package/src/components/DictionaryInput/DictionaryInput.tsx +5 -3
- package/src/components/EmptyState/EmptyState.module.scss +0 -1
- package/src/components/Key/Key.module.scss +1 -1
- package/src/components/PlainTiles/PlainTiles.tsx +0 -10
- package/src/components/PlainTiles/Tile.tsx +1 -4
- package/src/components/Results/Cell.tsx +2 -2
- package/src/components/Results/Result.tsx +4 -8
- package/src/components/Results/Results.module.scss +5 -4
- package/src/components/Solver/Solver.tsx +2 -2
- package/src/components/Tooltip/Tooltip.module.scss +2 -0
- package/src/components/index.ts +0 -2
- package/src/hooks/useAppLayout.ts +1 -0
- package/src/hooks/useDirection.ts +2 -2
- package/src/hooks/useLanguage.ts +2 -2
- package/src/i18n/constants.ts +25 -16
- package/src/i18n/de.json +2 -2
- package/src/i18n/en.json +2 -2
- package/src/i18n/es.json +2 -2
- package/src/i18n/fa.json +2 -2
- package/src/i18n/fr.json +2 -2
- package/src/i18n/pl.json +2 -2
- package/src/lib/dataUrlToBlob.ts +20 -0
- package/src/lib/index.ts +1 -0
- package/src/modals/KeyMapModal/components/Mapping/Mapping.module.scss +0 -1
- package/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.module.scss +0 -1
- package/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.module.scss +0 -5
- package/src/pages/_app.tsx +1 -3
- package/src/pages/index.tsx +1 -3
- package/src/parameters/index.ts +33 -2
- package/src/state/index.ts +1 -1
- package/src/state/sagas.ts +3 -4
- package/src/state/store.ts +34 -0
- package/src/styles/global.scss +4 -8
- package/src/styles/mixins.scss +0 -1
- package/src/styles/variables.scss +5 -5
- package/.next/static/UzQCOB6CHhyOupkEq8oZM/_buildManifest.js +0 -1
- package/.next/static/chunks/framework-2c79e2a64abdb08b.js +0 -33
- package/.next/static/chunks/pages/_app-e27464a187a58684.js +0 -28
- package/.next/static/chunks/pages/index-3fd280f406cc00fd.js +0 -1
- package/.next/static/css/4bd04cebe207859c.css +0 -1
- package/.next/static/css/5b3b78170f4c5875.css +0 -2
- package/src/components/Board/components/Cell/CellPure.tsx +0 -93
- package/src/components/Board/components/Cell/lib.ts +0 -59
- package/src/components/SvgFontCss/SvgFontCss.tsx +0 -14
- package/src/components/SvgFontCss/createCss.ts +0 -11
- package/src/components/SvgFontCss/createStyle.ts +0 -9
- package/src/components/SvgFontCss/createSvg.ts +0 -10
- package/src/components/SvgFontCss/index.ts +0 -1
- package/src/components/SvgFontFix/SvgFontFix.module.scss +0 -5
- package/src/components/SvgFontFix/SvgFontFix.tsx +0 -21
- package/src/components/SvgFontFix/index.ts +0 -1
- package/src/state/createAppStore.ts +0 -38
- /package/.next/static/{UzQCOB6CHhyOupkEq8oZM → uhB6d-q63uRC6RubwepLq}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BONUS_WORD } from '@scrabble-solver/constants';
|
|
2
|
+
import { Bonus } from '@scrabble-solver/types';
|
|
3
|
+
|
|
4
|
+
import { COLOR_BONUS_CHARACTER, COLOR_BONUS_CHARACTER_MULTIPLIER, COLOR_BONUS_WORD } from 'parameters';
|
|
5
|
+
|
|
6
|
+
const getBonusColor = (bonus: Bonus): string => {
|
|
7
|
+
if (bonus.type === BONUS_WORD) {
|
|
8
|
+
return COLOR_BONUS_WORD[bonus.multiplier];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (bonus.score) {
|
|
12
|
+
return COLOR_BONUS_CHARACTER[bonus.score];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return COLOR_BONUS_CHARACTER_MULTIPLIER[bonus.multiplier];
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default getBonusColor;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { COMMA_ARABIC, COMMA_LATIN } from '@scrabble-solver/constants';
|
|
2
1
|
import classNames from 'classnames';
|
|
3
2
|
import { ChangeEvent, FormEvent, FunctionComponent } from 'react';
|
|
4
3
|
import { useDispatch } from 'react-redux';
|
|
5
4
|
|
|
6
|
-
import {
|
|
5
|
+
import { LOCALE_FEATURES } from 'i18n';
|
|
6
|
+
import { dictionarySlice, selectDictionary, selectLocale, useTranslate, useTypedSelector } from 'state';
|
|
7
7
|
|
|
8
8
|
import styles from './DictionaryInput.module.scss';
|
|
9
9
|
|
|
@@ -14,7 +14,9 @@ interface Props {
|
|
|
14
14
|
const DictionaryInput: FunctionComponent<Props> = ({ className }) => {
|
|
15
15
|
const dispatch = useDispatch();
|
|
16
16
|
const translate = useTranslate();
|
|
17
|
+
const locale = useTypedSelector(selectLocale);
|
|
17
18
|
const { input } = useTypedSelector(selectDictionary);
|
|
19
|
+
const { comma } = LOCALE_FEATURES[locale];
|
|
18
20
|
|
|
19
21
|
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
|
|
20
22
|
dispatch(dictionarySlice.actions.changeInput(event.target.value));
|
|
@@ -29,7 +31,7 @@ const DictionaryInput: FunctionComponent<Props> = ({ className }) => {
|
|
|
29
31
|
<form className={classNames(styles.dictionaryInput, className)} onSubmit={handleSubmit}>
|
|
30
32
|
<input
|
|
31
33
|
className={styles.input}
|
|
32
|
-
pattern={`.*[^\\s${
|
|
34
|
+
pattern={`.*[^\\s${comma}].*`}
|
|
33
35
|
placeholder={translate('dictionary.input.placeholder')}
|
|
34
36
|
required
|
|
35
37
|
title={translate('dictionary.input.title')}
|
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import classNames from 'classnames';
|
|
2
2
|
import { CSSProperties, FunctionComponent, useMemo } from 'react';
|
|
3
3
|
|
|
4
|
-
import { LOCALE_FEATURES } from 'i18n';
|
|
5
|
-
import { selectLocale, useTypedSelector } from 'state';
|
|
6
|
-
|
|
7
|
-
import SvgFontCss from '../SvgFontCss';
|
|
8
|
-
|
|
9
4
|
import { createPlainTiles, getViewbox } from './lib';
|
|
10
5
|
import styles from './PlainTiles.module.scss';
|
|
11
6
|
import Tile from './Tile';
|
|
@@ -21,8 +16,6 @@ interface Props {
|
|
|
21
16
|
}
|
|
22
17
|
|
|
23
18
|
const PlainTiles: FunctionComponent<Props> = ({ className, color, content, dropShadow, showPoints, style, wave }) => {
|
|
24
|
-
const locale = useTypedSelector(selectLocale);
|
|
25
|
-
const { fontFamily } = LOCALE_FEATURES[locale];
|
|
26
19
|
const tiles = useMemo(() => createPlainTiles({ color, content, showPoints }), [color, content, showPoints]);
|
|
27
20
|
|
|
28
21
|
return (
|
|
@@ -35,14 +28,11 @@ const PlainTiles: FunctionComponent<Props> = ({ className, color, content, dropS
|
|
|
35
28
|
viewBox={getViewbox(content)}
|
|
36
29
|
xmlns="http://www.w3.org/2000/svg"
|
|
37
30
|
>
|
|
38
|
-
<SvgFontCss fontFamily={fontFamily} />
|
|
39
|
-
|
|
40
31
|
{tiles.map((tile, index) => (
|
|
41
32
|
<Tile
|
|
42
33
|
character={tile.character}
|
|
43
34
|
className={styles.tile}
|
|
44
35
|
color={tile.color}
|
|
45
|
-
fontFamily={fontFamily}
|
|
46
36
|
key={index}
|
|
47
37
|
points={tile.points}
|
|
48
38
|
size={tile.size}
|
|
@@ -4,7 +4,6 @@ interface Props {
|
|
|
4
4
|
character: string;
|
|
5
5
|
className?: string;
|
|
6
6
|
color: string;
|
|
7
|
-
fontFamily: string;
|
|
8
7
|
points?: number;
|
|
9
8
|
size: number;
|
|
10
9
|
transform?: string;
|
|
@@ -12,13 +11,12 @@ interface Props {
|
|
|
12
11
|
y: number;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
const Tile: FunctionComponent<Props> = ({ character, className, color,
|
|
14
|
+
const Tile: FunctionComponent<Props> = ({ character, className, color, points, size, transform, x, y }) => (
|
|
16
15
|
<g className={className} transform={transform}>
|
|
17
16
|
<rect fill={color} height={size} rx={size * 0.15} width={size} x={x} y={y} />
|
|
18
17
|
|
|
19
18
|
<text
|
|
20
19
|
dominantBaseline="central"
|
|
21
|
-
fontFamily={fontFamily}
|
|
22
20
|
fontSize={size * 0.6}
|
|
23
21
|
fontWeight="bold"
|
|
24
22
|
textAnchor="middle"
|
|
@@ -31,7 +29,6 @@ const Tile: FunctionComponent<Props> = ({ character, className, color, fontFamil
|
|
|
31
29
|
{typeof points === 'number' && (
|
|
32
30
|
<text
|
|
33
31
|
dominantBaseline="text-after-edge"
|
|
34
|
-
fontFamily={fontFamily}
|
|
35
32
|
fontSize={size * 0.25}
|
|
36
33
|
fontWeight="bold"
|
|
37
34
|
textAnchor="end"
|
|
@@ -22,9 +22,9 @@ const Cell: FunctionComponent<Props> = ({ className, translationKey, tooltip, va
|
|
|
22
22
|
const triggerProps = useTooltip(`${translate(translationKey)}: ${tooltip || formattedValue}`);
|
|
23
23
|
|
|
24
24
|
return (
|
|
25
|
-
<
|
|
25
|
+
<div className={classNames(styles.cell, className)} {...triggerProps}>
|
|
26
26
|
{formattedValue}
|
|
27
|
-
</
|
|
27
|
+
</div>
|
|
28
28
|
);
|
|
29
29
|
};
|
|
30
30
|
|
|
@@ -30,10 +30,10 @@ const Result = ({ data, index, style }: Props): ReactElement => {
|
|
|
30
30
|
const ref = useRef<HTMLButtonElement>(null);
|
|
31
31
|
const columns = useColumns();
|
|
32
32
|
const locale = useTypedSelector(selectLocale);
|
|
33
|
-
const { consonants, vowels } = LOCALE_FEATURES[locale];
|
|
33
|
+
const { consonants, direction, separator, vowels } = LOCALE_FEATURES[locale];
|
|
34
34
|
const result = results[index];
|
|
35
35
|
const isMatching = useTypedSelector((state) => selectIsResultMatching(state, index));
|
|
36
|
-
const
|
|
36
|
+
const words = direction === 'rtl' ? [...result.words].reverse() : result.words;
|
|
37
37
|
const enabledColumns = Object.fromEntries(columns.map((column) => [column.id, true]));
|
|
38
38
|
|
|
39
39
|
const handleClick: MouseEventHandler = (event) => onClick(result, event);
|
|
@@ -60,11 +60,7 @@ const Result = ({ data, index, style }: Props): ReactElement => {
|
|
|
60
60
|
>
|
|
61
61
|
<span className={styles.resultContent}>
|
|
62
62
|
{enabledColumns[ResultColumn.Word] && (
|
|
63
|
-
<Cell
|
|
64
|
-
className={styles.word}
|
|
65
|
-
translationKey="common.word"
|
|
66
|
-
value={`${result.word.toLocaleUpperCase()}${otherWords.length > 0 ? ` (${otherWords})` : ''}`}
|
|
67
|
-
/>
|
|
63
|
+
<Cell className={styles.word} translationKey="common.word" value={result.word} />
|
|
68
64
|
)}
|
|
69
65
|
|
|
70
66
|
{enabledColumns[ResultColumn.TilesCount] && (
|
|
@@ -87,7 +83,7 @@ const Result = ({ data, index, style }: Props): ReactElement => {
|
|
|
87
83
|
<Cell
|
|
88
84
|
className={styles.stat}
|
|
89
85
|
translationKey="common.words"
|
|
90
|
-
tooltip={`${result.wordsCount} (${
|
|
86
|
+
tooltip={`${result.wordsCount.toLocaleString(locale)} (${words.join(separator)})`}
|
|
91
87
|
value={result.wordsCount}
|
|
92
88
|
/>
|
|
93
89
|
)}
|
|
@@ -10,7 +10,6 @@ $row-padding-horizontal: calc(var(--spacing--m) + var(--spacing--s));
|
|
|
10
10
|
background: var(--color--background--element);
|
|
11
11
|
border: var(--border);
|
|
12
12
|
border-radius: var(--border--radius);
|
|
13
|
-
font-family: var(--font--family--title);
|
|
14
13
|
}
|
|
15
14
|
|
|
16
15
|
.emptyState {
|
|
@@ -61,7 +60,6 @@ $row-padding-horizontal: calc(var(--spacing--m) + var(--spacing--s));
|
|
|
61
60
|
cursor: pointer;
|
|
62
61
|
text-transform: uppercase;
|
|
63
62
|
transition: var(--transition);
|
|
64
|
-
padding: var(--spacing--s) 0;
|
|
65
63
|
|
|
66
64
|
&:focus,
|
|
67
65
|
&:hover {
|
|
@@ -136,6 +134,7 @@ $row-padding-horizontal: calc(var(--spacing--m) + var(--spacing--s));
|
|
|
136
134
|
display: flex;
|
|
137
135
|
align-items: center;
|
|
138
136
|
justify-content: space-between;
|
|
137
|
+
height: 100%;
|
|
139
138
|
|
|
140
139
|
.word {
|
|
141
140
|
@include ellipsis;
|
|
@@ -146,8 +145,10 @@ $row-padding-horizontal: calc(var(--spacing--m) + var(--spacing--s));
|
|
|
146
145
|
display: flex;
|
|
147
146
|
align-items: center;
|
|
148
147
|
justify-content: center;
|
|
148
|
+
height: 100%;
|
|
149
149
|
padding: 0 var(--spacing--s);
|
|
150
150
|
gap: var(--spacing--s);
|
|
151
|
+
line-height: var(--results--item--height);
|
|
151
152
|
|
|
152
153
|
.result &:first-child,
|
|
153
154
|
.headerButton:first-child & {
|
|
@@ -181,12 +182,12 @@ $row-padding-horizontal: calc(var(--spacing--m) + var(--spacing--s));
|
|
|
181
182
|
}
|
|
182
183
|
|
|
183
184
|
.word {
|
|
184
|
-
flex: 1 0
|
|
185
|
+
flex: 1 0;
|
|
185
186
|
text-transform: uppercase;
|
|
186
187
|
}
|
|
187
188
|
|
|
188
189
|
.stat {
|
|
189
|
-
$width:
|
|
190
|
+
$width: 55px;
|
|
190
191
|
|
|
191
192
|
flex: 0 0 $width;
|
|
192
193
|
max-width: $width;
|
|
@@ -34,7 +34,7 @@ const Solver: FunctionComponent<Props> = ({ className, onShowResults }) => {
|
|
|
34
34
|
const dispatch = useDispatch();
|
|
35
35
|
const translate = useTranslate();
|
|
36
36
|
const isTouchDevice = useIsTouchDevice();
|
|
37
|
-
const {
|
|
37
|
+
const { maxControlsWidth, showCompactControls, showFloatingSolveButton, tileSize } = useAppLayout();
|
|
38
38
|
const error = useTypedSelector(selectSolveError);
|
|
39
39
|
const isOutdated = useTypedSelector(selectAreResultsOutdated);
|
|
40
40
|
const resultCandidate = useTypedSelector(selectResultCandidate);
|
|
@@ -93,7 +93,7 @@ const Solver: FunctionComponent<Props> = ({ className, onShowResults }) => {
|
|
|
93
93
|
<div className={styles.container}>
|
|
94
94
|
<div className={styles.content}>
|
|
95
95
|
<form className={styles.boardContainer} onSubmit={handleSubmit}>
|
|
96
|
-
<Board
|
|
96
|
+
<Board className={styles.board} />
|
|
97
97
|
<input className={styles.submitInput} tabIndex={-1} type="submit" />
|
|
98
98
|
</form>
|
|
99
99
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
.tooltip {
|
|
2
|
+
max-width: var(--tooltip--max-width);
|
|
2
3
|
padding: var(--spacing--s) var(--spacing--m);
|
|
3
4
|
box-shadow: var(--box-shadow);
|
|
4
5
|
border-radius: var(--border--radius);
|
|
5
6
|
background-color: var(--color--tooltip--background);
|
|
6
7
|
color: var(--color--tooltip--foreground);
|
|
7
8
|
z-index: var(--z-index--tooltip);
|
|
9
|
+
text-align: center;
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
.arrow {
|
package/src/components/index.ts
CHANGED
|
@@ -22,7 +22,5 @@ export { default as ResultsInput } from './ResultsInput';
|
|
|
22
22
|
export { default as SeoMessage } from './SeoMessage';
|
|
23
23
|
export { default as Solver } from './Solver';
|
|
24
24
|
export { default as Spinner } from './Spinner';
|
|
25
|
-
export { default as SvgFontCss } from './SvgFontCss';
|
|
26
|
-
export { default as SvgFontFix } from './SvgFontFix';
|
|
27
25
|
export { default as Tile } from './Tile';
|
|
28
26
|
export { useTooltip } from './Tooltip';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
2
|
|
|
3
3
|
import { noop } from 'lib';
|
|
4
4
|
|
|
5
5
|
const useDirection = (direction: 'ltr' | 'rtl') => {
|
|
6
|
-
|
|
6
|
+
useEffect(() => {
|
|
7
7
|
const html = document.body.parentElement;
|
|
8
8
|
|
|
9
9
|
if (!html) {
|
package/src/hooks/useLanguage.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
2
|
|
|
3
3
|
import { noop } from 'lib';
|
|
4
4
|
|
|
5
5
|
const useLanguage = (language: string) => {
|
|
6
|
-
|
|
6
|
+
useEffect(() => {
|
|
7
7
|
const html = document.body.parentElement;
|
|
8
8
|
|
|
9
9
|
if (!html) {
|
package/src/i18n/constants.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { COMMA_ARABIC, COMMA_LATIN } from '@scrabble-solver/constants';
|
|
1
2
|
import { Locale } from '@scrabble-solver/types';
|
|
2
3
|
import { FunctionComponent, SVGAttributes } from 'react';
|
|
3
4
|
|
|
@@ -6,53 +7,61 @@ import { FlagDe, FlagEs, FlagFa, FlagFr, FlagGb, FlagPl, FlagUs } from 'icons';
|
|
|
6
7
|
import styles from './i18n.module.scss';
|
|
7
8
|
|
|
8
9
|
interface LocaleFeatures {
|
|
9
|
-
|
|
10
|
-
fontFamily: string;
|
|
10
|
+
comma: string;
|
|
11
11
|
consonants: boolean;
|
|
12
|
+
direction: 'ltr' | 'rtl';
|
|
13
|
+
separator: string;
|
|
12
14
|
vowels: boolean;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
export const LOCALE_FEATURES: Record<Locale, LocaleFeatures> = {
|
|
16
18
|
[Locale.DE_DE]: {
|
|
17
|
-
|
|
18
|
-
fontFamily: 'Open Sans',
|
|
19
|
+
comma: COMMA_LATIN,
|
|
19
20
|
consonants: true,
|
|
21
|
+
direction: 'ltr',
|
|
22
|
+
separator: `${COMMA_LATIN} `,
|
|
20
23
|
vowels: true,
|
|
21
24
|
},
|
|
22
25
|
[Locale.EN_GB]: {
|
|
23
|
-
|
|
24
|
-
fontFamily: 'Open Sans',
|
|
26
|
+
comma: COMMA_LATIN,
|
|
25
27
|
consonants: true,
|
|
28
|
+
direction: 'ltr',
|
|
29
|
+
separator: `${COMMA_LATIN} `,
|
|
26
30
|
vowels: true,
|
|
27
31
|
},
|
|
28
32
|
[Locale.EN_US]: {
|
|
29
|
-
|
|
30
|
-
fontFamily: 'Open Sans',
|
|
33
|
+
comma: COMMA_LATIN,
|
|
31
34
|
consonants: true,
|
|
35
|
+
direction: 'ltr',
|
|
36
|
+
separator: `${COMMA_LATIN} `,
|
|
32
37
|
vowels: true,
|
|
33
38
|
},
|
|
34
39
|
[Locale.ES_ES]: {
|
|
35
|
-
|
|
36
|
-
fontFamily: 'Open Sans',
|
|
40
|
+
comma: COMMA_LATIN,
|
|
37
41
|
consonants: true,
|
|
42
|
+
direction: 'ltr',
|
|
43
|
+
separator: `${COMMA_LATIN} `,
|
|
38
44
|
vowels: true,
|
|
39
45
|
},
|
|
40
46
|
[Locale.FA_IR]: {
|
|
41
|
-
|
|
42
|
-
fontFamily: 'Vazirmatn',
|
|
47
|
+
comma: COMMA_ARABIC,
|
|
43
48
|
consonants: false,
|
|
49
|
+
direction: 'rtl',
|
|
50
|
+
separator: `${COMMA_ARABIC} `,
|
|
44
51
|
vowels: false,
|
|
45
52
|
},
|
|
46
53
|
[Locale.FR_FR]: {
|
|
47
|
-
|
|
48
|
-
fontFamily: 'Open Sans',
|
|
54
|
+
comma: COMMA_LATIN,
|
|
49
55
|
consonants: true,
|
|
56
|
+
direction: 'ltr',
|
|
57
|
+
separator: `${COMMA_LATIN} `,
|
|
50
58
|
vowels: true,
|
|
51
59
|
},
|
|
52
60
|
[Locale.PL_PL]: {
|
|
53
|
-
|
|
54
|
-
fontFamily: 'Open Sans',
|
|
61
|
+
comma: COMMA_LATIN,
|
|
55
62
|
consonants: true,
|
|
63
|
+
direction: 'ltr',
|
|
64
|
+
separator: `${COMMA_LATIN} `,
|
|
56
65
|
vowels: true,
|
|
57
66
|
},
|
|
58
67
|
};
|
package/src/i18n/de.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"cell.filter-cell": "Zielort
|
|
2
|
+
"cell.filter-cell": "Zielort",
|
|
3
3
|
"cell.set-blank": "Als Blanko markieren",
|
|
4
4
|
"cell.set-not-blank": "Nicht als Blanko markieren",
|
|
5
5
|
"cell.tile.location": "Brett: Stein ({{x}}, {{y}})",
|
|
6
|
-
"cell.toggle-direction": "Schreibrichtung
|
|
6
|
+
"cell.toggle-direction": "Schreibrichtung",
|
|
7
7
|
"common.blanks": "Blankos",
|
|
8
8
|
"common.clear": "Löschen",
|
|
9
9
|
"common.close": "Schließen",
|
package/src/i18n/en.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"cell.filter-cell": "Target destination
|
|
2
|
+
"cell.filter-cell": "Target destination",
|
|
3
3
|
"cell.set-blank": "Mark it a blank",
|
|
4
4
|
"cell.set-not-blank": "Mark it not a blank",
|
|
5
5
|
"cell.tile.location": "Board: tile ({{x}}, {{y}})",
|
|
6
|
-
"cell.toggle-direction": "Typing direction
|
|
6
|
+
"cell.toggle-direction": "Typing direction",
|
|
7
7
|
"common.blanks": "Blanks",
|
|
8
8
|
"common.clear": "Clear",
|
|
9
9
|
"common.close": "Close",
|
package/src/i18n/es.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"cell.filter-cell": "Destino objetivo
|
|
2
|
+
"cell.filter-cell": "Destino objetivo",
|
|
3
3
|
"cell.set-blank": "Marcar como en blanco",
|
|
4
4
|
"cell.set-not-blank": "Marcar como no en blanco",
|
|
5
5
|
"cell.tile.location": "Tablero: espacio ({{x}}, {{y}})",
|
|
6
|
-
"cell.toggle-direction": "Dirección de escritura
|
|
6
|
+
"cell.toggle-direction": "Dirección de escritura",
|
|
7
7
|
"common.blanks": "Blancos",
|
|
8
8
|
"common.clear": "Borrar",
|
|
9
9
|
"common.close": "Cerrar",
|
package/src/i18n/fa.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"cell.filter-cell": "مقصد
|
|
2
|
+
"cell.filter-cell": "مقصد",
|
|
3
3
|
"cell.set-blank": "علامت گذاری به عنوان خالی",
|
|
4
4
|
"cell.set-not-blank": "علامت گذاری به عنوان غیر خالی",
|
|
5
|
-
"cell.toggle-direction": "جهت تایپ - کلیک برای تغییر",
|
|
6
5
|
"cell.tile.location": "({{x}}، {{y}}) کاشی: صفحه",
|
|
6
|
+
"cell.toggle-direction": "جهت تایپ",
|
|
7
7
|
"common.blanks": "خالی",
|
|
8
8
|
"common.clear": "پاک کردن",
|
|
9
9
|
"common.close": "بستن",
|
package/src/i18n/fr.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"cell.filter-cell": "Destination cible
|
|
2
|
+
"cell.filter-cell": "Destination cible",
|
|
3
3
|
"cell.set-blank": "Marquer comme vide",
|
|
4
4
|
"cell.set-not-blank": "Marquer comme non vide",
|
|
5
5
|
"cell.tile.location": "Plateau: la case ({{x}}, {{y}})",
|
|
6
|
-
"cell.toggle-direction": "Direction d'écriture
|
|
6
|
+
"cell.toggle-direction": "Direction d'écriture",
|
|
7
7
|
"common.blanks": "Cases vides",
|
|
8
8
|
"common.clear": "Effacer",
|
|
9
9
|
"common.close": "Fermer",
|
package/src/i18n/pl.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"cell.filter-cell": "Miejsce docelowe
|
|
2
|
+
"cell.filter-cell": "Miejsce docelowe",
|
|
3
3
|
"cell.set-blank": "Oznacz jako blank",
|
|
4
4
|
"cell.set-not-blank": "Oznacz jako nie blank",
|
|
5
5
|
"cell.tile.location": "Plansza: płytka ({{x}}, {{y}})",
|
|
6
|
-
"cell.toggle-direction": "Kierunek wpisywania
|
|
6
|
+
"cell.toggle-direction": "Kierunek wpisywania",
|
|
7
7
|
"common.blanks": "Blanki",
|
|
8
8
|
"common.clear": "Wyczyść",
|
|
9
9
|
"common.close": "Zamknij",
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const dataUrlToBlob = (dataUrl: string): Blob => {
|
|
2
|
+
const [mime = '', data] = dataUrl.split(',');
|
|
3
|
+
const [, type] = mime.match(/:(.*?);/) || [];
|
|
4
|
+
|
|
5
|
+
if (typeof type !== 'string') {
|
|
6
|
+
throw new Error('Unsupported data URL');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const byteString = globalThis.atob(data);
|
|
10
|
+
const u8arr = new Uint8Array(byteString.length);
|
|
11
|
+
let index = byteString.length;
|
|
12
|
+
|
|
13
|
+
while (index--) {
|
|
14
|
+
u8arr[index] = byteString.charCodeAt(index);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return new Blob([u8arr], { type });
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default dataUrlToBlob;
|
package/src/lib/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ export { default as createKeyComparator } from './createKeyComparator';
|
|
|
8
8
|
export { default as createNullMovingComparator } from './createNullMovingComparator';
|
|
9
9
|
export { default as createRegExp } from './createRegExp';
|
|
10
10
|
export { default as createStringComparator } from './createStringComparator';
|
|
11
|
+
export { default as dataUrlToBlob } from './dataUrlToBlob';
|
|
11
12
|
export { default as detectLocale } from './detectLocale';
|
|
12
13
|
export { default as extractCharacters } from './extractCharacters';
|
|
13
14
|
export { default as extractInputValue } from './extractInputValue';
|
package/src/pages/_app.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import { FunctionComponent } from 'react';
|
|
|
4
4
|
import { Provider } from 'react-redux';
|
|
5
5
|
|
|
6
6
|
import { SeoMessage } from 'components';
|
|
7
|
-
import {
|
|
7
|
+
import { store } from 'state';
|
|
8
8
|
|
|
9
9
|
import 'styles/global.scss';
|
|
10
10
|
|
|
@@ -40,8 +40,6 @@ const KEYWORDS = [
|
|
|
40
40
|
'Kamil Mielnik',
|
|
41
41
|
].join(',');
|
|
42
42
|
|
|
43
|
-
const store = createAppStore();
|
|
44
|
-
|
|
45
43
|
const App: FunctionComponent<AppProps> = ({ Component, pageProps }) => (
|
|
46
44
|
<>
|
|
47
45
|
<Head>
|
package/src/pages/index.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import { FunctionComponent, useCallback, useState } from 'react';
|
|
|
4
4
|
import ReactModal from 'react-modal';
|
|
5
5
|
import { useDispatch } from 'react-redux';
|
|
6
6
|
|
|
7
|
-
import { Logo, NavButtons, Solver
|
|
7
|
+
import { Logo, NavButtons, Solver } from 'components';
|
|
8
8
|
import { useDirection, useEffectOnce, useLanguage, useLocalStorage } from 'hooks';
|
|
9
9
|
import { LOCALE_FEATURES } from 'i18n';
|
|
10
10
|
import {
|
|
@@ -75,8 +75,6 @@ const Index: FunctionComponent<Props> = ({ version }) => {
|
|
|
75
75
|
|
|
76
76
|
return (
|
|
77
77
|
<>
|
|
78
|
-
<SvgFontFix />
|
|
79
|
-
|
|
80
78
|
<nav className={styles.nav}>
|
|
81
79
|
<div className={styles.navContent}>
|
|
82
80
|
<div className={styles.navLogo}>
|
package/src/parameters/index.ts
CHANGED
|
@@ -19,6 +19,34 @@ export const COLOR_GREEN = '#bae3ba';
|
|
|
19
19
|
export const COLOR_RED = '#f7c2aa';
|
|
20
20
|
export const COLOR_YELLOW = '#efe3ae';
|
|
21
21
|
|
|
22
|
+
export const COLOR_BONUS_CHARACTER_1 = '#f7f1d6';
|
|
23
|
+
export const COLOR_BONUS_CHARACTER_2 = '#d6ebd6';
|
|
24
|
+
export const COLOR_BONUS_CHARACTER_3 = '#dde4f6';
|
|
25
|
+
export const COLOR_BONUS_CHARACTER_5 = '#fbe0d4';
|
|
26
|
+
export const COLOR_BONUS_CHARACTER_MULTIPLIER_2 = '#b8d5ed';
|
|
27
|
+
export const COLOR_BONUS_CHARACTER_MULTIPLIER_3 = '#86aed1';
|
|
28
|
+
export const COLOR_BONUS_START = '#b284b8';
|
|
29
|
+
export const COLOR_BONUS_WORD_MULTIPLIER_2 = '#fbc997';
|
|
30
|
+
export const COLOR_BONUS_WORD_MULTIPLIER_3 = '#f19393';
|
|
31
|
+
export const COLOR_FILTERED = '#444';
|
|
32
|
+
|
|
33
|
+
export const COLOR_BONUS_CHARACTER: Record<number, string> = {
|
|
34
|
+
1: COLOR_BONUS_CHARACTER_1,
|
|
35
|
+
2: COLOR_BONUS_CHARACTER_2,
|
|
36
|
+
3: COLOR_BONUS_CHARACTER_3,
|
|
37
|
+
5: COLOR_BONUS_CHARACTER_5,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const COLOR_BONUS_CHARACTER_MULTIPLIER: Record<number, string> = {
|
|
41
|
+
2: COLOR_BONUS_CHARACTER_MULTIPLIER_2,
|
|
42
|
+
3: COLOR_BONUS_CHARACTER_MULTIPLIER_3,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const COLOR_BONUS_WORD: Record<number, string> = {
|
|
46
|
+
2: COLOR_BONUS_WORD_MULTIPLIER_2,
|
|
47
|
+
3: COLOR_BONUS_WORD_MULTIPLIER_3,
|
|
48
|
+
};
|
|
49
|
+
|
|
22
50
|
export const SPACING_XS = 2;
|
|
23
51
|
export const SPACING_S = 5;
|
|
24
52
|
export const SPACING_M = 10;
|
|
@@ -40,6 +68,9 @@ export const BOARD_TILE_SIZE_MAX = 64;
|
|
|
40
68
|
*/
|
|
41
69
|
export const BOARD_TILE_SIZE_MIN = 20;
|
|
42
70
|
|
|
71
|
+
export const BORDER_COLOR = '#cdcdcd';
|
|
72
|
+
export const BORDER_COLOR_LIGHT = '#d9d9d9';
|
|
73
|
+
export const BORDER_RADIUS = 5;
|
|
43
74
|
export const BORDER_WIDTH = 1;
|
|
44
75
|
|
|
45
76
|
export const BUTTON_ICON_SIZE = 24;
|
|
@@ -90,10 +121,10 @@ export const RACK_TILE_SIZE_MAX = 80;
|
|
|
90
121
|
|
|
91
122
|
export const REMAINING_TILES_TILE_SIZE = 50;
|
|
92
123
|
|
|
93
|
-
export const RESULTS_HEADER_HEIGHT = 35;
|
|
94
|
-
|
|
95
124
|
export const RESULTS_ITEM_HEIGHT = 40;
|
|
96
125
|
|
|
126
|
+
export const RESULTS_HEADER_HEIGHT = RESULTS_ITEM_HEIGHT;
|
|
127
|
+
|
|
97
128
|
export const SOLVER_COLUMN_WIDTH = 580;
|
|
98
129
|
|
|
99
130
|
export const TEXT_INPUT_HEIGHT = 40;
|
package/src/state/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from './actions';
|
|
2
|
-
export { default as createAppStore } from './createAppStore';
|
|
3
2
|
export { default as localStorage } from './localStorage';
|
|
4
3
|
export * from './selectors';
|
|
5
4
|
export * from './slices';
|
|
5
|
+
export { default as store } from './store';
|
|
6
6
|
export { default as useTranslate } from './useTranslate';
|
|
7
7
|
export { default as useTypedSelector } from './useTypedSelector';
|