scrabble-solver 2.13.12 → 2.13.13

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 (135) hide show
  1. package/.eslintrc.js +13 -4
  2. package/.github/workflows/cypress.yml +24 -0
  3. package/.github/workflows/eslint.yml +9 -10
  4. package/.github/workflows/jest.yml +27 -0
  5. package/.nx/cache/nx_files.nxt +0 -0
  6. package/.nx/workspace-data/file-map.json +632 -548
  7. package/.nx/workspace-data/lockfile.hash +1 -1
  8. package/.nx/workspace-data/parsed-lock-file.json +5765 -5261
  9. package/.nx/workspace-data/project-graph.json +4745 -3485
  10. package/README.md +5 -3
  11. package/cypress/e2e/app.spec.cy.ts +107 -0
  12. package/cypress/e2e/bugs/112.spec.cy.ts +29 -0
  13. package/cypress/e2e/bugs/129.spec.cy.ts +13 -0
  14. package/cypress/e2e/bugs/2.spec.cy.ts +15 -0
  15. package/cypress/e2e/bugs/3.spec.cy.ts +15 -0
  16. package/cypress/e2e/bugs/342.spec.cy.ts +37 -0
  17. package/cypress/e2e/bugs/348.spec.cy.ts +73 -0
  18. package/cypress/support/commands.ts +4 -0
  19. package/cypress/support/e2e.ts +1 -0
  20. package/cypress/support/index.ts +1 -0
  21. package/cypress/support/lib/actions.ts +57 -0
  22. package/cypress/support/lib/index.ts +2 -0
  23. package/cypress/support/lib/selectors.ts +70 -0
  24. package/cypress/tsconfig.json +9 -0
  25. package/cypress.config.ts +9 -0
  26. package/jest.config.js +2 -3
  27. package/lerna.json +1 -1
  28. package/package.json +27 -20
  29. package/packages/configs/package.json +3 -3
  30. package/packages/constants/package.json +1 -1
  31. package/packages/dictionaries/package-lock.json +2 -2
  32. package/packages/dictionaries/package.json +4 -4
  33. package/packages/logger/package-lock.json +3 -3
  34. package/packages/logger/package.json +2 -2
  35. package/packages/scrabble-solver/.next/BUILD_ID +1 -1
  36. package/packages/scrabble-solver/.next/build-manifest.json +14 -14
  37. package/packages/scrabble-solver/.next/cache/.tsbuildinfo +1 -1
  38. package/packages/scrabble-solver/.next/cache/eslint/.cache_8dgz12 +1 -1
  39. package/packages/scrabble-solver/.next/cache/webpack/client-production/0.pack +0 -0
  40. package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack +0 -0
  41. package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack.old +0 -0
  42. package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/0.pack +0 -0
  43. package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack +0 -0
  44. package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack.old +0 -0
  45. package/packages/scrabble-solver/.next/cache/webpack/server-production/0.pack +0 -0
  46. package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack +0 -0
  47. package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack.old +0 -0
  48. package/packages/scrabble-solver/.next/prerender-manifest.js +1 -1
  49. package/packages/scrabble-solver/.next/prerender-manifest.json +1 -1
  50. package/packages/scrabble-solver/.next/routes-manifest.json +1 -1
  51. package/packages/scrabble-solver/.next/server/chunks/807.js +1 -1
  52. package/packages/scrabble-solver/.next/server/middleware-build-manifest.js +1 -1
  53. package/packages/scrabble-solver/.next/server/pages/404.html +1 -1
  54. package/packages/scrabble-solver/.next/server/pages/500.html +1 -1
  55. package/packages/scrabble-solver/.next/server/pages/api/solve.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.json +1 -1
  59. package/packages/scrabble-solver/.next/server/pages-manifest.json +1 -1
  60. package/packages/scrabble-solver/.next/static/chunks/{main-b5b360c6afb66b05.js → main-8b0b4e610892a916.js} +1 -1
  61. package/packages/scrabble-solver/.next/static/chunks/pages/{404-0c9f3e0f8b15f487.js → 404-b0c2ccded2455be0.js} +1 -1
  62. package/packages/scrabble-solver/.next/static/chunks/pages/_app-42ce6b4032e931ff.js +17 -0
  63. package/packages/scrabble-solver/.next/static/chunks/pages/index-3718075f2ba2220c.js +1 -0
  64. package/packages/scrabble-solver/.next/static/chunks/webpack-c4acd79e87956a0e.js +1 -0
  65. package/packages/scrabble-solver/.next/static/css/2adc9736d823979b.css +2 -0
  66. package/packages/scrabble-solver/.next/static/{N8hSsS6Ppzlj3ebHMSZvI → qwJjm2FeDHHGY92CY5oQQ}/_buildManifest.js +1 -1
  67. package/packages/scrabble-solver/.next/trace +45 -45
  68. package/packages/scrabble-solver/package-lock.json +6 -6
  69. package/packages/scrabble-solver/package.json +12 -12
  70. package/packages/scrabble-solver/public/service-worker.js +1 -1
  71. package/packages/scrabble-solver/src/components/Board/Board.module.scss +3 -9
  72. package/packages/scrabble-solver/src/components/Board/Board.tsx +2 -2
  73. package/packages/scrabble-solver/src/components/Board/BoardPure.tsx +3 -2
  74. package/packages/scrabble-solver/src/components/Board/components/ToggleDirectionButton/ToggleDirectionButton.tsx +2 -0
  75. package/packages/scrabble-solver/src/components/Board/hooks/useBackgroundImage.tsx +2 -6
  76. package/packages/scrabble-solver/src/components/Board/hooks/useBoardStyle.ts +10 -4
  77. package/packages/scrabble-solver/src/components/Dictionary/Dictionary.module.scss +10 -7
  78. package/packages/scrabble-solver/src/components/Dictionary/Dictionary.tsx +38 -36
  79. package/packages/scrabble-solver/src/components/Loading/Loading.module.scss +1 -0
  80. package/packages/scrabble-solver/src/components/Loading/Loading.tsx +1 -1
  81. package/packages/scrabble-solver/src/components/Modal/components/Section/Section.tsx +3 -2
  82. package/packages/scrabble-solver/src/components/NavButtons/NavButtons.tsx +1 -0
  83. package/packages/scrabble-solver/src/components/Rack/Rack.tsx +1 -0
  84. package/packages/scrabble-solver/src/components/Results/Cell.tsx +7 -3
  85. package/packages/scrabble-solver/src/components/Results/Header.tsx +99 -0
  86. package/packages/scrabble-solver/src/components/Results/HeaderButton.tsx +18 -13
  87. package/packages/scrabble-solver/src/components/Results/Result.tsx +23 -16
  88. package/packages/scrabble-solver/src/components/Results/Results.module.scss +24 -12
  89. package/packages/scrabble-solver/src/components/Results/Results.tsx +3 -9
  90. package/packages/scrabble-solver/src/components/Results/types.ts +0 -8
  91. package/packages/scrabble-solver/src/components/Solver/Solver.tsx +1 -1
  92. package/packages/scrabble-solver/src/components/Tile/TilePure.tsx +1 -0
  93. package/packages/scrabble-solver/src/hooks/index.ts +1 -0
  94. package/packages/scrabble-solver/src/hooks/useAppLayout.ts +12 -1
  95. package/packages/scrabble-solver/src/hooks/useColumns.ts +47 -0
  96. package/packages/scrabble-solver/src/icons/GeoAlt.svg +5 -0
  97. package/packages/scrabble-solver/src/icons/OneTwoThree.svg +4 -0
  98. package/packages/scrabble-solver/src/icons/SquareA.svg +6 -0
  99. package/packages/scrabble-solver/src/icons/SquareB.svg +6 -0
  100. package/packages/scrabble-solver/src/icons/Squares.svg +34 -0
  101. package/packages/scrabble-solver/src/icons/Words.svg +22 -0
  102. package/packages/scrabble-solver/src/icons/index.ts +6 -0
  103. package/packages/scrabble-solver/src/lib/groupResults.ts +1 -1
  104. package/packages/scrabble-solver/src/lib/index.ts +0 -1
  105. package/packages/scrabble-solver/src/lib/sortResults.ts +10 -10
  106. package/packages/scrabble-solver/src/modals/KeyMapModal/KeyMapModal.tsx +8 -9
  107. package/packages/scrabble-solver/src/modals/RemainingTilesModal/RemainingTilesModal.tsx +1 -0
  108. package/packages/scrabble-solver/src/modals/SettingsModal/SettingsModal.tsx +5 -5
  109. package/packages/scrabble-solver/src/modals/WordsModal/WordsModal.tsx +2 -0
  110. package/packages/scrabble-solver/src/parameters/index.ts +12 -0
  111. package/packages/scrabble-solver/src/state/selectors.ts +26 -1
  112. package/packages/scrabble-solver/src/state/slices/resultsInitialState.ts +2 -2
  113. package/packages/scrabble-solver/src/state/slices/resultsSlice.ts +2 -2
  114. package/packages/scrabble-solver/src/state/useTranslate.ts +5 -1
  115. package/packages/scrabble-solver/src/styles/variables.scss +1 -0
  116. package/packages/scrabble-solver/src/types/index.ts +11 -2
  117. package/packages/solver/package-lock.json +2 -2
  118. package/packages/solver/package.json +5 -5
  119. package/packages/types/package.json +2 -2
  120. package/packages/word-definitions/build/lib/request.d.ts +0 -1
  121. package/packages/word-definitions/package-lock.json +2 -2
  122. package/packages/word-definitions/package.json +2 -2
  123. package/packages/word-lists/package-lock.json +2 -2
  124. package/packages/word-lists/package.json +2 -2
  125. package/tsconfig.jest.json +2 -1
  126. package/.github/workflows/test.yml +0 -28
  127. package/packages/scrabble-solver/.next/static/chunks/pages/_app-8246f5b39b6a5e59.js +0 -17
  128. package/packages/scrabble-solver/.next/static/chunks/pages/index-65bfe83d121535ab.js +0 -1
  129. package/packages/scrabble-solver/.next/static/chunks/webpack-6ef43a8d4a395f49.js +0 -1
  130. package/packages/scrabble-solver/.next/static/css/2f727b21d1331ea5.css +0 -2
  131. package/packages/scrabble-solver/src/components/Results/getCoordinatesColumn.ts +0 -14
  132. package/packages/scrabble-solver/src/components/Results/getLocaleColumns.ts +0 -58
  133. package/packages/scrabble-solver/src/components/Results/useColumns.ts +0 -44
  134. package/packages/scrabble-solver/src/lib/dataUrlToBlob.ts +0 -20
  135. /package/packages/scrabble-solver/.next/static/{N8hSsS6Ppzlj3ebHMSZvI → qwJjm2FeDHHGY92CY5oQQ}/_ssgManifest.js +0 -0
