@scrabble-solver/scrabble-solver 2.10.7 → 2.10.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +15 -21
- 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/images-manifest.json +1 -1
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +1 -1
- package/.next/required-server-files.json +1 -1
- package/.next/routes-manifest.json +1 -1
- package/.next/server/chunks/176.js +4603 -395
- package/.next/server/chunks/664.js +27 -2414
- package/.next/server/chunks/859.js +29 -1
- package/.next/server/font-loader-manifest.js +1 -0
- package/.next/server/font-loader-manifest.json +6 -0
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/pages/404.html +2 -2
- package/.next/server/pages/404.js.nft.json +1 -1
- package/.next/server/pages/500.html +1 -12
- package/.next/server/pages/_app.js +176 -13
- package/.next/server/pages/_app.js.nft.json +1 -1
- package/.next/server/pages/_document.js +1 -1
- package/.next/server/pages/_document.js.nft.json +1 -1
- package/.next/server/pages/_error.js +133 -17
- package/.next/server/pages/_error.js.nft.json +1 -1
- package/.next/server/pages/api/solve.js +16 -0
- package/.next/server/pages/index.html +1 -9
- package/.next/server/pages/index.js +52 -165
- package/.next/server/pages/index.js.nft.json +1 -1
- package/.next/server/pages/index.json +1 -1
- package/.next/server/pages-manifest.json +1 -1
- package/.next/static/chunks/main-74c4d6b2b5c362f3.js +1 -0
- package/.next/static/chunks/pages/{404-67383848027ec49b.js → 404-d5ff00df1c687977.js} +1 -1
- package/.next/static/chunks/pages/_app-52cb288dc680bdfe.js +28 -0
- package/.next/static/chunks/pages/index-5c2544930e46c5ce.js +1 -0
- package/.next/static/chunks/webpack-6ef43a8d4a395f49.js +1 -0
- package/.next/static/css/ec4e47a6b1866fe5.css +1 -0
- package/.next/static/css/f65b7b2a74f57c1c.css +2 -0
- package/.next/static/fZRsz4P0gQ8Wgb9jP8eap/_buildManifest.js +1 -0
- package/.next/trace +55 -55
- package/package.json +12 -10
- package/src/components/Badge/Badge.module.scss +1 -1
- package/src/components/Board/Board.module.scss +14 -0
- package/src/components/Board/Board.tsx +117 -19
- package/src/components/Board/BoardPure.tsx +7 -15
- package/src/components/Board/components/Actions/Actions.module.scss +64 -0
- package/src/components/Board/components/Actions/Actions.tsx +68 -0
- package/src/components/Board/components/Actions/index.ts +1 -0
- package/src/components/Board/components/Cell/Cell.module.scss +22 -165
- package/src/components/Board/components/Cell/Cell.tsx +0 -37
- package/src/components/Board/components/Cell/CellPure.tsx +5 -75
- package/src/components/Board/components/index.ts +1 -0
- package/src/components/Board/hooks/useGrid.ts +16 -16
- package/src/components/Button/Button.module.scss +3 -3
- package/src/components/Checkbox/Checkbox.tsx +1 -4
- package/src/components/Dictionary/Dictionary.tsx +28 -30
- package/src/components/DictionaryInput/DictionaryInput.tsx +3 -0
- package/src/components/Key/Key.module.scss +1 -1
- package/src/components/LogoSplashScreen/LogoSplashScreen.module.scss +1 -1
- package/src/components/Modal/Modal.module.scss +4 -2
- package/src/components/Rack/Rack.module.scss +5 -0
- package/src/components/Radio/Radio.tsx +1 -4
- package/src/components/Results/Results.module.scss +2 -2
- package/src/components/SeoMessage/SeoMessage.tsx +19 -0
- package/src/components/SeoMessage/index.ts +1 -0
- package/src/components/Solver/Solver.module.scss +0 -5
- package/src/components/Solver/Solver.tsx +1 -1
- package/src/components/Solver/components/EmptyState/EmptyState.module.scss +1 -1
- package/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.module.scss +9 -2
- package/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.tsx +2 -1
- package/src/components/Tile/Tile.module.scss +23 -11
- package/src/components/Tile/Tile.tsx +26 -9
- package/src/components/Tile/TilePure.tsx +9 -4
- package/src/components/Tooltip/Tooltip.module.scss +7 -7
- package/src/components/index.ts +1 -0
- package/src/hooks/useLocalStorage/useLocalStorageBoard.ts +6 -3
- package/src/hooks/useLocalStorage/useLocalStorageConfigId.ts +6 -3
- package/src/hooks/useLocalStorage/useLocalStorageLocale.ts +6 -3
- package/src/hooks/useLocalStorage/useLocalStorageRack.ts +6 -3
- package/src/i18n/de.json +1 -0
- package/src/i18n/en.json +1 -0
- package/src/i18n/es.json +1 -0
- package/src/i18n/fa.json +1 -0
- package/src/i18n/fr.json +1 -0
- package/src/i18n/pl.json +1 -0
- package/src/icons/Flag.svg +2 -2
- package/src/icons/FlagFill.svg +4 -0
- package/src/icons/Square.svg +4 -0
- package/src/icons/SquareFill.svg +4 -0
- package/src/icons/index.ts +3 -0
- package/src/modals/RemainingTilesModal/components/Character/Character.module.scss +1 -1
- package/src/modals/ResultsModal/ResultsModal.module.scss +1 -1
- package/src/modals/SettingsModal/components/AutoGroupTilesSetting/AutoGroupTilesSetting.tsx +1 -2
- package/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.module.scss +1 -1
- package/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.tsx +1 -2
- package/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.module.scss +14 -24
- package/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.tsx +1 -2
- package/src/pages/_app.tsx +9 -5
- package/src/pages/index.module.scss +1 -2
- package/src/pages/index.tsx +10 -8
- package/src/parameters/index.ts +12 -0
- package/src/state/slices/boardSlice.ts +5 -5
- package/src/styles/animations.scss +10 -0
- package/src/styles/global.scss +2 -2
- package/src/styles/mixins.scss +60 -3
- package/src/styles/variables.scss +43 -33
- package/src/types/index.ts +1 -0
- package/.next/server/chunks/210.js +0 -122
- package/.next/server/chunks/579.js +0 -3925
- package/.next/server/chunks/676.js +0 -32
- package/.next/static/6RggBFm8kHrh-k1-CG3um/_buildManifest.js +0 -1
- package/.next/static/chunks/490-d29992f1c264d70e.js +0 -5
- package/.next/static/chunks/509-6ad4482d4351452c.js +0 -1
- package/.next/static/chunks/main-f11614d8aa7ee555.js +0 -1
- package/.next/static/chunks/pages/_app-c58cfa832b76cc87.js +0 -24
- package/.next/static/chunks/pages/index-146039f501e49c08.js +0 -1
- package/.next/static/chunks/webpack-59c5c889f52620d6.js +0 -1
- package/.next/static/css/4482c4a0064d3807.css +0 -1
- package/.next/static/css/78e42ad01f580f64.css +0 -1
- package/.next/static/css/9d1013ec684361b9.css +0 -1
- package/src/components/Board/components/Cell/Button.tsx +0 -32
- /package/.next/static/{6RggBFm8kHrh-k1-CG3um → fZRsz4P0gQ8Wgb9jP8eap}/_ssgManifest.js +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
2
|
import { useDispatch } from 'react-redux';
|
|
3
3
|
import { useEffectOnce } from 'react-use';
|
|
4
4
|
|
|
@@ -7,6 +7,7 @@ import { localStorage, rackSlice, selectRack, useTypedSelector } from 'state';
|
|
|
7
7
|
const useLocalStorageRack = (): void => {
|
|
8
8
|
const dispatch = useDispatch();
|
|
9
9
|
const rack = useTypedSelector(selectRack);
|
|
10
|
+
const [isLoaded, setIsLoaded] = useState(false);
|
|
10
11
|
|
|
11
12
|
useEffectOnce(() => {
|
|
12
13
|
const persistedRack = localStorage.getRack();
|
|
@@ -14,13 +15,15 @@ const useLocalStorageRack = (): void => {
|
|
|
14
15
|
if (persistedRack) {
|
|
15
16
|
dispatch(rackSlice.actions.init(persistedRack));
|
|
16
17
|
}
|
|
18
|
+
|
|
19
|
+
setIsLoaded(true);
|
|
17
20
|
});
|
|
18
21
|
|
|
19
22
|
useEffect(() => {
|
|
20
|
-
if (rack) {
|
|
23
|
+
if (rack && isLoaded) {
|
|
21
24
|
localStorage.setRack(rack);
|
|
22
25
|
}
|
|
23
|
-
}, [rack]);
|
|
26
|
+
}, [isLoaded, rack]);
|
|
24
27
|
};
|
|
25
28
|
|
|
26
29
|
export default useLocalStorageRack;
|
package/src/i18n/de.json
CHANGED
|
@@ -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!",
|
package/src/i18n/en.json
CHANGED
|
@@ -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!",
|
package/src/i18n/es.json
CHANGED
|
@@ -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í!",
|
package/src/i18n/fa.json
CHANGED
|
@@ -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": "حله!",
|
package/src/i18n/fr.json
CHANGED
|
@@ -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!",
|
package/src/i18n/pl.json
CHANGED
|
@@ -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!",
|
package/src/icons/Flag.svg
CHANGED
|
@@ -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>
|
package/src/icons/index.ts
CHANGED
|
@@ -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}
|
|
@@ -22,12 +22,11 @@ const ConfigSetting: FunctionComponent<Props> = ({ className, disabled }) => {
|
|
|
22
22
|
|
|
23
23
|
return (
|
|
24
24
|
<div className={className}>
|
|
25
|
-
{options.map((option
|
|
25
|
+
{options.map((option) => (
|
|
26
26
|
<Radio
|
|
27
27
|
checked={configId === option.value}
|
|
28
28
|
className={styles.option}
|
|
29
29
|
disabled={disabled}
|
|
30
|
-
id={`configId-${index}`}
|
|
31
30
|
key={option.value}
|
|
32
31
|
name="configId"
|
|
33
32
|
value={option.value}
|
|
@@ -1,17 +1,8 @@
|
|
|
1
1
|
@import 'styles/mixins';
|
|
2
2
|
|
|
3
3
|
.option {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
&:last-child {
|
|
7
|
-
margin-bottom: 0;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
&:hover,
|
|
11
|
-
&.checked {
|
|
12
|
-
.flag {
|
|
13
|
-
box-shadow: var(--box-shadow);
|
|
14
|
-
}
|
|
4
|
+
& + & {
|
|
5
|
+
margin-top: var(--spacing--m);
|
|
15
6
|
}
|
|
16
7
|
}
|
|
17
8
|
|
|
@@ -19,10 +10,10 @@
|
|
|
19
10
|
display: flex;
|
|
20
11
|
align-items: center;
|
|
21
12
|
gap: var(--spacing--l);
|
|
22
|
-
font-family:
|
|
13
|
+
font-family: var(--font--family--latin);
|
|
23
14
|
|
|
24
15
|
&.fa {
|
|
25
|
-
font-family:
|
|
16
|
+
font-family: var(--font--family--arabic);
|
|
26
17
|
}
|
|
27
18
|
}
|
|
28
19
|
|
|
@@ -30,17 +21,16 @@
|
|
|
30
21
|
$height: 32px;
|
|
31
22
|
|
|
32
23
|
height: $height;
|
|
33
|
-
box-shadow: var(--box-shadow--null);
|
|
34
24
|
transition: var(--transition);
|
|
35
25
|
|
|
36
|
-
&.
|
|
37
|
-
$aspect-ratio: 1.
|
|
26
|
+
&.de {
|
|
27
|
+
$aspect-ratio: 1.6;
|
|
38
28
|
|
|
39
29
|
width: $height * $aspect-ratio;
|
|
40
30
|
}
|
|
41
31
|
|
|
42
|
-
&.
|
|
43
|
-
$aspect-ratio: 1.
|
|
32
|
+
&.es {
|
|
33
|
+
$aspect-ratio: 1.5;
|
|
44
34
|
|
|
45
35
|
width: $height * $aspect-ratio;
|
|
46
36
|
}
|
|
@@ -51,6 +41,12 @@
|
|
|
51
41
|
width: $height * $aspect-ratio;
|
|
52
42
|
}
|
|
53
43
|
|
|
44
|
+
&.fr {
|
|
45
|
+
$aspect-ratio: 1.6;
|
|
46
|
+
|
|
47
|
+
width: $height * $aspect-ratio;
|
|
48
|
+
}
|
|
49
|
+
|
|
54
50
|
&.gb {
|
|
55
51
|
$aspect-ratio: 2;
|
|
56
52
|
|
|
@@ -68,10 +64,4 @@
|
|
|
68
64
|
|
|
69
65
|
width: $height * $aspect-ratio;
|
|
70
66
|
}
|
|
71
|
-
|
|
72
|
-
&.de {
|
|
73
|
-
$aspect-ratio: 1.6;
|
|
74
|
-
|
|
75
|
-
width: $height * $aspect-ratio;
|
|
76
|
-
}
|
|
77
67
|
}
|
|
@@ -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}
|
package/src/pages/_app.tsx
CHANGED
|
@@ -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
|
</>
|
package/src/pages/index.tsx
CHANGED
|
@@ -76,6 +76,10 @@ const Index: FunctionComponent<Props> = ({ version }) => {
|
|
|
76
76
|
}
|
|
77
77
|
}, []);
|
|
78
78
|
|
|
79
|
+
if (!isClient) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
79
83
|
return (
|
|
80
84
|
<>
|
|
81
85
|
<SvgFontFix />
|
|
@@ -100,14 +104,12 @@ const Index: FunctionComponent<Props> = ({ version }) => {
|
|
|
100
104
|
</div>
|
|
101
105
|
</div>
|
|
102
106
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
/>
|
|
110
|
-
)}
|
|
107
|
+
<Solver
|
|
108
|
+
className={styles.solver}
|
|
109
|
+
height={solverHeight}
|
|
110
|
+
width={solverWidth}
|
|
111
|
+
onShowResults={() => setShowResults(true)}
|
|
112
|
+
/>
|
|
111
113
|
</div>
|
|
112
114
|
|
|
113
115
|
<MenuModal
|
package/src/parameters/index.ts
CHANGED
|
@@ -6,6 +6,9 @@ export const BREAKPOINTS = {
|
|
|
6
6
|
xl: 1400,
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
+
export const EASE_OUT_CUBIC = 'cubic-bezier(0.33, 1, 0.68, 1)'; // https://easings.net/#easeOutCubic
|
|
10
|
+
export const TRANSITION = 'var(--transition)';
|
|
11
|
+
|
|
9
12
|
export const GITHUB_PROJECT_URL = 'https://github.com/kamilmielnik/scrabble-solver';
|
|
10
13
|
|
|
11
14
|
export const INITIALIZATION_DURATION = 100;
|
|
@@ -21,6 +24,7 @@ export const COLOR_YELLOW = '#efe3ae';
|
|
|
21
24
|
export const COMPONENTS_SPACING = 40;
|
|
22
25
|
export const COMPONENTS_SPACING_SMALL = 20;
|
|
23
26
|
|
|
27
|
+
export const BOARD_CELL_ACTIONS_OFFSET = 3;
|
|
24
28
|
export const BOARD_CELL_BORDER_WIDTH = 1;
|
|
25
29
|
export const BOARD_TILE_FONT_SIZE_MIN = 14;
|
|
26
30
|
export const BOARD_TILE_FONT_SIZE_POINTS_MIN = 10;
|
|
@@ -72,3 +76,11 @@ export const REMAINING_TILES_TILE_SIZE = 50;
|
|
|
72
76
|
export const RESULTS_HEADER_HEIGHT = 34;
|
|
73
77
|
export const RESULTS_ITEM_HEIGHT = 40;
|
|
74
78
|
export const RESULTS_INPUT_HEIGHT = 40;
|
|
79
|
+
|
|
80
|
+
export const TILE_APPEAR_DURATION = 200;
|
|
81
|
+
|
|
82
|
+
export const TILE_APPEAR_KEYFRAMES = [
|
|
83
|
+
{ transform: 'translateY(0)' },
|
|
84
|
+
{ transform: 'translateY(10%)', offset: 0.5 },
|
|
85
|
+
{ transform: 'translateY(0)' },
|
|
86
|
+
];
|
|
@@ -19,6 +19,11 @@ const boardSlice = createSlice({
|
|
|
19
19
|
return newBoard;
|
|
20
20
|
},
|
|
21
21
|
|
|
22
|
+
change: (_state, action: PayloadAction<Board>) => {
|
|
23
|
+
const board = action.payload;
|
|
24
|
+
return board;
|
|
25
|
+
},
|
|
26
|
+
|
|
22
27
|
changeCellValue: (state, action: PayloadAction<{ value: string; x: number; y: number }>) => {
|
|
23
28
|
const newBoard = state.clone();
|
|
24
29
|
const { value, x, y } = action.payload;
|
|
@@ -32,11 +37,6 @@ const boardSlice = createSlice({
|
|
|
32
37
|
return newBoard;
|
|
33
38
|
},
|
|
34
39
|
|
|
35
|
-
change: (_state, action: PayloadAction<Board>) => {
|
|
36
|
-
const board = action.payload;
|
|
37
|
-
return board;
|
|
38
|
-
},
|
|
39
|
-
|
|
40
40
|
init: (_state, action: PayloadAction<Board>) => {
|
|
41
41
|
const board = action.payload;
|
|
42
42
|
return board;
|
package/src/styles/global.scss
CHANGED
package/src/styles/mixins.scss
CHANGED
|
@@ -16,6 +16,8 @@ $media-expressions: (
|
|
|
16
16
|
* It does not work when applied on input elements.
|
|
17
17
|
*/
|
|
18
18
|
@mixin focus-effect {
|
|
19
|
+
--focus-effect--size: 6px;
|
|
20
|
+
|
|
19
21
|
position: relative;
|
|
20
22
|
|
|
21
23
|
&::after {
|
|
@@ -25,10 +27,10 @@ $media-expressions: (
|
|
|
25
27
|
right: 0;
|
|
26
28
|
bottom: 0;
|
|
27
29
|
left: 0;
|
|
28
|
-
z-index:
|
|
30
|
+
z-index: var(--z-index--focus-effect);
|
|
29
31
|
transition: var(--transition);
|
|
30
32
|
border-radius: var(--border--radius);
|
|
31
|
-
box-shadow: 0 0 0 var(--
|
|
33
|
+
box-shadow: 0 0 0 var(--focus-effect--size) transparent;
|
|
32
34
|
pointer-events: none;
|
|
33
35
|
}
|
|
34
36
|
|
|
@@ -39,7 +41,7 @@ $media-expressions: (
|
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
&::after {
|
|
42
|
-
box-shadow: 0 0 0 var(--
|
|
44
|
+
box-shadow: 0 0 0 var(--focus-effect--size) var(--color--focus);
|
|
43
45
|
}
|
|
44
46
|
}
|
|
45
47
|
}
|
|
@@ -86,3 +88,58 @@ $media-expressions: (
|
|
|
86
88
|
text-shadow: $size 0 $color, (-$size) 0 $color, 0 $size $color, 0 (-$size) $color, (-$size) (-$size) $color,
|
|
87
89
|
(-$size) $size $color, $size (-$size) $color, $size $size $color;
|
|
88
90
|
}
|
|
91
|
+
|
|
92
|
+
@mixin lighthouse-input-size-hack {
|
|
93
|
+
// Hack for this Lighthouse warning:
|
|
94
|
+
// > Interactive elements like buttons and links should be large enough (48x48px), and have
|
|
95
|
+
// > enough space around them, to be easy enough to tap without overlapping onto other elements.
|
|
96
|
+
|
|
97
|
+
input {
|
|
98
|
+
position: absolute;
|
|
99
|
+
top: -100%;
|
|
100
|
+
left: -100%;
|
|
101
|
+
width: 300%;
|
|
102
|
+
height: 300%;
|
|
103
|
+
clip-path: inset((100% / 3));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
[dir='ltr'] & {
|
|
107
|
+
&:nth-child(1),
|
|
108
|
+
&:nth-child(2),
|
|
109
|
+
&:nth-child(3) {
|
|
110
|
+
input {
|
|
111
|
+
left: 0;
|
|
112
|
+
clip-path: polygon(0 (100% / 3), (100% / 3) (100% / 3), (100% / 3) (200% / 3), 0 (200% / 3));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
&:nth-last-child(1),
|
|
117
|
+
&:nth-last-child(2),
|
|
118
|
+
&:nth-last-child(3) {
|
|
119
|
+
input {
|
|
120
|
+
left: -200%;
|
|
121
|
+
clip-path: polygon((200% / 3) (100% / 3), 100% (100% / 3), 100% (200% / 3), (200% / 3) (200% / 3));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
[dir='rtl'] & {
|
|
127
|
+
&:nth-child(1),
|
|
128
|
+
&:nth-child(2),
|
|
129
|
+
&:nth-child(3) {
|
|
130
|
+
input {
|
|
131
|
+
left: -200%;
|
|
132
|
+
clip-path: polygon((200% / 3) (100% / 3), 100% (100% / 3), 100% (200% / 3), (200% / 3) (200% / 3));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
&:nth-last-child(1),
|
|
137
|
+
&:nth-last-child(2),
|
|
138
|
+
&:nth-last-child(3) {
|
|
139
|
+
input {
|
|
140
|
+
left: 0;
|
|
141
|
+
clip-path: polygon(0 (100% / 3), (100% / 3) (100% / 3), (100% / 3) (200% / 3), 0 (200% / 3));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -1,55 +1,63 @@
|
|
|
1
1
|
$easeOutSine: cubic-bezier(0.61, 1, 0.88, 1);
|
|
2
2
|
|
|
3
3
|
:root {
|
|
4
|
+
--border: var(--border--width) solid var(--border--color);
|
|
4
5
|
--border--color: #cdcdcd;
|
|
5
6
|
--border--color--light: #d9d9d9;
|
|
6
7
|
--border--radius: 5px;
|
|
7
8
|
--border--width: 1px;
|
|
8
|
-
--border: var(--border--width) solid var(--border--color);
|
|
9
9
|
|
|
10
|
+
--box-shadow: 0 0 var(--box-shadow--blur) var(--box-shadow--spread) var(--box-shadow--color);
|
|
10
11
|
--box-shadow--blur: 10px;
|
|
12
|
+
--box-shadow--color: rgba(0, 0, 0, 0.15);
|
|
11
13
|
--box-shadow--spread: 1px;
|
|
12
|
-
--box-shadow--offset: 1px;
|
|
13
|
-
--box-shadow--offset--negative: calc(-1 * var(--box-shadow--offset));
|
|
14
|
-
--box-shadow--color: #{rgba(#000, 0.15)};
|
|
15
|
-
--box-shadow: 0 0 var(--box-shadow--blur) var(--box-shadow--spread) var(--box-shadow--color);
|
|
16
|
-
--box-shadow--focus--spread: 6px;
|
|
17
14
|
--box-shadow--null: 0 0 var(--box-shadow--blur) var(--box-shadow--spread) transparent;
|
|
18
15
|
--box-shadow--error: 0 0 var(--box-shadow--blur) var(--box-shadow--spread) var(--color--error);
|
|
19
16
|
|
|
20
|
-
--color--
|
|
21
|
-
--color--background--secondary: #111;
|
|
22
|
-
--color--background--overlay: rgba(255, 255, 255, 0.65);
|
|
23
|
-
--color--error: hsl(0deg, 92%, 62%);
|
|
24
|
-
--color--success: #00a900;
|
|
25
|
-
--color--info: var(--color--dark-blue);
|
|
26
|
-
--color--warning: hsl(35deg, 90%, 60%);
|
|
27
|
-
--color--focus: #{rgba(#268fff, 0.5)};
|
|
28
|
-
--color--foreground: #222;
|
|
29
|
-
--color--foreground--secondary: #444;
|
|
30
|
-
--color--inactive: #cdcdcd;
|
|
31
|
-
--color--primary: var(--color--violet);
|
|
32
|
-
|
|
33
|
-
--color--yellow: #efe3ae;
|
|
34
|
-
--color--yellow--light: #f7f1d6;
|
|
35
|
-
--color--green: #bae3ba;
|
|
36
|
-
--color--green--light: #d6ebd6;
|
|
17
|
+
--color--white: #ffffff;
|
|
37
18
|
--color--blue: #c7d8f9;
|
|
38
19
|
--color--blue--light: #dde4f6;
|
|
39
|
-
--color--
|
|
40
|
-
--color--
|
|
41
|
-
--color--dark-blue: #1868ad;
|
|
42
|
-
--color--dark-blue--light: #86aed1;
|
|
20
|
+
--color--green: #bae3ba;
|
|
21
|
+
--color--green--light: #d6ebd6;
|
|
43
22
|
--color--red: #f7c2aa;
|
|
44
23
|
--color--red--light: #fbe0d4;
|
|
45
24
|
--color--violet: #78387f;
|
|
46
25
|
--color--violet--light: #b284b8;
|
|
47
|
-
--color--
|
|
48
|
-
--color--
|
|
26
|
+
--color--yellow: #efe3ae;
|
|
27
|
+
--color--yellow--light: #f7f1d6;
|
|
28
|
+
|
|
29
|
+
--color--focus: #{rgba(#268fff, 0.5)};
|
|
30
|
+
--color--inactive: #cdcdcd;
|
|
31
|
+
--color--background: #f4f4f4;
|
|
32
|
+
--color--background--element: var(--color--white);
|
|
33
|
+
--color--background--overlay: rgba(255, 255, 255, 0.65);
|
|
34
|
+
--color--foreground: #222;
|
|
35
|
+
--color--foreground--secondary: #444;
|
|
36
|
+
--color--error: hsl(0, 92%, 62%);
|
|
37
|
+
--color--error--opposite: var(--color--white);
|
|
38
|
+
--color--info: #1868ad;
|
|
39
|
+
--color--success: #00a900;
|
|
40
|
+
--color--warning: hsl(35, 90%, 60%);
|
|
41
|
+
--color--primary: var(--color--violet);
|
|
42
|
+
--color--primary--opposite: var(--color--white);
|
|
43
|
+
|
|
44
|
+
--color--bonus--character--1: var(--color--yellow--light);
|
|
45
|
+
--color--bonus--character--2: var(--color--green--light);
|
|
46
|
+
--color--bonus--character--3: var(--color--blue--light);
|
|
47
|
+
--color--bonus--character--5: var(--color--red--light);
|
|
48
|
+
--color--bonus--character-multiplier--2: #b8d5ed;
|
|
49
|
+
--color--bonus--character-multiplier--3: #86aed1;
|
|
50
|
+
--color--bonus--start: var(--color--violet--light);
|
|
51
|
+
--color--bonus--word-multiplier--2: #fbc997;
|
|
52
|
+
--color--bonus--word-multiplier--3: #f19393;
|
|
53
|
+
--color--tooltip--background: #222;
|
|
54
|
+
--color--tooltip--foreground: var(--color--white);
|
|
49
55
|
|
|
50
56
|
--font--family: 'Open Sans', sans-serif;
|
|
51
|
-
--font--family--
|
|
57
|
+
--font--family--latin: 'Open Sans', sans-serif;
|
|
58
|
+
--font--family--arabic: 'Vazirmatn', sans-serif;
|
|
52
59
|
--font--family--monospace: 'Roboto Mono', monospace;
|
|
60
|
+
--font--family--title: 'Lato', sans-serif;
|
|
53
61
|
--font--size--h1: 30px;
|
|
54
62
|
--font--size--h2: 22px;
|
|
55
63
|
--font--size--h3: 18px;
|
|
@@ -66,13 +74,17 @@ $easeOutSine: cubic-bezier(0.61, 1, 0.88, 1);
|
|
|
66
74
|
--spacing--xl: 40px;
|
|
67
75
|
--spacing--xxl: 80px;
|
|
68
76
|
|
|
77
|
+
--transition: all var(--transition--duration) var(--transition--easing);
|
|
78
|
+
--transition--long: all var(--transition--duration--long) var(--transition--easing);
|
|
69
79
|
--transition--duration: 100ms;
|
|
70
80
|
--transition--duration--long: 250ms;
|
|
71
81
|
--transition--easing: #{$easeOutSine};
|
|
72
|
-
--transition: all var(--transition--duration) var(--transition--easing);
|
|
73
82
|
|
|
83
|
+
--z-index--focus-effect: 1;
|
|
84
|
+
--z-index--actions: 2;
|
|
74
85
|
--z-index--modal: 100;
|
|
75
86
|
--z-index--close-button: 101;
|
|
87
|
+
--z-index--tooltip: 102;
|
|
76
88
|
|
|
77
89
|
--dictionary--height: 260px;
|
|
78
90
|
--modal--width: 370px;
|
|
@@ -80,6 +92,4 @@ $easeOutSine: cubic-bezier(0.61, 1, 0.88, 1);
|
|
|
80
92
|
--square-button--size: 32px;
|
|
81
93
|
--button--icon--size: 24px;
|
|
82
94
|
--text-input--height: 40px;
|
|
83
|
-
--tooltip--background: #222;
|
|
84
|
-
--tooltip--foreground: #fff;
|
|
85
95
|
}
|