scrabble-solver 2.15.4 → 2.15.6

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 (90) hide show
  1. package/.nx/workspace-data/file-map.json +1378 -1333
  2. package/.nx/workspace-data/lockfile.hash +1 -1
  3. package/.nx/workspace-data/nx_files.nxt +0 -0
  4. package/.nx/workspace-data/parsed-lock-file.json +289 -278
  5. package/.nx/workspace-data/project-graph.json +270 -288
  6. package/cypress/e2e/bugs/363-dictionary-input-unique-words.ts +41 -0
  7. package/cypress/e2e/bugs.spec.cy.ts +1 -0
  8. package/lerna.json +1 -1
  9. package/package.json +7 -7
  10. package/packages/configs/package.json +3 -3
  11. package/packages/constants/package.json +1 -1
  12. package/packages/dictionaries/package.json +4 -4
  13. package/packages/logger/package.json +2 -2
  14. package/packages/scrabble-solver/.next/BUILD_ID +1 -1
  15. package/packages/scrabble-solver/.next/build-manifest.json +9 -9
  16. package/packages/scrabble-solver/.next/cache/.rscinfo +1 -1
  17. package/packages/scrabble-solver/.next/cache/.tsbuildinfo +1 -1
  18. package/packages/scrabble-solver/.next/cache/eslint/.cache_8dgz12 +1 -1
  19. package/packages/scrabble-solver/.next/cache/webpack/client-production/0.pack +0 -0
  20. package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack +0 -0
  21. package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack.old +0 -0
  22. package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/0.pack +0 -0
  23. package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack +0 -0
  24. package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack.old +0 -0
  25. package/packages/scrabble-solver/.next/cache/webpack/server-production/0.pack +0 -0
  26. package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack +0 -0
  27. package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack.old +0 -0
  28. package/packages/scrabble-solver/.next/diagnostics/framework.json +1 -1
  29. package/packages/scrabble-solver/.next/next-minimal-server.js.nft.json +1 -1
  30. package/packages/scrabble-solver/.next/next-server.js.nft.json +1 -1
  31. package/packages/scrabble-solver/.next/prerender-manifest.json +1 -1
  32. package/packages/scrabble-solver/.next/required-server-files.json +1 -1
  33. package/packages/scrabble-solver/.next/routes-manifest.json +1 -1
  34. package/packages/scrabble-solver/.next/server/chunks/{964.js → 292.js} +1 -1
  35. package/packages/scrabble-solver/.next/server/chunks/331.js +2 -2
  36. package/packages/scrabble-solver/.next/server/chunks/577.js +1 -1
  37. package/packages/scrabble-solver/.next/server/chunks/807.js +1 -0
  38. package/packages/scrabble-solver/.next/server/middleware-build-manifest.js +1 -1
  39. package/packages/scrabble-solver/.next/server/pages/404.html +1 -1
  40. package/packages/scrabble-solver/.next/server/pages/404.js.nft.json +1 -1
  41. package/packages/scrabble-solver/.next/server/pages/500.html +1 -1
  42. package/packages/scrabble-solver/.next/server/pages/_app.js +1 -1
  43. package/packages/scrabble-solver/.next/server/pages/_app.js.nft.json +1 -1
  44. package/packages/scrabble-solver/.next/server/pages/_document.js +1 -1
  45. package/packages/scrabble-solver/.next/server/pages/_error.js +1 -1
  46. package/packages/scrabble-solver/.next/server/pages/_error.js.nft.json +1 -1
  47. package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale]/[word].js +2 -2
  48. package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale]/[word].js.nft.json +1 -1
  49. package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale].js +1 -1
  50. package/packages/scrabble-solver/.next/server/pages/api/dictionary/[locale].js.nft.json +1 -1
  51. package/packages/scrabble-solver/.next/server/pages/api/solve.js +1 -1
  52. package/packages/scrabble-solver/.next/server/pages/api/solve.js.nft.json +1 -1
  53. package/packages/scrabble-solver/.next/server/pages/api/verify.js +1 -1
  54. package/packages/scrabble-solver/.next/server/pages/api/verify.js.nft.json +1 -1
  55. package/packages/scrabble-solver/.next/server/pages/api/visit.js +1 -1
  56. package/packages/scrabble-solver/.next/server/pages/index.html +1 -1
  57. package/packages/scrabble-solver/.next/server/pages/index.js +1 -1
  58. package/packages/scrabble-solver/.next/server/pages/index.js.nft.json +1 -1
  59. package/packages/scrabble-solver/.next/server/pages/index.json +1 -1
  60. package/packages/scrabble-solver/.next/server/pages-manifest.json +1 -1
  61. package/packages/scrabble-solver/.next/static/chunks/main-8d63777bf8b90ccb.js +1 -0
  62. package/packages/scrabble-solver/.next/static/chunks/pages/_app-79ef8056607a21da.js +1 -0
  63. package/packages/scrabble-solver/.next/static/chunks/pages/index-5866a12bfb8f00c4.js +1 -0
  64. package/packages/scrabble-solver/.next/static/css/bc158181051cf066.css +2 -0
  65. package/packages/scrabble-solver/.next/static/{ySzTsF3RIcISdWO2C2H3Z → uekKIGQQUe4pM47TO6mBn}/_buildManifest.js +1 -1
  66. package/packages/scrabble-solver/.next/trace +23 -23
  67. package/packages/scrabble-solver/package.json +16 -16
  68. package/packages/scrabble-solver/public/service-worker.js +2 -2
  69. package/packages/scrabble-solver/public/service-worker.js.map +1 -1
  70. package/packages/scrabble-solver/src/components/Board/Board.tsx +1 -0
  71. package/packages/scrabble-solver/src/components/Button/Button.module.scss +16 -1
  72. package/packages/scrabble-solver/src/components/Button/Button.tsx +3 -0
  73. package/packages/scrabble-solver/src/components/Button/Link.tsx +3 -0
  74. package/packages/scrabble-solver/src/components/Dictionary/Dictionary.module.scss +9 -1
  75. package/packages/scrabble-solver/src/components/Dictionary/Dictionary.tsx +3 -0
  76. package/packages/scrabble-solver/src/components/Radio/Radio.module.scss +14 -20
  77. package/packages/scrabble-solver/src/components/Radio/Radio.tsx +3 -1
  78. package/packages/scrabble-solver/src/hooks/useAppLayout.ts +3 -0
  79. package/packages/scrabble-solver/src/modals/MenuModal/MenuModal.tsx +11 -3
  80. package/packages/scrabble-solver/src/state/sagas.ts +3 -1
  81. package/packages/solver/package.json +5 -5
  82. package/packages/types/package.json +2 -2
  83. package/packages/word-definitions/package.json +2 -2
  84. package/packages/word-lists/package.json +2 -2
  85. package/packages/scrabble-solver/.next/server/chunks/67.js +0 -1
  86. package/packages/scrabble-solver/.next/static/chunks/main-6e8e32bd2f4e331c.js +0 -1
  87. package/packages/scrabble-solver/.next/static/chunks/pages/_app-fb5bb6aa71eaaa4e.js +0 -1
  88. package/packages/scrabble-solver/.next/static/chunks/pages/index-6ef7d0f12c9321e2.js +0 -1
  89. package/packages/scrabble-solver/.next/static/css/35b36298aba4ccad.css +0 -2
  90. /package/packages/scrabble-solver/.next/static/{ySzTsF3RIcISdWO2C2H3Z → uekKIGQQUe4pM47TO6mBn}/_ssgManifest.js +0 -0