@@ -0,0 +1,34 @@
1
+ <!-- https://icons.getbootstrap.com/icons/square/ -->
2
+ <!-- https://icons.getbootstrap.com/icons/alphabet-uppercase/ -->
3
+ <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 16 16">
4
+ <path
5
+ d="m 2.75,4 v 0.75 h 7.75 a 0.75,0.75 0 0 1 0.75,0.75 v 7.75 H 12 V 5.5 A 1.5,1.5 0 0 0 10.5,4 Z"
6
+ stroke-width="0.75" />
7
+ <path
8
+ d="m 12,14 h -0.75 v 0.5 a 0.75,0.75 0 0 1 -0.75,0.75 h -9 A 0.75,0.75 0 0 1 0.75,14.5 v -9 A 0.75,0.75 0 0 1 1.5,4.75 H 2 V 4 H 1.5 A 1.5,1.5 0 0 0 0,5.5 v 9 A 1.5,1.5 0 0 0 1.5,16 h 9 A 1.5,1.5 0 0 0 12,14.5 Z"
9
+ stroke-width="0.75" />
10
+ <path
11
+ d="M 2,4.75 H 2.75 V 4 H 2 Z"
12
+ stroke-width="0.75" />
13
+ <path
14
+ d="M 12,14 V 13.25 H 11.25 V 14 Z"
15
+ stroke-width="0.75" />
16
+ <path
17
+ d="m 4.75,2 v 0.75 h 7.75 a 0.75,0.75 0 0 1 0.75,0.75 v 7.75 H 14 V 3.5 A 1.5,1.5 0 0 0 12.5,2 Z"
18
+ stroke-width="0.75" />
19
+ <path
20
+ d="M 4,2.75 V 2 H 3.5 A 1.5,1.5 0 0 0 2,3.5 V 4 H 2.75 V 3.5 A 0.75,0.75 0 0 1 3.5,2.75 Z"
21
+ stroke-width="0.75" />
22
+ <path
23
+ d="m 14,12 h -0.75 v 0.5 A 0.75,0.75 0 0 1 12.5,13.25 H 12 V 14 h 0.5 A 1.5,1.5 0 0 0 14,12.5 Z"
24
+ stroke-width="0.75" />
25
+ <path
26
+ d="M 4,2.75 H 4.75 V 2 H 4 Z"
27
+ stroke-width="0.75" />
28
+ <path
29
+ d="M 14,12 V 11.25 H 13.25 V 12 Z"
30
+ stroke-width="0.75" />
31
+ <path
32
+ d="M 5.5,0 A 1.5,1.5 0 0 0 4,1.5 V 2 H 4.75 V 1.5 A 0.75,0.75 0 0 1 5.5,0.75 h 9 a 0.75,0.75 0 0 1 0.75,0.75 v 9 A 0.75,0.75 0 0 1 14.5,11.25 H 14 V 12 h 0.5 A 1.5,1.5 0 0 0 16,10.5 v -9 A 1.5,1.5 0 0 0 14.5,0 Z"
33
+ stroke-width="0.75" />
34
+ </svg>
@@ -0,0 +1,22 @@
1
+ <!-- https://icons.getbootstrap.com/icons/square/ -->
2
+ <!-- https://icons.getbootstrap.com/icons/alphabet-uppercase/ -->
3
+ <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 16 16">
4
+ <path
5
+ d="M 7.21875,0.51562499 A 0.51562499,0.51562499 0 0 1 7.734375,1.03125 v 6.1875 A 0.51562499,0.51562499 0 0 1 7.21875,7.734375 H 1.03125 A 0.51562499,0.51562499 0 0 1 0.51562499,7.21875 V 1.03125 A 0.51562499,0.51562499 0 0 1 1.03125,0.51562499 Z M 1.03125,0 A 1.03125,1.03125 0 0 0 0,1.03125 v 6.1875 A 1.03125,1.03125 0 0 0 1.03125,8.25 h 6.1875 A 1.03125,1.03125 0 0 0 8.25,7.21875 V 1.03125 A 1.03125,1.03125 0 0 0 7.21875,0 Z"
6
+ stroke-width="0.5" />
7
+ <path
8
+ d="m 14.96875,8.265625 a 0.51562499,0.51562499 0 0 1 0.515625,0.515625 v 6.1875 A 0.51562499,0.51562499 0 0 1 14.96875,15.484375 H 8.7812501 A 0.51562499,0.51562499 0 0 1 8.265625,14.96875 V 8.78125 A 0.51562499,0.51562499 0 0 1 8.7812501,8.265625 Z M 8.7812501,7.75 A 1.03125,1.03125 0 0 0 7.75,8.78125 v 6.1875 A 1.03125,1.03125 0 0 0 8.7812501,16 H 14.96875 A 1.03125,1.03125 0 0 0 16,14.96875 V 8.78125 A 1.03125,1.03125 0 0 0 14.96875,7.75 Z"
9
+ stroke-width="0.5" />
10
+ <path
11
+ d="M 3.7614277,2.5 2.7009247,5.75 H 3.3333995 L 3.5811523,4.9136776 H 4.6366198 L 4.8833654,5.75 H 5.5490753 L 4.493608,2.5 Z m 0.3343657,0.6224265 h 0.0282 L 4.5107288,4.4362133 H 3.7090572 Z"
12
+ stroke-width="0.5" />
13
+ <path
14
+ d="m 2.954049,10.250001 v 3.25 h 1.275448 c 0.621526,0 1.066454,-0.335617 1.066454,-0.916407 0,-0.488403 -0.314632,-0.754324 -0.682648,-0.792732 v -0.0294 c 0.303013,-0.07889 0.525414,-0.316137 0.525414,-0.711635 0,-0.497226 -0.359314,-0.799828 -0.904337,-0.799828 z m 0.60159,0.483546 h 0.537133 c 0.285012,0 0.448262,0.161062 0.448262,0.425765 0,0.282869 -0.17897,0.442997 -0.584987,0.442997 H 3.555639 Z m 0,1.316828 h 0.57522 c 0.356516,0 0.547877,0.187953 0.547877,0.494698 0,0.309859 -0.196385,0.471382 -0.671906,0.471382 H 3.555639 Z"
15
+ stroke-width="0.5" />
16
+ <path
17
+ d="M 7.21875,8.265625 A 0.51562499,0.51562499 0 0 1 7.734375,8.78125 v 6.1875 A 0.51562499,0.51562499 0 0 1 7.21875,15.484375 H 1.03125 A 0.51562499,0.51562499 0 0 1 0.515625,14.96875 V 8.78125 A 0.51562499,0.51562499 0 0 1 1.03125,8.265625 Z M 1.03125,7.75 A 1.03125,1.03125 0 0 0 0,8.78125 v 6.1875 A 1.03125,1.03125 0 0 0 1.03125,16 h 6.1875 A 1.03125,1.03125 0 0 0 8.25,14.96875 V 8.78125 A 1.03125,1.03125 0 0 0 7.21875,7.75 Z"
18
+ stroke-width="0.5" />
19
+ <path
20
+ d="m 11.92041,10.250001 c -0.819499,0 -1.287109,0.548047 -1.287109,1.435547 v 0.389648 c 0,0.887999 0.46311,1.424805 1.287109,1.424805 0.6715,0 1.167289,-0.413243 1.196289,-1.010742 v -0.06055 h -0.585937 c -0.0245,0.320999 -0.253946,0.547851 -0.606446,0.547851 -0.428499,0 -0.672851,-0.323367 -0.672851,-0.901367 v -0.386719 c 0,-0.579999 0.248352,-0.915039 0.672851,-0.915039 0.348,0 0.581446,0.244649 0.606446,0.577149 h 0.585937 v -0.05664 c -0.0265,-0.618999 -0.522789,-1.043945 -1.196289,-1.043945 z"
21
+ stroke-width="0.5" />
22
+ </svg>
@@ -28,15 +28,21 @@ export { default as FlagGb } from './FlagGb.svg';
28
28
  export { default as FlagPl } from './FlagPl.svg';
