@scrabble-solver/scrabble-solver 2.9.0 → 2.9.2

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.
Files changed (61) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +8 -8
  3. package/.next/cache/.tsbuildinfo +1 -1
  4. package/.next/cache/eslint/.cache_8dgz12 +1 -1
  5. package/.next/cache/next-server.js.nft.json +1 -1
  6. package/.next/cache/webpack/client-production/0.pack +0 -0
  7. package/.next/cache/webpack/client-production/index.pack +0 -0
  8. package/.next/cache/webpack/edge-server-production/0.pack +0 -0
  9. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  10. package/.next/cache/webpack/server-production/0.pack +0 -0
  11. package/.next/cache/webpack/server-production/index.pack +0 -0
  12. package/.next/next-server.js.nft.json +1 -1
  13. package/.next/prerender-manifest.json +1 -1
  14. package/.next/required-server-files.json +1 -1
  15. package/.next/routes-manifest.json +1 -1
  16. package/.next/server/chunks/413.js +7 -3
  17. package/.next/server/chunks/44.js +895 -4
  18. package/.next/server/chunks/515.js +15 -6
  19. package/.next/server/chunks/865.js +230 -116
  20. package/.next/server/middleware-build-manifest.js +1 -1
  21. package/.next/server/pages/404.html +2 -2
  22. package/.next/server/pages/404.js.nft.json +1 -1
  23. package/.next/server/pages/500.html +2 -2
  24. package/.next/server/pages/_app.js.nft.json +1 -1
  25. package/.next/server/pages/_error.js.nft.json +1 -1
  26. package/.next/server/pages/api/dictionary/[locale]/[word].js +121 -65
  27. package/.next/server/pages/api/dictionary/[locale]/[word].js.nft.json +1 -1
  28. package/.next/server/pages/api/dictionary/[locale].js +1 -1
  29. package/.next/server/pages/api/dictionary/[locale].js.nft.json +1 -1
  30. package/.next/server/pages/api/solve.js +1 -1
  31. package/.next/server/pages/api/solve.js.nft.json +1 -1
  32. package/.next/server/pages/api/verify.js +1 -1
  33. package/.next/server/pages/api/verify.js.nft.json +1 -1
  34. package/.next/server/pages/index.html +2 -2
  35. package/.next/server/pages/index.js +5 -1
  36. package/.next/server/pages/index.js.nft.json +1 -1
  37. package/.next/server/pages/index.json +1 -1
  38. package/.next/static/{BiJ0RS1mh1CdONVQg_p20 → Ntg-ilwD7GqTIFwRpSaTQ}/_buildManifest.js +1 -1
  39. package/.next/static/{BiJ0RS1mh1CdONVQg_p20 → Ntg-ilwD7GqTIFwRpSaTQ}/_ssgManifest.js +0 -0
  40. package/.next/static/chunks/317-5e5334962dd7c681.js +1 -0
  41. package/.next/static/chunks/pages/{_app-1878e12521f2d115.js → _app-183f598b1d4d480b.js} +1 -1
  42. package/.next/static/chunks/pages/{index-14d33636a0746c22.js → index-b1ffeaddd9fb64b5.js} +1 -1
  43. package/.next/static/css/e8de67ad5ea35427.css +1 -0
  44. package/.next/trace +52 -52
  45. package/LICENSE +1 -1
  46. package/package.json +11 -11
  47. package/src/components/Board/BoardPure.tsx +2 -7
  48. package/src/components/Board/components/Cell/Cell.module.scss +1 -1
  49. package/src/components/Board/components/Cell/Cell.tsx +4 -1
  50. package/src/components/Board/components/Cell/CellPure.tsx +12 -1
  51. package/src/components/Dictionary/Dictionary.module.scss +1 -0
  52. package/src/components/Dictionary/Dictionary.tsx +7 -2
  53. package/src/components/Splash/Splash.module.scss +1 -1
  54. package/src/i18n/en.json +2 -2
  55. package/src/pages/api/dictionary/[locale]/[word].ts +3 -1
  56. package/src/pages/index.tsx +6 -1
  57. package/src/service-worker/dictionaries/constants.ts +3 -1
  58. package/.next/server/chunks/452.js +0 -894
  59. package/.next/static/chunks/317-c5d262202c17d519.js +0 -1
  60. package/.next/static/css/9ac903004135f4b1.css +0 -1
  61. package/public/robots.txt +0 -4