@@ -178,6 +178,7 @@ const Board: FunctionComponent<Props> = ({ className }) => {
178
178
  position: floatingFocus.strategy,
179
179
  top: floatingFocus.y + cellSize,
180
180
  left: floatingFocus.x,
181
+ display: floatingFocus.isPositioned ? 'block' : 'none',
181
182
  width: cellSize,
182
183
  height: cellSize,
183
184
  opacity: hasFocus ? 1 : 0,
@@ -60,8 +60,13 @@
60
60
  .content {
61
61
  display: flex;
62
62
  align-items: center;
63
+ justify-content: center;
63
64
  gap: var(--spacing--l);
64
65
  line-height: var(--button--icon--size);
66
+
67
+ @include media('<l') {
68
+ gap: var(--spacing--m);
69
+ }
65
70
  }
66
71
 
67
72
  .icon {
@@ -74,8 +79,18 @@
74
79
  .label {
75
80
  @include ellipsis;
76
81
 
77
- flex: 1;
78
82
  font-size: var(--font--size--h3);
79
83
  transition: var(--transition);
80
84
  text-align: start;
81
85
  }
86
+
87
+ .wide {
88
+ .content {
89
+ justify-content: normal;
90
+ gap: var(--spacing--l);
91
+ }
92
+
93
+ .label {
94
+ flex: 1;
95
+ }
96
+ }
@@ -12,6 +12,7 @@ interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
12
12
  iconClassName?: string;
13
13
  tooltip?: ReactNode;
14
14
  variant?: 'default' | 'primary';
15
+ wide?: boolean;
15
16
  }
16
17
 
17
18
  const Button: FunctionComponent<Props> = ({
@@ -21,6 +22,7 @@ const Button: FunctionComponent<Props> = ({
21
22
  iconClassName,
22
23
  tooltip,
23
24
  variant = 'default',
25
+ wide,
24
26
  ...props
25
27
  }) => {
26
28
  return (
@@ -29,6 +31,7 @@ const Button: FunctionComponent<Props> = ({
29
31
  className={classNames(styles.button, className, {
30
32
  [styles.default]: variant === 'default',
31
33
  [styles.primary]: variant === 'primary',
34
+ [styles.wide]: wide,
32
35
  })}
33
36
  type="button"
34
37
  {...props}
@@ -12,6 +12,7 @@ interface Props extends AnchorHTMLAttributes<HTMLAnchorElement> {
12
12
  iconClassName?: string;
13
13
  tooltip?: ReactNode;
14
14
  variant?: 'default' | 'primary';
15
+ wide?: boolean;
15
16
  }
16
17
 
17
18
  const Link: FunctionComponent<Props> = ({
@@ -21,6 +22,7 @@ const Link: FunctionComponent<Props> = ({
21
22
  iconClassName,
22
23
  tooltip,
23
24
  variant = 'default',
25
+ wide,
24
26
  ...props
25
27
  }) => {
26
28
  return (
@@ -29,6 +31,7 @@ const Link: FunctionComponent<Props> = ({
29
31
  className={classNames(styles.button, className, {
30
32
  [styles.default]: variant === 'default',
31
33
  [styles.primary]: variant === 'primary',
34
+ [styles.wide]: wide,
32
35
  })}
33
36
  {...props}
34
37
  >
@@ -4,7 +4,6 @@
4
4
  position: relative;
5
5
  transition: var(--transition);
6
6
  word-break: break-word;
7
- overflow: hidden;
8
7
 
9
8
  &.isAllowed {
10
9
  background-color: var(--color--green--light);
@@ -13,6 +12,10 @@
13
12
  &.isNotAllowed {
14
13
  background-color: var(--color--red--light);
15
14
  }
15
+
16
+ &:focus-within {
17
+ @include focus-effect;
18
+ }
16
19
  }
17
20
 
18
21
  .content {
@@ -20,6 +23,11 @@
20
23
 
21
24
  height: 100%;
22
25
  overflow-y: auto;
26
+ border-radius: inherit;
27
+
28
+ &:focus-visible {
29
+ outline: none;
30
+ }
23
31
  }
24
32
 
25
33
  .result {
@@ -1,6 +1,7 @@
1
1
  import classNames from 'classnames';
2
2
  import { FunctionComponent } from 'react';
3
3
 
4
+ import { useAppLayout } from 'hooks';
4
5
  import { selectDictionary, selectDictionaryError, useTranslate, useTypedSelector } from 'state';
5
6
 
6
7
  import EmptyState from '../EmptyState';
@@ -14,6 +15,7 @@ interface Props {
14
15
 
15
16
  const Dictionary: FunctionComponent<Props> = ({ className }) => {
16
17
  const translate = useTranslate();
18
+ const { dictionaryResultsHeight } = useAppLayout();
17
19
  const { results, isLoading } = useTypedSelector(selectDictionary);
18
20
  const error = useTypedSelector(selectDictionaryError);
19
21
  const isLastAllowed = results.at(-1)?.isAllowed;
@@ -24,6 +26,7 @@ const Dictionary: FunctionComponent<Props> = ({ className }) => {
24
26
  [styles.isAllowed]: isLastAllowed === true,
25
27
  [styles.isNotAllowed]: isLastAllowed === false,
26
28
  })}
29
+ style={{ height: dictionaryResultsHeight }}
27
30
  >
28
31
  <div className={styles.content}>
29
32
  {typeof error !== 'undefined' && !isLoading && <EmptyState variant="error">{error.message}</EmptyState>}
@@ -16,10 +16,8 @@ $radio-box-size: $radio-size + 2 * $radio-inner-border;
16
16
  cursor: pointer;
17
17
 
18
18
  &.checked {
19
- .icon {
20
- &::after {
21
- background-color: var(--color--primary);
22
- }
19
+ .iconContent {
20
+ background-color: var(--color--primary);
23
21
  }
24
22
  }
25
23
 
@@ -40,28 +38,24 @@ $radio-box-size: $radio-size + 2 * $radio-inner-border;
40
38
  }
41
39
 
42
40
  .icon {
41
+ display: flex;
42
+ justify-content: center;
43
+ align-items: center;
43
44
  flex: 0 0 auto;
44
- position: relative;
45
45
  width: $radio-box-size;
46
46
  height: $radio-box-size;
47
- border-radius: 50%;
48
47
  border: $radio-inner-border solid var(--color--primary);
49
- pointer-events: none;
50
-
51
- &::after {
52
- content: ' ';
53
- position: absolute;
54
- top: 50%;
55
- left: 50%;
56
- transform: translate(-50%, -50%);
57
- width: $radio-inner-size;
58
- height: $radio-inner-size;
59
- background-color: transparent;
60
- border-radius: 50%;
61
- transition: var(--transition);
62
- }
48
+ border-radius: 50%;
63
49
  }
64
50
 
65
51
  .content {
66
52
  flex: 1;
67
53
  }
54
+
55
+ .iconContent {
56
+ width: $radio-inner-size;
57
+ height: $radio-inner-size;
58
+ background-color: transparent;
59
+ border-radius: 50%;
60
+ transition: var(--transition);
61
+ }
@@ -30,7 +30,9 @@ const Radio: FunctionComponent<Props> = ({ checked, children, className, disable
30
30
  onChange={onChange}
31
31
  />
32
32
 
33
- <div aria-hidden="true" className={styles.icon} role="img" />
33
+ <div aria-hidden="true" className={styles.icon} role="img">
34
+ <div className={styles.iconContent} />
35
+ </div>
34
36
 
35
37
  <div className={styles.content}>{children}</div>
36
38
  </label>
@@ -17,6 +17,7 @@ import {
17
17
  RACK_TILE_SIZE_MAX,
18
18
  RESULTS_COLUMN_WIDTH,
19
19
  SOLVER_COLUMN_WIDTH,
20
+ TEXT_INPUT_HEIGHT,
20
21
  } from 'parameters';
21
22
  import { selectConfig, selectShowCoordinates, useTypedSelector } from 'state';
22
23
  import { ResultColumnId } from 'types';
@@ -67,6 +68,7 @@ const useAppLayout = () => {
67
68
  const maxControlsWidth = tileSize * config.rackSize + 2 * BORDER_WIDTH;
68
69
  const showResultsInModal = isLessThanL;
69
70
  const dictionaryHeight = showResultsInModal ? DICTIONARY_HEIGHT_MOBILE : DICTIONARY_HEIGHT;
71
+ const dictionaryResultsHeight = dictionaryHeight - TEXT_INPUT_HEIGHT - 2 * BORDER_WIDTH;
70
72
  const modalWidth = isLessThanS ? viewportWidth : MODAL_WIDTH;
71
73
  const resultsHeight = isLessThanL
72
74
  ? viewportHeight - dictionaryHeight - BUTTON_HEIGHT - MODAL_HEADER_HEIGHT - 5 * componentsSpacing
@@ -86,6 +88,7 @@ const useAppLayout = () => {
86
88
  coordinatesFontSize: coordinatesSize * 0.6,
87
89
  coordinatesSize,
88
90
  dictionaryHeight,
91
+ dictionaryResultsHeight,
89
92
  isModalFullWidth: isLessThanS,
90
93
  logoHeight,
91
94
  logoWidth: logoHeight * LOGO_ASPECT_RATIO,
@@ -37,16 +37,23 @@ const MenuModal: FunctionComponent<Props> = ({
37
37
  aria-label={translate('remaining-tiles')}
38
38
  className={styles.button}
39
39
  Icon={Sack}
40
+ wide
40
41
  onClick={onShowRemainingTiles}
41
42
  >
42
43
  {translate('remaining-tiles')}
43
44
  </Button>
44
45
 
45
- <Button aria-label={translate('words')} className={styles.button} Icon={CardChecklist} onClick={onShowWords}>
46
+ <Button aria-label={translate('words')} className={styles.button} Icon={CardChecklist} wide onClick={onShowWords}>
46
47
  {translate('words')}
47
48
  </Button>
48
49
 
49
- <Button aria-label={translate('dictionary')} className={styles.button} Icon={BookHalf} onClick={onShowDictionary}>
50
+ <Button
51
+ aria-label={translate('dictionary')}
52
+ className={styles.button}
53
+ Icon={BookHalf}
54
+ wide
55
+ onClick={onShowDictionary}
56
+ >
50
57
  {translate('dictionary')}
51
58
  </Button>
52
59
 
@@ -57,11 +64,12 @@ const MenuModal: FunctionComponent<Props> = ({
57
64
  Icon={Github}
58
65
  rel="noopener noreferrer"
59
66
  target="_blank"
67
+ wide
60
68
  >
61
69
  {translate('github')}
62
70
  </Button.Link>
63
71
 
64
- <Button aria-label={translate('settings')} className={styles.button} Icon={Cog} onClick={onShowSettings}>
72
+ <Button aria-label={translate('settings')} className={styles.button} Icon={Cog} wide onClick={onShowSettings}>
65
73
  <div className={styles.settings}>
66
74
  <div className={styles.settingsLabel}>{translate('settings')}</div>
67
75
  <Icon aria-hidden="true" className={styles.flag} role="img" />
@@ -167,7 +167,9 @@ function* onLocaleChange({ payload: locale }: PayloadAction<Locale>): AnyGenerat
167
167
  function* onResultCandidateChange({ payload: result }: PayloadAction<Result | null>): AnyGenerator {
168
168
  if (result) {
169
169
  const locale: Locale = yield select(selectLocale);
170
- yield put(dictionarySlice.actions.changeInput(result.words.join(LOCALE_FEATURES[locale].separator)));
170
+ const uniqueWords = Array.from(new Set(result.words));
171
+ const input = uniqueWords.join(LOCALE_FEATURES[locale].separator);
172
+ yield put(dictionarySlice.actions.changeInput(input));
171
173
  yield put(dictionarySlice.actions.submit());
172
174
  }
173
175
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrabble-solver/solver",
3
- "version": "2.15.4",
3
+ "version": "2.15.6",
4
4
  "description": "Scrabble Solver 2 - Solver",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -24,12 +24,12 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "@kamilmielnik/trie": "^3.1.0",
27
- "@scrabble-solver/types": "^2.15.4"
27
+ "@scrabble-solver/types": "^2.15.6"
28
28
  },
29
29
  "devDependencies": {
30
- "@scrabble-solver/configs": "^2.15.4",
31
- "@scrabble-solver/constants": "^2.15.4",
32
- "@scrabble-solver/dictionaries": "^2.15.4"
30
+ "@scrabble-solver/configs": "^2.15.6",
31
+ "@scrabble-solver/constants": "^2.15.6",
32
+ "@scrabble-solver/dictionaries": "^2.15.6"
33
33
  },
34
34
  "gitHead": "1e2d1ad49a288d4a44196d8e3336740da132c637"
35
35
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrabble-solver/types",
3
- "version": "2.15.4",
3
+ "version": "2.15.6",
4
4
  "description": "Scrabble Solver 2 - Types",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -23,7 +23,7 @@
23
23
  "clean": "rimraf build/"
24
24
  },
25
25
  "dependencies": {
26
- "@scrabble-solver/constants": "^2.15.4"
26
+ "@scrabble-solver/constants": "^2.15.6"
27
27
  },
28
28
  "gitHead": "1e2d1ad49a288d4a44196d8e3336740da132c637"
29
29
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrabble-solver/word-definitions",
3
- "version": "2.15.4",
3
+ "version": "2.15.6",
4
4
  "description": "Scrabble Solver 2 - Word definitions",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -23,7 +23,7 @@
23
23
  "clean": "rimraf build/"
24
24
  },
25
25
  "dependencies": {
26
- "@scrabble-solver/types": "^2.15.4",
26
+ "@scrabble-solver/types": "^2.15.6",
27
27
  "cheerio": "^1.0.0",
28
28
  "follow-redirects": "^1.15.9",
29
29
  "striptags": "^3.2.0"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrabble-solver/word-lists",
3
- "version": "2.15.4",
3
+ "version": "2.15.6",
4
4
  "description": "Scrabble Solver 2 - Word lists",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -23,7 +23,7 @@
23
23
  "clean": "rimraf build/"
24
24
  },
25
25
  "dependencies": {
26
- "@scrabble-solver/types": "^2.15.4",
26
+ "@scrabble-solver/types": "^2.15.6",
27
27
  "cheerio": "^1.0.0",
28
28
  "follow-redirects": "^1.15.9",
29
29
  "latinize": "^1.0.0",