29
29
  export { default as FlagRo } from './FlagRo.svg';
30
30
  export { default as FlagUs } from './FlagUs.svg';
31
+ export { default as GeoAlt } from './GeoAlt.svg';
31
32
  export { default as Github } from './Github.svg';
32
33
  export { default as InfoCircleFill } from './InfoCircleFill.svg';
33
34
  export { default as Keyboard } from './Keyboard.svg';
34
35
  export { default as KeyboardFill } from './KeyboardFill.svg';
35
36
  export { default as List } from './List.svg';
37
+ export { default as OneTwoThree } from './OneTwoThree.svg';
36
38
  export { default as Sack } from './Sack.svg';
37
39
  export { default as Search } from './Search.svg';
38
40
  export { default as SortDown } from './SortDown.svg';
39
41
  export { default as SortUp } from './SortUp.svg';
40
42
  export { default as Square } from './Square.svg';
43
+ export { default as SquareA } from './SquareA.svg';
44
+ export { default as SquareB } from './SquareB.svg';
41
45
  export { default as SquareFill } from './SquareFill.svg';
46
+ export { default as Squares } from './Squares.svg';
42
47
  export { default as Star } from './Star.svg';
48
+ export { default as Words } from './Words.svg';
@@ -18,7 +18,7 @@ const groupResults = (
18
18
 
19
19
  const { matching, other } = results.reduce<GroupedResults>(
20
20
  (groupedResults, result) => {
21
- const matchesQuery = () => regExp.test(result.word);
21
+ const matchesQuery = () => Boolean(result.word.match(regExp));
22
22
 
23
23
  if (resultMatchesCellFilter(result, cellFilter) && matchesQuery()) {
24
24
  groupedResults.matching.push(result);
@@ -7,7 +7,6 @@ export { default as createKeyboardNavigation } from './createKeyboardNavigation'
7
7
  export { default as createNullMovingComparator } from './createNullMovingComparator';
8
8
  export { default as createRegExp } from './createRegExp';
9
9
  export { default as createStringComparator } from './createStringComparator';
10
- export { default as dataUrlToBlob } from './dataUrlToBlob';
11
10
  export { default as detectLocale } from './detectLocale';
12
11
  export { default as extractCharacters } from './extractCharacters';
13
12
  export { default as extractCharactersByCase } from './extractCharactersByCase';
@@ -1,26 +1,26 @@
1
1
  import { Result, ShowCoordinates } from '@scrabble-solver/types';
2
2
 
3
- import { Comparator, ResultColumn, Sort, SortDirection } from 'types';
3
+ import { Comparator, ResultColumnId, Sort, SortDirection } from 'types';
4
4
 
5
5
  import createKeyComparator from './createKeyComparator';
6
6
  import createStringComparator from './createStringComparator';
7
7
  import getCoordinates from './getCoordinates';
8
8
  import reverseComparator from './reverseComparator';
9
9
 
10
- const comparators: Record<ResultColumn, (locale: string, showCoordinates: ShowCoordinates) => Comparator<Result>> = {
11
- [ResultColumn.BlanksCount]: (locale: string) => createKeyComparator('blanksCount', locale),
12
- [ResultColumn.ConsonantsCount]: (locale: string) => createKeyComparator('consonantsCount', locale),
13
- [ResultColumn.Coordinates]: (locale: string, showCoordinates: ShowCoordinates) => (a, b) => {
10
+ const comparators: Record<ResultColumnId, (locale: string, showCoordinates: ShowCoordinates) => Comparator<Result>> = {
11
+ [ResultColumnId.BlanksCount]: (locale: string) => createKeyComparator('blanksCount', locale),
12
+ [ResultColumnId.ConsonantsCount]: (locale: string) => createKeyComparator('consonantsCount', locale),
13
+ [ResultColumnId.Coordinates]: (locale: string, showCoordinates: ShowCoordinates) => (a, b) => {
14
14
  const stringComparator = createStringComparator(locale);
15
15
  const aValue = getCoordinates(a, showCoordinates);
16
16
  const bValue = getCoordinates(b, showCoordinates);
17
17
  return stringComparator(aValue, bValue);
18
18
  },
19
- [ResultColumn.Points]: (locale: string) => createKeyComparator('points', locale),
20
- [ResultColumn.TilesCount]: (locale: string) => createKeyComparator('tilesCount', locale),
21
- [ResultColumn.VowelsCount]: (locale: string) => createKeyComparator('vowelsCount', locale),
22
- [ResultColumn.Word]: (locale: string) => createKeyComparator('word', locale),
23
- [ResultColumn.WordsCount]: (locale: string) => createKeyComparator('wordsCount', locale),
19
+ [ResultColumnId.Points]: (locale: string) => createKeyComparator('points', locale),
20
+ [ResultColumnId.TilesCount]: (locale: string) => createKeyComparator('tilesCount', locale),
21
+ [ResultColumnId.VowelsCount]: (locale: string) => createKeyComparator('vowelsCount', locale),
22
+ [ResultColumnId.Word]: (locale: string) => createKeyComparator('word', locale),
23
+ [ResultColumnId.WordsCount]: (locale: string) => createKeyComparator('wordsCount', locale),
24
24
  };
25
25
 
26
26
  const sortResults = (
@@ -17,7 +17,7 @@ const KeyMapModal: FunctionComponent<Props> = ({ className, isOpen, onClose }) =
17
17
 
18
18
  return (
19
19
  <Modal className={className} isOpen={isOpen} title={translate('keyMap')} onClose={onClose}>
20
- <Modal.Section title={translate('keyMap.board-and-rack')}>
20
+ <Modal.Section label={translate('keyMap.board-and-rack')} title={translate('keyMap.board-and-rack')}>
21
21
  <Mapping description={translate('keyMap.board-and-rack.navigate')} mapping={[<Arrows key="arrows" />]} />
22
22
 
23
23
  <Mapping
@@ -27,11 +27,6 @@ const KeyMapModal: FunctionComponent<Props> = ({ className, isOpen, onClose }) =
27
27
 
28
28
  <Mapping description={translate('keyMap.board-and-rack.submit')} mapping={[<Enter key="del" />]} />
29
29
 
30
- <Mapping
31
- description={translate('keyMap.board.toggle-cell-filter')}
32
- mapping={[[<Ctrl key="ctrl" />, <Key key="g">G</Key>]]}
33
- />
34
-
35
30
  {config.twoCharacterTiles.length > 0 && (
36
31
  <Mapping
37
32
  description={translate('keyMap.board-and-rack.insert-two-letter-tile')}
@@ -49,12 +44,16 @@ const KeyMapModal: FunctionComponent<Props> = ({ className, isOpen, onClose }) =
49
44
  )}
50
45
  </Modal.Section>
51
46
 
52
- <Modal.Section title={translate('keyMap.board')}>
53
- <Mapping description={translate('keyMap.board.toggle-blank')} mapping={[<Space key="space" />]} />
47
+ <Modal.Section label={translate('keyMap.board')} title={translate('keyMap.board')}>
54
48
  <Mapping description={translate('keyMap.board.toggle-direction')} mapping={[<Arrows key="arrows" />]} />
49
+ <Mapping description={translate('keyMap.board.toggle-blank')} mapping={[<Space key="space" />]} />
50
+ <Mapping
51
+ description={translate('keyMap.board.toggle-cell-filter')}
52
+ mapping={[[<Ctrl key="ctrl" />, <Key key="g">G</Key>]]}
53
+ />
55
54
  </Modal.Section>
56
55
 
57
- <Modal.Section title={translate('keyMap.rack')}>
56
+ <Modal.Section label={translate('keyMap.rack')} title={translate('keyMap.rack')}>
58
57
  <Mapping description={translate('keyMap.rack.insert-blank')} mapping={[<Space key="space" />]} />
59
58
  </Modal.Section>
60
59
  </Modal>
@@ -31,6 +31,7 @@ const RemainingTilesModal: FunctionComponent<Props> = ({ className, isOpen, onCl
31
31
  return (
32
32
  <Modal.Section
33
33
  key={translationKey}
34
+ label={translate(translationKey)}
34
35
  title={
35
36
  <span className={styles.title}>
36
37
  <span>{translate(translationKey)}</span>
@@ -24,25 +24,25 @@ const SettingsModal: FunctionComponent<Props> = ({ className, isOpen, onClose })
24
24
 
25
25
  return (
26
26
  <Modal className={className} isOpen={isOpen} title={translate('settings')} onClose={onClose}>
27
- <Modal.Section title={translate('settings.game')}>
27
+ <Modal.Section label={translate('settings.game')} title={translate('settings.game')}>
28
28
  <ConfigSetting disabled={!isOpen} />
29
29
  </Modal.Section>
30
30
 
31
- <Modal.Section title={translate('settings.language')}>
31
+ <Modal.Section label={translate('settings.language')} title={translate('settings.language')}>
32
32
  <LocaleSetting disabled={!isOpen} />
33
33
  </Modal.Section>
34
34
 
35
- <Modal.Section title={translate('settings.showCoordinates')}>
35
+ <Modal.Section label={translate('settings.showCoordinates')} title={translate('settings.showCoordinates')}>
36
36
  <ShowCoordinatesSetting disabled={!isOpen} />
37
37
  </Modal.Section>
38
38
 
39
39
  {!isTouchDevice && (
40
- <Modal.Section title={translate('settings.inputMode')}>
40
+ <Modal.Section label={translate('settings.inputMode')} title={translate('settings.inputMode')}>
41
41
  <InputModeSetting disabled={!isOpen} />
42
42
  </Modal.Section>
43
43
  )}
44
44
 
45
- <Modal.Section title={translate('settings.autoGroupTiles')}>
45
+ <Modal.Section label={translate('settings.autoGroupTiles')} title={translate('settings.autoGroupTiles')}>
46
46
  <AutoGroupTilesSetting disabled={!isOpen} />
47
47
  </Modal.Section>
48
48
  </Modal>
@@ -21,6 +21,7 @@ const WordsModal: FunctionComponent<Props> = ({ className, isOpen, onClose }) =>
21
21
  return (
22
22
  <Modal className={className} isOpen={isOpen} title={translate('words')} onClose={onClose}>
23
23
  <Modal.Section
24
+ label={translate('words.invalid')}
24
25
  title={
25
26
  <span className={styles.title}>
26
27
  <span>{translate('words.invalid')}</span>
@@ -36,6 +37,7 @@ const WordsModal: FunctionComponent<Props> = ({ className, isOpen, onClose }) =>
36
37
  </Modal.Section>
37
38
 
38
39
  <Modal.Section
40
+ label={translate('words.valid')}
39
41
  title={
40
42
  <span className={styles.title}>
41
43
  <span>{translate('words.valid')}</span>
@@ -1,3 +1,5 @@
1
+ import { ResultColumnId } from 'types';
2
+
1
3
  export const BREAKPOINTS = {
2
4
  xs: 480,
3
5
  s: 768,
@@ -120,6 +122,16 @@ export const RACK_TILE_SIZE_MAX = 80;
120
122
 
121
123
  export const REMAINING_TILES_TILE_SIZE = 50;
122
124
 
125
+ export const RESULTS_COLUMN_WIDTH: Record<ResultColumnId, number | undefined> = {
126
+ [ResultColumnId.BlanksCount]: 55,
127
+ [ResultColumnId.ConsonantsCount]: 55,
128
+ [ResultColumnId.Coordinates]: 55,
129
+ [ResultColumnId.Points]: 80,
130
+ [ResultColumnId.TilesCount]: 55,
131
+ [ResultColumnId.VowelsCount]: 55,
132
+ [ResultColumnId.Word]: undefined,
133
+ [ResultColumnId.WordsCount]: 55,
134
+ };
123
135
  export const RESULTS_ITEM_HEIGHT = 40;
124
136
 
125
137
  export const RESULTS_HEADER_HEIGHT = RESULTS_ITEM_HEIGHT;
@@ -16,7 +16,7 @@ import {
16
16
  sortGroupedResults,
17
17
  unorderedArraysEqual,
18
18
  } from 'lib';
19
- import { Point, Translations } from 'types';
19
+ import { Point, ResultColumnId, Translations } from 'types';
20
20
 
21
21
  import { RootState } from './types';
22
22
 
@@ -231,3 +231,28 @@ export const selectVerify = selectVerifyRoot;
231
231
  export const selectHasInvalidWords = createSelector([selectVerify], ({ invalidWords }) => {
232
232
  return invalidWords.length > 0;
233
233
  });
234
+
235
+ export const selectColumns = createSelector([selectLocale, selectShowCoordinates], (locale, showCoordinates) => {
236
+ const { consonants, vowels } = LOCALE_FEATURES[locale];
237
+ const columns: ResultColumnId[] = [
238
+ ResultColumnId.Word,
239
+ ResultColumnId.TilesCount,
240
+ ResultColumnId.BlanksCount,
241
+ ResultColumnId.WordsCount,
242
+ ResultColumnId.Points,
243
+ ];
244
+
245
+ if (showCoordinates !== 'hidden') {
246
+ columns.push(ResultColumnId.Coordinates);
247
+ }
248
+
249
+ if (vowels) {
250
+ columns.push(ResultColumnId.VowelsCount);
251
+ }
252
+
253
+ if (consonants) {
254
+ columns.push(ResultColumnId.ConsonantsCount);
255
+ }
256
+
257
+ return columns;
258
+ });
@@ -1,6 +1,6 @@
1
1
  import { Result } from '@scrabble-solver/types';
2
2
 
3
- import { ResultColumn, Sort, SortDirection } from 'types';
3
+ import { ResultColumnId, Sort, SortDirection } from 'types';
4
4
 
5
5
  export interface ResultsState {
6
6
  candidate: Result | null;
@@ -14,7 +14,7 @@ const resultsInitialState: ResultsState = {
14
14
  query: '',
15
15
  results: undefined,
16
16
  sort: {
17
- column: ResultColumn.Points,
17
+ column: ResultColumnId.Points,
18
18
  direction: SortDirection.Descending,
19
19
  },
20
20
  };
@@ -1,7 +1,7 @@
1
1
  import { createSlice, PayloadAction } from '@reduxjs/toolkit';
2
2
  import { Result } from '@scrabble-solver/types';
3
3
 
4
- import { ResultColumn, SortDirection } from 'types';
4
+ import { ResultColumnId, SortDirection } from 'types';
5
5
 
6
6
  import resultsInitialState from './resultsInitialState';
7
7
 
@@ -37,7 +37,7 @@ const resultsSlice = createSlice({
37
37
  };
38
38
  },
39
39
 
40
- sort: (state, action: PayloadAction<ResultColumn>) => {
40
+ sort: (state, action: PayloadAction<ResultColumnId>) => {
41
41
  const columndId = action.payload;
42
42
  const { column, direction } = state.sort;
43
43
 
@@ -9,13 +9,17 @@ const useTranslate = (): Translate => {
9
9
  const translations = useTypedSelector(selectTranslations);
10
10
  const locale = useTypedSelector(selectLocale);
11
11
  const translate: Translate = useCallback(
12
- (id, replacements = {}) => {
12
+ (id, replacements) => {
13
13
  const translation = translations[id];
14
14
 
15
15
  if (typeof translation === 'undefined') {
16
16
  throw new Error(`Untranslated key "${id}" in locale "${locale}"`);
17
17
  }
18
18
 
19
+ if (!replacements) {
20
+ return translation;
21
+ }
22
+
19
23
  return Object.entries(replacements).reduce(
20
24
  (result, [key, value]) => result.replaceAll(`{{${key}}}`, value),
21
25
  translation,
@@ -106,6 +106,7 @@ $easeOutSine: cubic-bezier(0.61, 1, 0.88, 1);
106
106
  --modal--width: 370px;
107
107
  --nav--height: calc(var(--logo--height) + var(--nav--padding));
108
108
  --nav--padding: var(--spacing--l);
109
+ --results--icon--size: 18px;
109
110
  --results--item--height: 40px;
110
111
  --solver-column--width: 580px;
111
112
  --square-button--size: 32px;
@@ -1,4 +1,5 @@
1
1
  import { Result } from '@scrabble-solver/types';
2
+ import { FunctionComponent, SVGAttributes } from 'react';
2
3
 
3
4
  export type Comparator<T> = (a: T, B: T) => number;
4
5
 
@@ -24,7 +25,7 @@ export interface Point {
24
25
  export type Rack = (string | null)[];
25
26
 
26
27
  export interface Sort {
27
- column: ResultColumn;
28
+ column: ResultColumnId;
28
29
  direction: SortDirection;
29
30
  }
30
31
 
@@ -47,7 +48,7 @@ export interface RemainingTilesGroup {
47
48
  totalCount: number;
48
49
  }
49
50
 
50
- export enum ResultColumn {
51
+ export enum ResultColumnId {
51
52
  BlanksCount = 'blanks-count',
52
53
  ConsonantsCount = 'consonants-count',
53
54
  Coordinates = 'coordinates',
@@ -58,6 +59,14 @@ export enum ResultColumn {
58
59
  WordsCount = 'words-count',
59
60
  }
60
61
 
62
+ export interface ResultColumn {
63
+ className: string;
64
+ Icon?: FunctionComponent<SVGAttributes<SVGElement>>;
65
+ id: ResultColumnId;
66
+ translationKey: TranslationKey;
67
+ width?: number;
68
+ }
69
+
61
70
  export interface GroupedResults {
62
71
  matching: Result[];
63
72
  other: Result[];
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@scrabble-solver/solver",
3
- "version": "2.13.12",
3
+ "version": "2.13.13",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@scrabble-solver/solver",
9
- "version": "2.13.12",
9
+ "version": "2.13.13",
10
10
  "license": "CC-BY-NC-ND-4.0",
11
11
  "dependencies": {
12
12
  "@kamilmielnik/trie": "^3.0.0"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrabble-solver/solver",
3
- "version": "2.13.12",
3
+ "version": "2.13.13",
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.0.0",
27
- "@scrabble-solver/types": "^2.13.12"
27
+ "@scrabble-solver/types": "^2.13.13"
28
28
  },
29
29
  "devDependencies": {
30
- "@scrabble-solver/configs": "^2.13.12",
31
- "@scrabble-solver/constants": "^2.13.12",
32
- "@scrabble-solver/dictionaries": "^2.13.12"
30
+ "@scrabble-solver/configs": "^2.13.13",
31
+ "@scrabble-solver/constants": "^2.13.13",
32
+ "@scrabble-solver/dictionaries": "^2.13.13"
33
33
  },
34
34
  "gitHead": "1e2d1ad49a288d4a44196d8e3336740da132c637"
35
35
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrabble-solver/types",
3
- "version": "2.13.12",
3
+ "version": "2.13.13",
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.13.12"
26
+ "@scrabble-solver/constants": "^2.13.13"
27
27
  },
28
28
  "gitHead": "1e2d1ad49a288d4a44196d8e3336740da132c637"
29
29
  }
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import { RequestOptions } from 'http';
3
2
  interface Options extends RequestOptions {
4
3
  protocol?: 'http' | 'https';
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@scrabble-solver/word-definitions",
3
- "version": "2.13.12",
3
+ "version": "2.13.13",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@scrabble-solver/word-definitions",
9
- "version": "2.13.12",
9
+ "version": "2.13.13",
10
10
  "license": "CC-BY-NC-ND-4.0",
11
11
  "dependencies": {
12
12
  "cheerio": "^1.0.0-rc.12",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrabble-solver/word-definitions",
3
- "version": "2.13.12",
3
+ "version": "2.13.13",
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.13.12",
26
+ "@scrabble-solver/types": "^2.13.13",
27
27
  "cheerio": "^1.0.0-rc.12",
28
28
  "follow-redirects": "^1.15.6",
29
29
  "striptags": "^3.2.0"
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@scrabble-solver/word-lists",
3
- "version": "2.13.12",
3
+ "version": "2.13.13",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@scrabble-solver/word-lists",
9
- "version": "2.13.12",
9
+ "version": "2.13.13",
10
10
  "license": "CC-BY-NC-ND-4.0",
11
11
  "dependencies": {
12
12
  "cheerio": "^1.0.0-rc.12",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrabble-solver/word-lists",
3
- "version": "2.13.12",
3
+ "version": "2.13.13",
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.13.12",
26
+ "@scrabble-solver/types": "^2.13.13",
27
27
  "cheerio": "^1.0.0-rc.12",
28
28
  "follow-redirects": "^1.15.6",
29
29
  "latinize": "^1.0.0",
@@ -3,5 +3,6 @@
3
3
 
4
4
  "compilerOptions": {
5
5
  "jsx": "react"
6
- }
6
+ },
7
+ "exclude": ["cypress", "./cypress", "./cypress.config.ts"]
7
8
  }
@@ -1,28 +0,0 @@
1
- name: Test
2
-
3
- on:
4
- push:
5
- branches: [master]
6
- pull_request:
7
- branches: [master]
8
-
9
- jobs:
10
- build:
11
-
12
- runs-on: ubuntu-latest
13
-
14
- strategy:
15
- matrix:
16
- node-version: [20.x]
17
-
18
- steps:
19
- - uses: actions/checkout@v2
20
- - name: Use Node.js ${{ matrix.node-version }}
21
- uses: actions/setup-node@v1
22
- with:
23
- node-version: ${{ matrix.node-version }}
24
- - run: npm ci
25
- - run: npm run build
26
- - run: npm run test
27
- env:
28
- CI: true