@scrabble-solver/scrabble-solver 2.10.2 → 2.10.4
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 +31 -19
- 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/176.js +1269 -1559
- package/.next/server/chunks/579.js +50 -26
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-react-loadable-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 +2 -2
- package/.next/server/pages/_app.js.nft.json +1 -1
- package/.next/server/pages/api/dictionary/[locale]/[word].js +2 -1
- package/.next/server/pages/api/solve.js +22 -6
- package/.next/server/pages/index.html +2 -2
- package/.next/server/pages/index.js +1539 -52
- 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/P7XhuDLmwJJqC8kgPjX42/_buildManifest.js +1 -0
- package/.next/static/{FjrbXpI5fkt4lmko-vL_7 → P7XhuDLmwJJqC8kgPjX42}/_ssgManifest.js +0 -0
- package/.next/static/chunks/490-d29992f1c264d70e.js +5 -0
- package/.next/static/chunks/528-9942ddad0031ff79.js +1 -0
- package/.next/static/chunks/pages/{404-24f9617eeb8d6dc1.js → 404-6c99a0c91257c60b.js} +1 -1
- package/.next/static/chunks/pages/_app-fa0661b072fc6af9.js +24 -0
- package/.next/static/chunks/pages/index-d761f0af070273d2.js +1 -0
- package/.next/static/css/78e42ad01f580f64.css +1 -0
- package/.next/static/css/97eb6ee0c4300c83.css +1 -0
- package/.next/static/css/dcca0c1a39cf5ef5.css +1 -0
- package/.next/trace +55 -52
- package/package.json +11 -9
- package/src/components/Badge/Badge.module.scss +4 -5
- package/src/components/Board/BoardPure.tsx +5 -5
- package/src/components/Board/components/Cell/Cell.module.scss +15 -2
- package/src/components/Button/Button.module.scss +10 -38
- package/src/components/Button/Button.tsx +6 -5
- package/src/components/Dictionary/Dictionary.module.scss +1 -2
- package/src/components/Dictionary/Dictionary.tsx +2 -6
- package/src/components/DictionaryInput/DictionaryInput.module.scss +1 -3
- package/src/components/EmptyState/EmptyState.module.scss +6 -7
- package/src/components/EmptyState/EmptyState.tsx +6 -6
- package/src/components/Key/Key.module.scss +0 -1
- package/src/components/{Splash/Splash.module.scss → LogoSplashScreen/LogoSplashScreen.module.scss} +1 -1
- package/src/components/{Splash/Splash.tsx → LogoSplashScreen/LogoSplashScreen.tsx} +7 -7
- package/src/components/LogoSplashScreen/index.ts +1 -0
- package/src/components/{Sidebar/Sidebar.module.scss → Modal/Modal.module.scss} +25 -20
- package/src/components/{Sidebar/Sidebar.tsx → Modal/Modal.tsx} +9 -9
- package/src/components/{Sidebar → Modal}/components/Section/Section.module.scss +0 -0
- package/src/components/{Sidebar → Modal}/components/Section/Section.tsx +0 -0
- package/src/components/{Sidebar → Modal}/components/Section/index.ts +0 -0
- package/src/components/{Sidebar → Modal}/components/index.ts +0 -0
- package/src/components/Modal/index.ts +1 -0
- package/src/components/NavButtons/NavButtons.tsx +22 -3
- package/src/components/Progress/Progress.module.scss +9 -0
- package/src/components/Progress/Progress.tsx +38 -0
- package/src/components/Progress/index.ts +1 -0
- package/src/components/Rack/Rack.module.scss +2 -0
- package/src/components/Rack/Rack.tsx +3 -1
- package/src/components/Rack/RackTile.tsx +3 -2
- package/src/components/ResultCandidatePicker/ResultCandidatePicker.module.scss +76 -0
- package/src/components/ResultCandidatePicker/ResultCandidatePicker.tsx +38 -0
- package/src/components/ResultCandidatePicker/index.ts +1 -0
- package/src/components/Results/Result.tsx +64 -43
- package/src/components/Results/Results.module.scss +9 -16
- package/src/components/Results/Results.tsx +45 -28
- package/src/components/Results/SolveButton.tsx +9 -7
- package/src/components/Results/{getColumns.ts → getLocaleColumns.ts} +2 -2
- package/src/components/Results/types.ts +16 -0
- package/src/components/Results/useColumns.ts +44 -0
- package/src/components/ResultsInput/ResultsInput.module.scss +1 -3
- package/src/components/Sizer/Sizer.module.scss +10 -0
- package/src/components/Sizer/Sizer.tsx +10 -0
- package/src/components/Sizer/index.ts +1 -0
- package/src/components/Solver/Solver.module.scss +83 -27
- package/src/components/Solver/Solver.tsx +157 -24
- package/src/components/Solver/components/ApplyButton/ApplyButton.module.scss +5 -0
- package/src/components/Solver/components/ApplyButton/ApplyButton.tsx +37 -0
- package/src/components/Solver/components/ApplyButton/index.ts +1 -0
- package/src/components/Solver/components/EmptyState/EmptyState.module.scss +59 -0
- package/src/components/Solver/components/EmptyState/EmptyState.tsx +41 -0
- package/src/components/Solver/components/EmptyState/index.ts +1 -0
- package/src/components/Solver/components/SolveButton/SolveButton.module.scss +4 -0
- package/src/components/Solver/components/SolveButton/SolveButton.tsx +42 -0
- package/src/components/Solver/components/SolveButton/index.ts +1 -0
- package/src/components/Solver/components/index.ts +3 -0
- package/src/components/{Screen/Screen.module.scss → SplashScreen/SplashScreen.module.scss} +2 -12
- package/src/components/{Screen/Screen.tsx → SplashScreen/SplashScreen.tsx} +4 -4
- package/src/components/SplashScreen/index.ts +1 -0
- package/src/components/SquareButton/SquareButton.module.scss +3 -3
- package/src/components/Tile/Tile.module.scss +7 -15
- package/src/components/Tooltip/Tooltip.module.scss +0 -1
- package/src/components/index.ts +6 -7
- package/src/hooks/index.ts +1 -1
- package/src/hooks/useMediaQuery.ts +11 -0
- package/src/hooks/usePortal.tsx +1 -1
- package/src/i18n/de.json +2 -0
- package/src/i18n/en.json +2 -0
- package/src/i18n/es.json +2 -0
- package/src/i18n/fa.json +2 -0
- package/src/i18n/fr.json +2 -0
- package/src/i18n/pl.json +2 -0
- package/src/icons/CardChecklist.svg +5 -0
- package/src/icons/Check.svg +2 -2
- package/src/icons/ChevronDown.svg +4 -0
- package/src/icons/CrossCircleFill.svg +4 -0
- package/src/icons/{CrossFill.svg → CrossSquareFill.svg} +0 -0
- package/src/icons/ExclamationTriangleFill.svg +4 -0
- package/src/icons/InfoCircleFill.svg +4 -0
- package/src/icons/List.svg +4 -0
- package/src/icons/Search.svg +4 -0
- package/src/icons/index.ts +8 -2
- package/src/{components/KeyMap/KeyMap.tsx → modals/KeyMapModal/KeyMapModal.tsx} +11 -13
- package/src/{components/KeyMap → modals/KeyMapModal}/components/Mapping/Mapping.module.scss +0 -0
- package/src/{components/KeyMap → modals/KeyMapModal}/components/Mapping/Mapping.tsx +0 -0
- package/src/{components/KeyMap → modals/KeyMapModal}/components/Mapping/index.ts +0 -0
- package/src/{components/KeyMap → modals/KeyMapModal}/components/index.ts +0 -0
- package/src/modals/KeyMapModal/index.ts +1 -0
- package/src/{components/KeyMap → modals/KeyMapModal}/keys.tsx +1 -2
- package/src/modals/MenuModal/MenuModal.module.scss +46 -0
- package/src/modals/MenuModal/MenuModal.tsx +54 -0
- package/src/modals/MenuModal/index.ts +1 -0
- package/src/modals/RemainingTilesModal/RemainingTilesModal.module.scss +28 -0
- package/src/{components/RemainingTiles/RemainingTiles.tsx → modals/RemainingTilesModal/RemainingTilesModal.tsx} +14 -12
- package/src/{components/RemainingTiles → modals/RemainingTilesModal/components/Character}/Character.module.scss +6 -2
- package/src/{components/RemainingTiles → modals/RemainingTilesModal/components/Character}/Character.tsx +11 -3
- package/src/modals/RemainingTilesModal/components/Character/index.ts +1 -0
- package/src/modals/RemainingTilesModal/components/index.ts +1 -0
- package/src/modals/RemainingTilesModal/index.ts +1 -0
- package/src/modals/ResultsModal/ResultsModal.module.scss +7 -0
- package/src/modals/ResultsModal/ResultsModal.tsx +58 -0
- package/src/modals/ResultsModal/index.ts +1 -0
- package/src/modals/SettingsModal/SettingsModal.tsx +34 -0
- package/src/{components/Settings → modals/SettingsModal}/components/AutoGroupTilesSetting/AutoGroupTilesSetting.module.scss +0 -0
- package/src/{components/Settings → modals/SettingsModal}/components/AutoGroupTilesSetting/AutoGroupTilesSetting.tsx +1 -2
- package/src/{components/Settings → modals/SettingsModal}/components/AutoGroupTilesSetting/constants.ts +0 -0
- package/src/{components/Settings → modals/SettingsModal}/components/AutoGroupTilesSetting/index.ts +0 -0
- package/src/{components/Settings → modals/SettingsModal}/components/AutoGroupTilesSetting/lib.ts +0 -0
- package/src/{components/Settings → modals/SettingsModal}/components/ConfigSetting/ConfigSetting.module.scss +0 -0
- package/src/{components/Settings → modals/SettingsModal}/components/ConfigSetting/ConfigSetting.tsx +1 -2
- package/src/{components/Settings → modals/SettingsModal}/components/ConfigSetting/index.ts +0 -0
- package/src/{components/Settings → modals/SettingsModal}/components/ConfigSetting/options.ts +0 -0
- package/src/{components/Settings → modals/SettingsModal}/components/ConfigSetting/types.ts +0 -0
- package/src/{components/Settings → modals/SettingsModal}/components/LocaleSetting/LocaleSetting.module.scss +0 -0
- package/src/{components/Settings → modals/SettingsModal}/components/LocaleSetting/LocaleSetting.tsx +1 -2
- package/src/{components/Settings → modals/SettingsModal}/components/LocaleSetting/index.ts +0 -0
- package/src/{components/Settings → modals/SettingsModal}/components/LocaleSetting/options.ts +0 -0
- package/src/{components/Settings → modals/SettingsModal}/components/LocaleSetting/types.ts +0 -0
- package/src/{components/Settings → modals/SettingsModal}/components/index.ts +0 -0
- package/src/modals/SettingsModal/index.ts +1 -0
- package/src/{components/Words/Words.module.scss → modals/WordsModal/WordsModal.module.scss} +7 -1
- package/src/{components/Words/Words.tsx → modals/WordsModal/WordsModal.tsx} +10 -12
- package/src/modals/WordsModal/index.ts +1 -0
- package/src/modals/index.ts +6 -0
- package/src/pages/api/dictionary/[locale]/[word].ts +2 -1
- package/src/pages/index.module.scss +6 -4
- package/src/pages/index.tsx +63 -26
- package/src/parameters/index.ts +28 -6
- package/src/state/createAppStore.ts +7 -4
- package/src/styles/mixins.scss +15 -13
- package/src/styles/variables.scss +15 -17
- package/src/types/index.ts +2 -0
- package/tsconfig.json +1 -0
- package/.next/cache/webpack/client-development/0.pack +0 -0
- package/.next/cache/webpack/client-development/1.pack +0 -0
- package/.next/cache/webpack/client-development/2.pack +0 -0
- package/.next/cache/webpack/client-development/3.pack +0 -0
- package/.next/cache/webpack/client-development/4.pack +0 -0
- package/.next/cache/webpack/client-development/index.pack +0 -0
- package/.next/cache/webpack/client-development/index.pack.old +0 -0
- package/.next/cache/webpack/server-development/0.pack +0 -0
- package/.next/cache/webpack/server-development/10.pack_ +0 -0
- package/.next/cache/webpack/server-development/5.pack_ +0 -0
- package/.next/cache/webpack/server-development/8.pack_ +0 -0
- package/.next/cache/webpack/server-development/index.pack +0 -0
- package/.next/static/FjrbXpI5fkt4lmko-vL_7/_buildManifest.js +0 -1
- package/.next/static/chunks/361-d16f336a9752a55a.js +0 -1
- package/.next/static/chunks/724-eb48df4d1ba3df8b.js +0 -5
- package/.next/static/chunks/amp.js +0 -720
- package/.next/static/chunks/main.js +0 -1076
- package/.next/static/chunks/pages/_app-959e495f0f221247.js +0 -24
- package/.next/static/chunks/pages/_app.js +0 -2121
- package/.next/static/chunks/pages/_error.js +0 -28
- package/.next/static/chunks/pages/index-1e30dafa41bddb80.js +0 -1
- package/.next/static/chunks/pages/index.js +0 -5314
- package/.next/static/chunks/react-refresh.js +0 -62
- package/.next/static/chunks/webpack.js +0 -1237
- package/.next/static/css/aafd07997120f1e4.css +0 -1
- package/.next/static/css/c8d26240c04079b9.css +0 -1
- package/.next/static/css/eb9d57f7103525ab.css +0 -1
- package/.next/static/development/_buildManifest.js +0 -1
- package/.next/static/development/_ssgManifest.js +0 -1
- package/.next/static/webpack/fb4b50d5e70ee127.webpack.hot-update.json +0 -1
- package/.next/static/webpack/pages/index.fb4b50d5e70ee127.hot-update.js +0 -171
- package/.next/static/webpack/webpack.fb4b50d5e70ee127.hot-update.js +0 -18
- package/src/components/KeyMap/index.ts +0 -1
- package/src/components/RemainingTiles/RemainingTiles.module.scss +0 -16
- package/src/components/RemainingTiles/index.ts +0 -1
- package/src/components/Screen/index.ts +0 -1
- package/src/components/Settings/Settings.tsx +0 -35
- package/src/components/Settings/index.ts +0 -1
- package/src/components/Sidebar/index.ts +0 -1
- package/src/components/Splash/index.ts +0 -1
- package/src/components/Words/index.ts +0 -1
- package/src/hooks/useIsTablet.ts +0 -10
- package/src/icons/Play.svg +0 -4
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { FunctionComponent } from 'react';
|
|
2
2
|
|
|
3
|
+
import { Badge, Modal } from 'components';
|
|
3
4
|
import { LOCALE_FEATURES } from 'i18n';
|
|
4
5
|
import { selectLocale, selectRemainingTilesGroups, useTranslate, useTypedSelector } from 'state';
|
|
5
6
|
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
import Character from './Character';
|
|
10
|
-
import styles from './RemainingTiles.module.scss';
|
|
7
|
+
import { Character } from './components';
|
|
8
|
+
import styles from './RemainingTilesModal.module.scss';
|
|
11
9
|
|
|
12
10
|
interface Props {
|
|
13
11
|
className?: string;
|
|
@@ -15,20 +13,20 @@ interface Props {
|
|
|
15
13
|
onClose: () => void;
|
|
16
14
|
}
|
|
17
15
|
|
|
18
|
-
const
|
|
16
|
+
const RemainingTilesModal: FunctionComponent<Props> = ({ className, isOpen, onClose }) => {
|
|
19
17
|
const translate = useTranslate();
|
|
20
18
|
const locale = useTypedSelector(selectLocale);
|
|
21
19
|
const groups = useTypedSelector(selectRemainingTilesGroups);
|
|
22
20
|
const { direction } = LOCALE_FEATURES[locale];
|
|
23
21
|
|
|
24
22
|
return (
|
|
25
|
-
<
|
|
23
|
+
<Modal className={className} isOpen={isOpen} title={translate('remaining-tiles')} onClose={onClose}>
|
|
26
24
|
{groups.map(({ remainingCount, tiles, translationKey, totalCount }) => {
|
|
27
25
|
const current = direction === 'ltr' ? remainingCount : totalCount;
|
|
28
26
|
const total = direction === 'ltr' ? totalCount : remainingCount;
|
|
29
27
|
|
|
30
28
|
return (
|
|
31
|
-
<
|
|
29
|
+
<Modal.Section
|
|
32
30
|
key={translationKey}
|
|
33
31
|
title={
|
|
34
32
|
<span className={styles.title}>
|
|
@@ -41,14 +39,18 @@ const RemainingTiles: FunctionComponent<Props> = ({ className, isOpen, onClose }
|
|
|
41
39
|
>
|
|
42
40
|
<div className={styles.content}>
|
|
43
41
|
{tiles.map((tile) => {
|
|
44
|
-
return
|
|
42
|
+
return (
|
|
43
|
+
<div className={styles.character} key={tile.character}>
|
|
44
|
+
<Character tile={tile} />
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
45
47
|
})}
|
|
46
48
|
</div>
|
|
47
|
-
</
|
|
49
|
+
</Modal.Section>
|
|
48
50
|
);
|
|
49
51
|
})}
|
|
50
|
-
</
|
|
52
|
+
</Modal>
|
|
51
53
|
);
|
|
52
54
|
};
|
|
53
55
|
|
|
54
|
-
export default
|
|
56
|
+
export default RemainingTilesModal;
|
|
@@ -2,13 +2,12 @@ import { BLANK } from '@scrabble-solver/constants';
|
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import { FunctionComponent } from 'react';
|
|
4
4
|
|
|
5
|
+
import { Progress, Tile } from 'components';
|
|
5
6
|
import { LOCALE_FEATURES } from 'i18n';
|
|
6
7
|
import { REMAINING_TILES_TILE_SIZE } from 'parameters';
|
|
7
8
|
import { selectCharacterPoints, selectLocale, useTypedSelector } from 'state';
|
|
8
9
|
import { RemainingTile } from 'types';
|
|
9
10
|
|
|
10
|
-
import Tile from '../Tile';
|
|
11
|
-
|
|
12
11
|
import styles from './Character.module.scss';
|
|
13
12
|
|
|
14
13
|
interface Props {
|
|
@@ -30,7 +29,6 @@ const Character: FunctionComponent<Props> = ({ tile }) => {
|
|
|
30
29
|
[styles.finished]: remainingCount <= 0,
|
|
31
30
|
[styles.overused]: remainingCount < 0,
|
|
32
31
|
})}
|
|
33
|
-
key={character}
|
|
34
32
|
>
|
|
35
33
|
<Tile
|
|
36
34
|
character={character}
|
|
@@ -42,6 +40,16 @@ const Character: FunctionComponent<Props> = ({ tile }) => {
|
|
|
42
40
|
raised
|
|
43
41
|
size={REMAINING_TILES_TILE_SIZE}
|
|
44
42
|
/>
|
|
43
|
+
|
|
44
|
+
<Progress
|
|
45
|
+
className={styles.remaining}
|
|
46
|
+
max={count}
|
|
47
|
+
style={{
|
|
48
|
+
width: REMAINING_TILES_TILE_SIZE,
|
|
49
|
+
}}
|
|
50
|
+
value={remainingCount}
|
|
51
|
+
/>
|
|
52
|
+
|
|
45
53
|
<div className={styles.count}>
|
|
46
54
|
{current.toLocaleString(locale)} / {total.toLocaleString(locale)}
|
|
47
55
|
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './Character';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Character } from './Character';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './RemainingTilesModal';
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Result } from '@scrabble-solver/types';
|
|
2
|
+
import { FunctionComponent, useMemo } from 'react';
|
|
3
|
+
import { useDispatch } from 'react-redux';
|
|
4
|
+
import { useMeasure } from 'react-use';
|
|
5
|
+
|
|
6
|
+
import { Modal, Results, Sizer, Well } from 'components';
|
|
7
|
+
import { useMediaQuery } from 'hooks';
|
|
8
|
+
import {
|
|
9
|
+
resultsSlice,
|
|
10
|
+
selectResultCandidate,
|
|
11
|
+
selectSortedFilteredResults,
|
|
12
|
+
useTranslate,
|
|
13
|
+
useTypedSelector,
|
|
14
|
+
} from 'state';
|
|
15
|
+
|
|
16
|
+
import styles from './ResultsModal.module.scss';
|
|
17
|
+
|
|
18
|
+
interface Props {
|
|
19
|
+
className?: string;
|
|
20
|
+
isOpen: boolean;
|
|
21
|
+
onClose: () => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const ResultsModal: FunctionComponent<Props> = ({ className, isOpen, onClose }) => {
|
|
25
|
+
const dispatch = useDispatch();
|
|
26
|
+
const translate = useTranslate();
|
|
27
|
+
const [sizerRef, { height, width }] = useMeasure<HTMLDivElement>();
|
|
28
|
+
const isLessThanM = useMediaQuery('<m');
|
|
29
|
+
const results = useTypedSelector(selectSortedFilteredResults);
|
|
30
|
+
const resultCandidate = useTypedSelector(selectResultCandidate);
|
|
31
|
+
const index = (results || []).findIndex((result) => result.id === resultCandidate?.id);
|
|
32
|
+
const highlightedIndex = index === -1 ? undefined : index;
|
|
33
|
+
|
|
34
|
+
const callbacks = useMemo(
|
|
35
|
+
() => ({
|
|
36
|
+
onClick: (result: Result) => {
|
|
37
|
+
dispatch(resultsSlice.actions.changeResultCandidate(result));
|
|
38
|
+
|
|
39
|
+
if (isLessThanM) {
|
|
40
|
+
onClose();
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
}),
|
|
44
|
+
[dispatch, isLessThanM, onClose],
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Modal className={className} isOpen={isOpen} title={translate('results')} onClose={onClose}>
|
|
49
|
+
<Well className={styles.content}>
|
|
50
|
+
<Sizer ref={sizerRef} />
|
|
51
|
+
|
|
52
|
+
<Results callbacks={callbacks} height={height} highlightedIndex={highlightedIndex} width={width} />
|
|
53
|
+
</Well>
|
|
54
|
+
</Modal>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export default ResultsModal;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './ResultsModal';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { FunctionComponent } from 'react';
|
|
2
|
+
|
|
3
|
+
import { Modal } from 'components';
|
|
4
|
+
import { useTranslate } from 'state';
|
|
5
|
+
|
|
6
|
+
import { AutoGroupTilesSetting, ConfigSetting, LocaleSetting } from './components';
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
className?: string;
|
|
10
|
+
isOpen: boolean;
|
|
11
|
+
onClose: () => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const SettingsModal: FunctionComponent<Props> = ({ className, isOpen, onClose }) => {
|
|
15
|
+
const translate = useTranslate();
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Modal className={className} isOpen={isOpen} title={translate('settings')} onClose={onClose}>
|
|
19
|
+
<Modal.Section title={translate('settings.game')}>
|
|
20
|
+
<ConfigSetting disabled={!isOpen} />
|
|
21
|
+
</Modal.Section>
|
|
22
|
+
|
|
23
|
+
<Modal.Section title={translate('settings.language')}>
|
|
24
|
+
<LocaleSetting disabled={!isOpen} />
|
|
25
|
+
</Modal.Section>
|
|
26
|
+
|
|
27
|
+
<Modal.Section title={translate('settings.autoGroupTiles')}>
|
|
28
|
+
<AutoGroupTilesSetting disabled={!isOpen} />
|
|
29
|
+
</Modal.Section>
|
|
30
|
+
</Modal>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export default SettingsModal;
|
|
File without changes
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { ChangeEvent, FunctionComponent } from 'react';
|
|
2
2
|
import { useDispatch } from 'react-redux';
|
|
3
3
|
|
|
4
|
+
import { Radio } from 'components';
|
|
4
5
|
import { selectAutoGroupTiles, settingsSlice, useTranslate, useTypedSelector } from 'state';
|
|
5
6
|
|
|
6
|
-
import Radio from '../../../Radio';
|
|
7
|
-
|
|
8
7
|
import styles from './AutoGroupTilesSetting.module.scss';
|
|
9
8
|
import { NULL_VALUE } from './constants';
|
|
10
9
|
import { parseValue } from './lib';
|
|
File without changes
|
package/src/{components/Settings → modals/SettingsModal}/components/AutoGroupTilesSetting/index.ts
RENAMED
|
File without changes
|
package/src/{components/Settings → modals/SettingsModal}/components/AutoGroupTilesSetting/lib.ts
RENAMED
|
File without changes
|
|
File without changes
|
package/src/{components/Settings → modals/SettingsModal}/components/ConfigSetting/ConfigSetting.tsx
RENAMED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { ChangeEvent, FunctionComponent } from 'react';
|
|
2
2
|
import { useDispatch } from 'react-redux';
|
|
3
3
|
|
|
4
|
+
import { Radio } from 'components';
|
|
4
5
|
import { selectConfigId, settingsSlice, useTypedSelector } from 'state';
|
|
5
6
|
|
|
6
|
-
import Radio from '../../../Radio';
|
|
7
|
-
|
|
8
7
|
import styles from './ConfigSetting.module.scss';
|
|
9
8
|
import options from './options';
|
|
10
9
|
|
|
File without changes
|
package/src/{components/Settings → modals/SettingsModal}/components/ConfigSetting/options.ts
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/src/{components/Settings → modals/SettingsModal}/components/LocaleSetting/LocaleSetting.tsx
RENAMED
|
@@ -3,10 +3,9 @@ import classNames from 'classnames';
|
|
|
3
3
|
import { ChangeEvent, FunctionComponent } from 'react';
|
|
4
4
|
import { useDispatch } from 'react-redux';
|
|
5
5
|
|
|
6
|
+
import { Radio } from 'components';
|
|
6
7
|
import { selectLocale, settingsSlice, useTypedSelector } from 'state';
|
|
7
8
|
|
|
8
|
-
import Radio from '../../../Radio';
|
|
9
|
-
|
|
10
9
|
import styles from './LocaleSetting.module.scss';
|
|
11
10
|
import options from './options';
|
|
12
11
|
|
|
File without changes
|
package/src/{components/Settings → modals/SettingsModal}/components/LocaleSetting/options.ts
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './SettingsModal';
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import classNames from 'classnames';
|
|
2
2
|
import { FunctionComponent } from 'react';
|
|
3
3
|
|
|
4
|
+
import { Badge, Modal } from 'components';
|
|
4
5
|
import { Check, Cross } from 'icons';
|
|
5
6
|
import { selectLocale, selectVerify, useTranslate, useTypedSelector } from 'state';
|
|
6
7
|
|
|
7
|
-
import
|
|
8
|
-
import Sidebar from '../Sidebar';
|
|
9
|
-
|
|
10
|
-
import styles from './Words.module.scss';
|
|
8
|
+
import styles from './WordsModal.module.scss';
|
|
11
9
|
|
|
12
10
|
interface Props {
|
|
13
11
|
className?: string;
|
|
@@ -15,14 +13,14 @@ interface Props {
|
|
|
15
13
|
onClose: () => void;
|
|
16
14
|
}
|
|
17
15
|
|
|
18
|
-
const
|
|
16
|
+
const WordsModal: FunctionComponent<Props> = ({ className, isOpen, onClose }) => {
|
|
19
17
|
const translate = useTranslate();
|
|
20
18
|
const locale = useTypedSelector(selectLocale);
|
|
21
19
|
const { invalidWords, validWords } = useTypedSelector(selectVerify);
|
|
22
20
|
|
|
23
21
|
return (
|
|
24
|
-
<
|
|
25
|
-
<
|
|
22
|
+
<Modal className={className} isOpen={isOpen} title={translate('words')} onClose={onClose}>
|
|
23
|
+
<Modal.Section
|
|
26
24
|
title={
|
|
27
25
|
<span className={styles.title}>
|
|
28
26
|
<span>{translate('words.invalid')}</span>
|
|
@@ -35,9 +33,9 @@ const Words: FunctionComponent<Props> = ({ className, isOpen, onClose }) => {
|
|
|
35
33
|
<Cross className={classNames(styles.icon, styles.invalid)} /> {word}
|
|
36
34
|
</div>
|
|
37
35
|
))}
|
|
38
|
-
</
|
|
36
|
+
</Modal.Section>
|
|
39
37
|
|
|
40
|
-
<
|
|
38
|
+
<Modal.Section
|
|
41
39
|
title={
|
|
42
40
|
<span className={styles.title}>
|
|
43
41
|
<span>{translate('words.valid')}</span>
|
|
@@ -50,9 +48,9 @@ const Words: FunctionComponent<Props> = ({ className, isOpen, onClose }) => {
|
|
|
50
48
|
<Check className={classNames(styles.icon, styles.valid)} /> {word}
|
|
51
49
|
</div>
|
|
52
50
|
))}
|
|
53
|
-
</
|
|
54
|
-
</
|
|
51
|
+
</Modal.Section>
|
|
52
|
+
</Modal>
|
|
55
53
|
);
|
|
56
54
|
};
|
|
57
55
|
|
|
58
|
-
export default
|
|
56
|
+
export default WordsModal;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './WordsModal';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { default as KeyMapModal } from './KeyMapModal';
|
|
2
|
+
export { default as MenuModal } from './MenuModal';
|
|
3
|
+
export { default as RemainingTilesModal } from './RemainingTilesModal';
|
|
4
|
+
export { default as ResultsModal } from './ResultsModal';
|
|
5
|
+
export { default as SettingsModal } from './SettingsModal';
|
|
6
|
+
export { default as WordsModal } from './WordsModal';
|
|
@@ -12,7 +12,8 @@ interface RequestData {
|
|
|
12
12
|
words: string[];
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
const
|
|
15
|
+
const MAXIMUM_COLLISIONS_COUNT = scrabble['en-US'].maximumCharactersCount;
|
|
16
|
+
const MAXIMUM_WORDS_COUNT = MAXIMUM_COLLISIONS_COUNT + 1;
|
|
16
17
|
|
|
17
18
|
const dictionary = async (request: NextApiRequest, response: NextApiResponse): Promise<void> => {
|
|
18
19
|
const meta = getServerLoggingData(request);
|
|
@@ -4,10 +4,8 @@
|
|
|
4
4
|
display: flex;
|
|
5
5
|
flex-direction: column;
|
|
6
6
|
height: 100%;
|
|
7
|
-
min-width: 900px;
|
|
8
|
-
min-height: 700px;
|
|
9
7
|
opacity: 0;
|
|
10
|
-
overflow:
|
|
8
|
+
overflow: auto;
|
|
11
9
|
transition: var(--transition);
|
|
12
10
|
transition-duration: var(--transition--duration--long);
|
|
13
11
|
|
|
@@ -20,6 +18,10 @@
|
|
|
20
18
|
position: relative;
|
|
21
19
|
z-index: 1;
|
|
22
20
|
flex: 0 0 auto;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.navContent {
|
|
24
|
+
width: 100%;
|
|
23
25
|
display: flex;
|
|
24
26
|
align-items: flex-start;
|
|
25
27
|
padding: var(--spacing--l);
|
|
@@ -38,7 +40,7 @@
|
|
|
38
40
|
height: 60px;
|
|
39
41
|
user-select: none;
|
|
40
42
|
|
|
41
|
-
@include
|
|
43
|
+
@include media('<l') {
|
|
42
44
|
height: 48px;
|
|
43
45
|
}
|
|
44
46
|
}
|
package/src/pages/index.tsx
CHANGED
|
@@ -2,33 +2,42 @@ import classNames from 'classnames';
|
|
|
2
2
|
import fs from 'fs';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { AnimationEvent, FunctionComponent, useEffect, useState } from 'react';
|
|
5
|
-
import
|
|
5
|
+
import ReactModal from 'react-modal';
|
|
6
6
|
import { useDispatch } from 'react-redux';
|
|
7
|
-
import { useEffectOnce } from 'react-use';
|
|
7
|
+
import { useEffectOnce, useMeasure } from 'react-use';
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
import { useDirection, useLanguage, useLocalStorage } from 'hooks';
|
|
9
|
+
import { Logo, LogoSplashScreen, NavButtons, Solver, SvgFontFix } from 'components';
|
|
10
|
+
import { useDirection, useLanguage, useLocalStorage, useMediaQuery } from 'hooks';
|
|
11
11
|
import { LOCALE_FEATURES } from 'i18n';
|
|
12
|
+
import { KeyMapModal, MenuModal, RemainingTilesModal, ResultsModal, SettingsModal, WordsModal } from 'modals';
|
|
12
13
|
import { INITIALIZATION_DURATION } from 'parameters';
|
|
13
14
|
import { registerServiceWorker } from 'serviceWorkerManager';
|
|
14
15
|
import { initialize, localStorage, reset, selectLocale, useTypedSelector } from 'state';
|
|
15
16
|
|
|
16
17
|
import styles from './index.module.scss';
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
ReactModal.setAppElement('#__next');
|
|
19
20
|
|
|
20
21
|
interface Props {
|
|
21
22
|
version: string;
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
// eslint-disable-next-line max-statements
|
|
24
26
|
const Index: FunctionComponent<Props> = ({ version }) => {
|
|
25
27
|
const dispatch = useDispatch();
|
|
26
28
|
const locale = useTypedSelector(selectLocale);
|
|
29
|
+
const isLessThanL = useMediaQuery('<l');
|
|
27
30
|
const [showKeyMap, setShowKeyMap] = useState(false);
|
|
31
|
+
const [showMenu, setShowMenu] = useState(false);
|
|
28
32
|
const [showRemainingTiles, setShowRemainingTiles] = useState(false);
|
|
33
|
+
const [showResults, setShowResults] = useState(false);
|
|
29
34
|
const [showSettings, setShowSettings] = useState(false);
|
|
30
35
|
const [showWords, setShowWords] = useState(false);
|
|
31
36
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
37
|
+
const [indexRef, { height: indexHeight, width: indexWidth }] = useMeasure<HTMLDivElement>();
|
|
38
|
+
const [navRef, { height: navHeight }] = useMeasure<HTMLDivElement>();
|
|
39
|
+
const solverHeight = indexHeight - navHeight;
|
|
40
|
+
const solverWidth = indexWidth;
|
|
32
41
|
|
|
33
42
|
const handleClear = () => {
|
|
34
43
|
dispatch(reset());
|
|
@@ -48,11 +57,17 @@ const Index: FunctionComponent<Props> = ({ version }) => {
|
|
|
48
57
|
useEffectOnce(() => {
|
|
49
58
|
dispatch(initialize());
|
|
50
59
|
|
|
51
|
-
setTimeout(() => {
|
|
60
|
+
globalThis.setTimeout(() => {
|
|
52
61
|
setIsInitialized(true);
|
|
53
62
|
}, INITIALIZATION_DURATION);
|
|
54
63
|
});
|
|
55
64
|
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
if (!isLessThanL) {
|
|
67
|
+
setShowResults(false);
|
|
68
|
+
}
|
|
69
|
+
}, [isLessThanL]);
|
|
70
|
+
|
|
56
71
|
useEffect(() => {
|
|
57
72
|
if (process.env.NODE_ENV === 'production') {
|
|
58
73
|
registerServiceWorker();
|
|
@@ -63,31 +78,53 @@ const Index: FunctionComponent<Props> = ({ version }) => {
|
|
|
63
78
|
<>
|
|
64
79
|
<SvgFontFix />
|
|
65
80
|
|
|
66
|
-
<div className={classNames(styles.index, { [styles.initialized]: isInitialized })}>
|
|
67
|
-
<div className={styles.nav}>
|
|
68
|
-
<div className={styles.
|
|
69
|
-
<
|
|
70
|
-
<
|
|
71
|
-
|
|
81
|
+
<div className={classNames(styles.index, { [styles.initialized]: isInitialized })} ref={indexRef}>
|
|
82
|
+
<div className={styles.nav} ref={navRef}>
|
|
83
|
+
<div className={styles.navContent}>
|
|
84
|
+
<div className={styles.navLogo}>
|
|
85
|
+
<a className={styles.logoContainer} href="/" title={version}>
|
|
86
|
+
<Logo className={styles.logo} />
|
|
87
|
+
</a>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<NavButtons
|
|
91
|
+
onClear={handleClear}
|
|
92
|
+
onShowKeyMap={() => setShowKeyMap(true)}
|
|
93
|
+
onShowMenu={() => setShowMenu(true)}
|
|
94
|
+
onShowRemainingTiles={() => setShowRemainingTiles(true)}
|
|
95
|
+
onShowSettings={() => setShowSettings(true)}
|
|
96
|
+
onShowWords={() => setShowWords(true)}
|
|
97
|
+
/>
|
|
72
98
|
</div>
|
|
73
|
-
|
|
74
|
-
<NavButtons
|
|
75
|
-
onClear={handleClear}
|
|
76
|
-
onShowKeyMap={() => setShowKeyMap(true)}
|
|
77
|
-
onShowRemainingTiles={() => setShowRemainingTiles(true)}
|
|
78
|
-
onShowSettings={() => setShowSettings(true)}
|
|
79
|
-
onShowWords={() => setShowWords(true)}
|
|
80
|
-
/>
|
|
81
99
|
</div>
|
|
82
100
|
|
|
83
|
-
<Solver
|
|
101
|
+
<Solver
|
|
102
|
+
className={styles.solver}
|
|
103
|
+
height={solverHeight}
|
|
104
|
+
width={solverWidth}
|
|
105
|
+
onShowResults={() => setShowResults(true)}
|
|
106
|
+
/>
|
|
84
107
|
</div>
|
|
85
108
|
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
109
|
+
<MenuModal
|
|
110
|
+
isOpen={showMenu}
|
|
111
|
+
onClose={() => setShowMenu(false)}
|
|
112
|
+
onShowRemainingTiles={() => setShowRemainingTiles(true)}
|
|
113
|
+
onShowSettings={() => setShowSettings(true)}
|
|
114
|
+
onShowWords={() => setShowWords(true)}
|
|
115
|
+
/>
|
|
116
|
+
|
|
117
|
+
<SettingsModal isOpen={showSettings} onClose={() => setShowSettings(false)} />
|
|
118
|
+
|
|
119
|
+
<KeyMapModal isOpen={showKeyMap} onClose={() => setShowKeyMap(false)} />
|
|
120
|
+
|
|
121
|
+
<WordsModal isOpen={showWords} onClose={() => setShowWords(false)} />
|
|
122
|
+
|
|
123
|
+
<RemainingTilesModal isOpen={showRemainingTiles} onClose={() => setShowRemainingTiles(false)} />
|
|
124
|
+
|
|
125
|
+
<ResultsModal isOpen={showResults} onClose={() => setShowResults(false)} />
|
|
126
|
+
|
|
127
|
+
<LogoSplashScreen forceShow={!isInitialized} onAnimationEnd={handleSplashAnimationEnd} />
|
|
91
128
|
</>
|
|
92
129
|
);
|
|
93
130
|
};
|
package/src/parameters/index.ts
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
export const BREAKPOINTS = {
|
|
2
|
+
xs: 480,
|
|
3
|
+
s: 768,
|
|
4
|
+
m: 992,
|
|
5
|
+
l: 1200,
|
|
6
|
+
xl: 1400,
|
|
7
|
+
};
|
|
8
|
+
|
|
1
9
|
export const GITHUB_PROJECT_URL = 'https://github.com/kamilmielnik/scrabble-solver';
|
|
2
10
|
|
|
3
11
|
export const INITIALIZATION_DURATION = 100;
|
|
@@ -11,15 +19,24 @@ export const COLOR_RED = '#f7c2aa';
|
|
|
11
19
|
export const COLOR_YELLOW = '#efe3ae';
|
|
12
20
|
|
|
13
21
|
export const COMPONENTS_SPACING = 40;
|
|
14
|
-
export const
|
|
22
|
+
export const COMPONENTS_SPACING_SMALL = 20;
|
|
15
23
|
|
|
16
24
|
export const BOARD_CELL_BORDER_WIDTH = 1;
|
|
17
25
|
export const BOARD_TILE_FONT_SIZE_MIN = 14;
|
|
18
26
|
export const BOARD_TILE_FONT_SIZE_POINTS_MIN = 10;
|
|
19
27
|
export const BOARD_TILE_SIZE_MAX = 64;
|
|
20
|
-
|
|
28
|
+
/**
|
|
29
|
+
* 20 - fits all board tiles without horizontal scrollbar on 360px viewport width (font-size: 14px)
|
|
30
|
+
* 21 - fits all board tiles without horizontal scrollbar on 375px viewport width (font-size: 14px)
|
|
31
|
+
* 26 - tiles start to look good (font-size: 16px)
|
|
32
|
+
*/
|
|
33
|
+
export const BOARD_TILE_SIZE_MIN = 20;
|
|
34
|
+
|
|
35
|
+
export const BORDER_WIDTH = 1;
|
|
21
36
|
|
|
22
|
-
export const
|
|
37
|
+
export const COLUMN_MIN_HEIGHT = 588.5;
|
|
38
|
+
|
|
39
|
+
export const DICTIONARY_HEIGHT = 260;
|
|
23
40
|
|
|
24
41
|
export const TILE_SIZE = 80;
|
|
25
42
|
|
|
@@ -45,8 +62,13 @@ export const PLAIN_TILES_TILE_SIZE = 80;
|
|
|
45
62
|
export const PLAIN_TILES_VERSION_TILE_COLOR = COLOR_GREEN;
|
|
46
63
|
export const PLAIN_TILES_VERSION_TILE_SIZE = TILE_SIZE;
|
|
47
64
|
|
|
65
|
+
export const PROGRESS_COLOR_VALUE = 'var(--color--violet--light)';
|
|
66
|
+
export const PROGRESS_COLOR_BACKGROUND = 'var(--color--inactive)';
|
|
67
|
+
|
|
68
|
+
export const RACK_TILE_SIZE_MAX = 80;
|
|
69
|
+
|
|
48
70
|
export const REMAINING_TILES_TILE_SIZE = 50;
|
|
49
71
|
|
|
50
|
-
export const RESULTS_HEADER_HEIGHT =
|
|
51
|
-
export const RESULTS_ITEM_HEIGHT =
|
|
52
|
-
export const RESULTS_INPUT_HEIGHT =
|
|
72
|
+
export const RESULTS_HEADER_HEIGHT = 34;
|
|
73
|
+
export const RESULTS_ITEM_HEIGHT = 40;
|
|
74
|
+
export const RESULTS_INPUT_HEIGHT = 40;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { applyMiddleware, compose, createStore } from 'redux';
|
|
2
2
|
import reduxSaga from 'redux-saga';
|
|
3
3
|
|
|
4
4
|
import rootReducer from './rootReducer';
|
|
@@ -8,12 +8,15 @@ import { RootState } from './types';
|
|
|
8
8
|
const sagaMiddleware = reduxSaga();
|
|
9
9
|
const initialState: Partial<RootState> | undefined = undefined;
|
|
10
10
|
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
12
|
+
// @ts-ignore
|
|
13
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
14
|
+
const composeEnhancers = globalThis.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
|
|
15
|
+
|
|
11
16
|
const createAppStore = (): ReturnType<typeof createStore> => {
|
|
12
|
-
const store = createStore(rootReducer, initialState,
|
|
17
|
+
const store = createStore(rootReducer, initialState, composeEnhancers(applyMiddleware(sagaMiddleware)));
|
|
13
18
|
sagaMiddleware.run(rootSaga);
|
|
14
19
|
return store;
|
|
15
20
|
};
|
|
16
21
|
|
|
17
|
-
const createEnhancer = () => applyMiddleware(sagaMiddleware);
|
|
18
|
-
|
|
19
22
|
export default createAppStore;
|