package/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2021 Kamil Mielnik <kamil.adam.mielnik@gmail.com>
1
+ Copyright (c) 2022 Kamil Mielnik <kamil@kamilmielnik.com>
2
2
 
3
3
  Attribution-NonCommercial-NoDerivatives 4.0 International
4
4
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrabble-solver/scrabble-solver",
3
- "version": "2.9.0",
3
+ "version": "2.9.2",
4
4
  "description": "Scrabble Solver 2 - App",
5
5
  "engines": {
6
6
  "node": ">=16"
@@ -11,8 +11,8 @@
11
11
  },
12
12
  "author": {
13
13
  "name": "Kamil Mielnik",
14
- "email": "kamil.adam.mielnik@gmail.com",
15
- "url": "https://kamilmielnik.com/"
14
+ "email": "kamil@kamilmielnik.com",
15
+ "url": "https://kamilmielnik.com"
16
16
  },
17
17
  "license": "CC BY-NC-ND 4.0",
18
18
  "bugs": {
@@ -31,13 +31,13 @@
31
31
  "@kamilmielnik/trie": "^2.0.1",
32
32
  "@popperjs/core": "^2.11.6",
33
33
  "@reduxjs/toolkit": "^1.8.6",
34
- "@scrabble-solver/configs": "^2.9.0",
35
- "@scrabble-solver/constants": "^2.9.0",
36
- "@scrabble-solver/dictionaries": "^2.9.0",
37
- "@scrabble-solver/logger": "^2.9.0",
38
- "@scrabble-solver/solver": "^2.9.0",
39
- "@scrabble-solver/types": "^2.9.0",
40
- "@scrabble-solver/word-definitions": "^2.9.0",
34
+ "@scrabble-solver/configs": "^2.9.2",
35
+ "@scrabble-solver/constants": "^2.9.2",
36
+ "@scrabble-solver/dictionaries": "^2.9.2",
37
+ "@scrabble-solver/logger": "^2.9.2",
38
+ "@scrabble-solver/solver": "^2.9.2",
39
+ "@scrabble-solver/types": "^2.9.2",
40
+ "@scrabble-solver/word-definitions": "^2.9.2",
41
41
  "classnames": "^2.3.2",
42
42
  "next": "^12.3.1",
43
43
  "normalize.css": "^8.0.1",
@@ -74,5 +74,5 @@
74
74
  "sass": "^1.55.0",
75
75
  "workbox-webpack-plugin": "^6.5.4"
76
76
  },
77
- "gitHead": "f100d9d52460a68f1fb5a1059cd335029d5e46a8"
77
+ "gitHead": "f50d782088cb89544f0c2c504f31fca81a6ff409"
78
78
  }
@@ -44,13 +44,7 @@ const BoardPure: FunctionComponent<Props> = ({
44
44
  onKeyDown,
45
45
  onPaste,
46
46
  }) => (
47
- <div
48
- className={classNames(styles.board, className)}
49
- ref={innerRef}
50
- onChange={onChange}
51
- onKeyDown={onKeyDown}
52
- onPaste={onPaste}
53
- >
47
+ <div className={classNames(styles.board, className)} ref={innerRef} onKeyDown={onKeyDown} onPaste={onPaste}>
54
48
  {rows.map((cells, y) => (
55
49
  <div className={styles.row} key={y}>
56
50
  {cells.map((cell, x) => (
@@ -62,6 +56,7 @@ const BoardPure: FunctionComponent<Props> = ({
62
56
  isCenter={center.x === x && center.y === y}
63
57
  key={x}
64
58
  size={cellSize}
59
+ onChange={onChange}
65
60
  onDirectionToggle={onDirectionToggle}
66
61
  onFocus={onFocus}
67
62
  />
@@ -213,7 +213,7 @@ $icon-size: 16px;
213
213
 
214
214
  .flag,
215
215
  .star {
216
- $size: 24px;
216
+ $size: 50%;
217
217
 
218
218
  width: $size;
219
219
  height: $size;
@@ -1,6 +1,6 @@
1
1
  import { EMPTY_CELL } from '@scrabble-solver/constants';
2
2
  import { Cell as CellModel } from '@scrabble-solver/types';
3
- import { FunctionComponent, RefObject, useCallback, useMemo } from 'react';
3
+ import { ChangeEventHandler, FunctionComponent, RefObject, useCallback, useMemo } from 'react';
4
4
  import { useDispatch } from 'react-redux';
5
5
 
6
6
  import { getTileSizes } from 'lib';
@@ -23,6 +23,7 @@ interface Props {
23
23
  inputRef: RefObject<HTMLInputElement>;
24
24
  isCenter: boolean;
25
25
  size: number;
26
+ onChange: ChangeEventHandler<HTMLInputElement>;
26
27
  onDirectionToggle: () => void;
27
28
  onFocus: (x: number, y: number) => void;
28
29
  }
@@ -34,6 +35,7 @@ const Cell: FunctionComponent<Props> = ({
34
35
  inputRef,
35
36
  isCenter,
36
37
  size,
38
+ onChange,
37
39
  onDirectionToggle,
38
40
  onFocus,
39
41
  }) => {
@@ -88,6 +90,7 @@ const Cell: FunctionComponent<Props> = ({
88
90
  style={style}
89
91
  tile={tile}
90
92
  translate={translate}
93
+ onChange={onChange}
91
94
  onDirectionToggleClick={handleDirectionToggleClick}
92
95
  onFocus={handleFocus}
93
96
  onToggleBlankClick={handleToggleBlankClick}
@@ -1,6 +1,14 @@
1
1
  import { Bonus, Cell, Tile as TileModel } from '@scrabble-solver/types';
2
2
  import classNames from 'classnames';
3
- import { CSSProperties, FocusEventHandler, FunctionComponent, memo, MouseEventHandler, RefObject } from 'react';
3
+ import {
4
+ ChangeEventHandler,
5
+ CSSProperties,
6
+ FocusEventHandler,
7
+ FunctionComponent,
8
+ memo,
9
+ MouseEventHandler,
10
+ RefObject,
11
+ } from 'react';
4
12
 
5
13
  import { ArrowDown, Flag, Star } from 'icons';
6
14
  import { Translate } from 'types';
@@ -25,6 +33,7 @@ interface Props {
25
33
  style?: CSSProperties;
26
34
  tile: TileModel;
27
35
  translate: Translate;
36
+ onChange: ChangeEventHandler<HTMLInputElement>;
28
37
  onDirectionToggleClick: MouseEventHandler<HTMLButtonElement>;
29
38
  onFocus: FocusEventHandler<HTMLInputElement>;
30
39
  onToggleBlankClick: MouseEventHandler<HTMLButtonElement>;
@@ -45,6 +54,7 @@ const CellPure: FunctionComponent<Props> = ({
45
54
  style,
46
55
  tile,
47
56
  translate,
57
+ onChange,
48
58
  onDirectionToggleClick,
49
59
  onFocus,
50
60
  onToggleBlankClick,
@@ -78,6 +88,7 @@ const CellPure: FunctionComponent<Props> = ({
78
88
  raised={!isEmpty}
79
89
  size={size}
80
90
  tabIndex={cell.x === 0 && cell.y === 0 ? undefined : -1}
91
+ onChange={onChange}
81
92
  onFocus={onFocus}
82
93
  />
83
94
 
@@ -53,6 +53,7 @@
53
53
 
54
54
  .definition {
55
55
  margin-bottom: var(--spacing--s);
56
+ white-space: pre-wrap;
56
57
 
57
58
  &:last-child {
58
59
  margin-bottom: 0;
@@ -31,7 +31,7 @@ const Dictionary: FunctionComponent<Props> = ({ className }) => {
31
31
  </EmptyState>
32
32
  )}
33
33
 
34
- {results.map(({ definitions, isAllowed, word }) => (
34
+ {results.map(({ definitions, exists, isAllowed, word }) => (
35
35
  <div
36
36
  className={classNames(styles.result, {
37
37
  [styles.isAllowed]: isAllowed === true,
@@ -51,7 +51,12 @@ const Dictionary: FunctionComponent<Props> = ({ className }) => {
51
51
 
52
52
  {isAllowed === true && (
53
53
  <>
54
- {definitions.length === 0 && <div>{translate('dictionary.empty-state.no-definitions')}</div>}
54
+ {definitions.length === 0 && (
55
+ <>
56
+ {exists && <div>{translate('dictionary.empty-state.no-definitions')}</div>}
57
+ {!exists && <div>{translate('dictionary.empty-state.no-results')}</div>}
58
+ </>
59
+ )}
55
60
 
56
61
  {definitions.length > 0 && (
57
62
  <ul className={styles.definitions}>
@@ -1,6 +1,6 @@
1
1
  @import 'styles/animations';
2
2
 
3
- $loading-duration: 450ms;
3
+ $loading-duration: 250ms;
4
4
  $loaded-duration: 100ms;
5
5
  $hiding-duration: 200ms;
6
6
 
package/src/i18n/en.json CHANGED
@@ -15,9 +15,9 @@
15
15
  "common.word": "Word",
16
16
  "common.words": "Words",
17
17
  "dictionary.empty-state.no-definitions": "Word exists in the dictionary but it does not have a definition.",
18
- "dictionary.empty-state.no-results": "Unable to find word definition in dictionary.",
18
+ "dictionary.empty-state.no-results": "Unable to find word definition in the dictionary.",
19
19
  "dictionary.empty-state.not-allowed": "This word is not allowed.",
20
- "dictionary.empty-state.uninitialized": "Dictionary definition of the last highlighted word will be shown here.",
20
+ "dictionary.empty-state.uninitialized": "Dictionary definition of the most recently highlighted word will be shown here.",
21
21
  "dictionary.input.placeholder": "Search dictionary...",
22
22
  "empty-state.error": "Error",
23
23
  "empty-state.info": "Info",
@@ -1,4 +1,5 @@
1
1
  import { scrabble } from '@scrabble-solver/configs';
2
+ import { dictionaries } from '@scrabble-solver/dictionaries';
2
3
  import logger from '@scrabble-solver/logger';
3
4
  import { isLocale, Locale } from '@scrabble-solver/types';
4
5
  import { getWordDefinition } from '@scrabble-solver/word-definitions';
@@ -27,7 +28,8 @@ const dictionary = async (request: NextApiRequest, response: NextApiResponse): P
27
28
  },
28
29
  });
29
30
 
30
- const results = await Promise.all(words.map((word) => getWordDefinition(locale, word)));
31
+ const trie = await dictionaries.get(locale);
32
+ const results = await Promise.all(words.map((word) => getWordDefinition(locale, word, trie.has(word))));
31
33
  response.status(200).send(results.map((result) => result.toJson()));
32
34
  } catch (error) {
33
35
  const message = error instanceof Error ? error.message : 'Unknown error';
@@ -48,7 +48,8 @@ const Index: FunctionComponent<Props> = ({ version }) => {
48
48
  useMeasure<HTMLDivElement>();
49
49
  const config = useTypedSelector(selectConfig);
50
50
  const cellSize = getCellSize(config, contentWidth - resultsContainerWidth, contentHeight);
51
- const isInitialized = contentWidth > 0 && boardHeight > 0 && resultsContainerWidth > 0;
51
+ const isInitializedInitial = contentWidth > 0 && boardHeight > 0 && resultsContainerWidth > 0;
52
+ const [isInitialized, setIsInitialized] = useState(isInitializedInitial);
52
53
  const resultsHeight = boardHeight - DICTIONARY_HEIGHT - (isTablet ? COMPONENTS_SPACING_MOBILE : COMPONENTS_SPACING);
53
54
 
54
55
  const handleClear = () => {
@@ -71,6 +72,10 @@ const Index: FunctionComponent<Props> = ({ version }) => {
71
72
 
72
73
  useEffectOnce(() => {
73
74
  dispatch(initialize());
75
+
76
+ setTimeout(() => {
77
+ setIsInitialized(true);
78
+ }, 100);
74
79
  });
75
80
 
76
81
  useEffect(() => {
@@ -1,3 +1,5 @@
1
1
  export const DICTIONARY_CACHE = 'dictionary-api-cache';
2
2
 
3
- export const DICTIONARY_CACHE_MAX_AGE = 30 * 24 * 60 * 60 * 1000;
3
+ export const DAY = 24 * 60 * 60 * 1000;
4
+
5
+ export const DICTIONARY_CACHE_MAX_AGE = 1 * DAY; // eslint-disable-line no-implicit-coercion