@scrabble-solver/scrabble-solver 2.10.7 → 2.10.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +15 -21
  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/images-manifest.json +1 -1
  13. package/.next/next-server.js.nft.json +1 -1
  14. package/.next/prerender-manifest.json +1 -1
  15. package/.next/required-server-files.json +1 -1
  16. package/.next/routes-manifest.json +1 -1
  17. package/.next/server/chunks/176.js +4603 -395
  18. package/.next/server/chunks/664.js +27 -2414
  19. package/.next/server/chunks/859.js +29 -1
  20. package/.next/server/font-loader-manifest.js +1 -0
  21. package/.next/server/font-loader-manifest.json +6 -0
  22. package/.next/server/middleware-build-manifest.js +1 -1
  23. package/.next/server/pages/404.html +2 -2
  24. package/.next/server/pages/404.js.nft.json +1 -1
  25. package/.next/server/pages/500.html +1 -12
  26. package/.next/server/pages/_app.js +176 -13
  27. package/.next/server/pages/_app.js.nft.json +1 -1
  28. package/.next/server/pages/_document.js +1 -1
  29. package/.next/server/pages/_document.js.nft.json +1 -1
  30. package/.next/server/pages/_error.js +133 -17
  31. package/.next/server/pages/_error.js.nft.json +1 -1
  32. package/.next/server/pages/api/solve.js +16 -0
  33. package/.next/server/pages/index.html +1 -9
  34. package/.next/server/pages/index.js +52 -165
  35. package/.next/server/pages/index.js.nft.json +1 -1
  36. package/.next/server/pages/index.json +1 -1
  37. package/.next/server/pages-manifest.json +1 -1
  38. package/.next/static/chunks/main-74c4d6b2b5c362f3.js +1 -0
  39. package/.next/static/chunks/pages/{404-67383848027ec49b.js → 404-d5ff00df1c687977.js} +1 -1
  40. package/.next/static/chunks/pages/_app-52cb288dc680bdfe.js +28 -0
  41. package/.next/static/chunks/pages/index-5c2544930e46c5ce.js +1 -0
  42. package/.next/static/chunks/webpack-6ef43a8d4a395f49.js +1 -0
  43. package/.next/static/css/ec4e47a6b1866fe5.css +1 -0
  44. package/.next/static/css/f65b7b2a74f57c1c.css +2 -0
  45. package/.next/static/fZRsz4P0gQ8Wgb9jP8eap/_buildManifest.js +1 -0
  46. package/.next/trace +55 -55
  47. package/package.json +12 -10
  48. package/src/components/Badge/Badge.module.scss +1 -1
  49. package/src/components/Board/Board.module.scss +14 -0
  50. package/src/components/Board/Board.tsx +117 -19
  51. package/src/components/Board/BoardPure.tsx +7 -15
  52. package/src/components/Board/components/Actions/Actions.module.scss +64 -0
  53. package/src/components/Board/components/Actions/Actions.tsx +68 -0
  54. package/src/components/Board/components/Actions/index.ts +1 -0
  55. package/src/components/Board/components/Cell/Cell.module.scss +22 -165
  56. package/src/components/Board/components/Cell/Cell.tsx +0 -37
  57. package/src/components/Board/components/Cell/CellPure.tsx +5 -75
  58. package/src/components/Board/components/index.ts +1 -0
  59. package/src/components/Board/hooks/useGrid.ts +16 -16
  60. package/src/components/Button/Button.module.scss +3 -3
  61. package/src/components/Checkbox/Checkbox.tsx +1 -4
  62. package/src/components/Dictionary/Dictionary.tsx +28 -30
  63. package/src/components/DictionaryInput/DictionaryInput.tsx +3 -0
  64. package/src/components/Key/Key.module.scss +1 -1
  65. package/src/components/LogoSplashScreen/LogoSplashScreen.module.scss +1 -1
  66. package/src/components/Modal/Modal.module.scss +4 -2
  67. package/src/components/Rack/Rack.module.scss +5 -0
  68. package/src/components/Radio/Radio.tsx +1 -4
  69. package/src/components/Results/Results.module.scss +2 -2
  70. package/src/components/SeoMessage/SeoMessage.tsx +19 -0
  71. package/src/components/SeoMessage/index.ts +1 -0
  72. package/src/components/Solver/Solver.module.scss +0 -5
  73. package/src/components/Solver/Solver.tsx +1 -1
  74. package/src/components/Solver/components/EmptyState/EmptyState.module.scss +1 -1
  75. package/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.module.scss +9 -2
  76. package/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.tsx +2 -1
  77. package/src/components/Tile/Tile.module.scss +23 -11
  78. package/src/components/Tile/Tile.tsx +26 -9
  79. package/src/components/Tile/TilePure.tsx +9 -4
  80. package/src/components/Tooltip/Tooltip.module.scss +7 -7
  81. package/src/components/index.ts +1 -0
  82. package/src/hooks/useLocalStorage/useLocalStorageBoard.ts +6 -3
  83. package/src/hooks/useLocalStorage/useLocalStorageConfigId.ts +6 -3
  84. package/src/hooks/useLocalStorage/useLocalStorageLocale.ts +6 -3
  85. package/src/hooks/useLocalStorage/useLocalStorageRack.ts +6 -3
  86. package/src/i18n/de.json +1 -0
  87. package/src/i18n/en.json +1 -0
  88. package/src/i18n/es.json +1 -0
  89. package/src/i18n/fa.json +1 -0
  90. package/src/i18n/fr.json +1 -0
  91. package/src/i18n/pl.json +1 -0
  92. package/src/icons/Flag.svg +2 -2
  93. package/src/icons/FlagFill.svg +4 -0
  94. package/src/icons/Square.svg +4 -0
  95. package/src/icons/SquareFill.svg +4 -0
  96. package/src/icons/index.ts +3 -0
  97. package/src/modals/RemainingTilesModal/components/Character/Character.module.scss +1 -1
  98. package/src/modals/ResultsModal/ResultsModal.module.scss +1 -1
  99. package/src/modals/SettingsModal/components/AutoGroupTilesSetting/AutoGroupTilesSetting.tsx +1 -2
  100. package/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.module.scss +1 -1
  101. package/src/modals/SettingsModal/components/ConfigSetting/ConfigSetting.tsx +1 -2
  102. package/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.module.scss +14 -24
  103. package/src/modals/SettingsModal/components/LocaleSetting/LocaleSetting.tsx +1 -2
  104. package/src/pages/_app.tsx +9 -5
  105. package/src/pages/index.module.scss +1 -2
  106. package/src/pages/index.tsx +10 -8
  107. package/src/parameters/index.ts +12 -0
  108. package/src/state/slices/boardSlice.ts +5 -5
  109. package/src/styles/animations.scss +10 -0
  110. package/src/styles/global.scss +2 -2
  111. package/src/styles/mixins.scss +60 -3
  112. package/src/styles/variables.scss +43 -33
  113. package/src/types/index.ts +1 -0
  114. package/.next/server/chunks/210.js +0 -122
  115. package/.next/server/chunks/579.js +0 -3925
  116. package/.next/server/chunks/676.js +0 -32
  117. package/.next/static/6RggBFm8kHrh-k1-CG3um/_buildManifest.js +0 -1
  118. package/.next/static/chunks/490-d29992f1c264d70e.js +0 -5
  119. package/.next/static/chunks/509-6ad4482d4351452c.js +0 -1
  120. package/.next/static/chunks/main-f11614d8aa7ee555.js +0 -1
  121. package/.next/static/chunks/pages/_app-c58cfa832b76cc87.js +0 -24
  122. package/.next/static/chunks/pages/index-146039f501e49c08.js +0 -1
  123. package/.next/static/chunks/webpack-59c5c889f52620d6.js +0 -1
  124. package/.next/static/css/4482c4a0064d3807.css +0 -1
  125. package/.next/static/css/78e42ad01f580f64.css +0 -1
  126. package/.next/static/css/9d1013ec684361b9.css +0 -1
  127. package/src/components/Board/components/Cell/Button.tsx +0 -32
  128. /package/.next/static/{6RggBFm8kHrh-k1-CG3um → fZRsz4P0gQ8Wgb9jP8eap}/_ssgManifest.js +0 -0
@@ -1,13 +1,12 @@
1
1
  @import 'styles/mixins';
2
2
 
3
- $icon-size: 16px;
4
-
5
3
  .cell {
6
4
  @include focus-effect;
5
+ @include lighthouse-input-size-hack;
7
6
 
8
7
  position: relative;
9
8
  display: table-cell;
10
- background-color: white;
9
+ background-color: var(--color--white);
11
10
  border-bottom: var(--border--width) dotted var(--border--color--light);
12
11
  transition: var(--transition);
13
12
  background-clip: padding-box;
@@ -36,64 +35,64 @@ $icon-size: 16px;
36
35
 
37
36
  &.bonusStart {
38
37
  &::before {
39
- background-color: var(--color--violet--light);
38
+ background-color: var(--color--bonus--start);
40
39
  }
41
40
  }
42
41
 
43
42
  &.bonusCharacter1 {
44
43
  &::before {
45
- background-color: var(--color--yellow--light);
44
+ background-color: var(--color--bonus--character--1);
46
45
  }
47
46
  }
48
47
 
49
48
  &.bonusCharacter2 {
50
49
  &::before {
51
- background-color: var(--color--green--light);
50
+ background-color: var(--color--bonus--character--2);
52
51
  }
53
52
  }
54
53
 
55
54
  &.bonusCharacter3 {
56
55
  &::before {
57
- background-color: var(--color--blue--light);
56
+ background-color: var(--color--bonus--character--3);
58
57
  }
59
58
  }
60
59
 
61
60
  &.bonusCharacter5 {
62
61
  &::before {
63
- background-color: var(--color--red--light);
62
+ background-color: var(--color--bonus--character--5);
64
63
  }
65
64
  }
66
65
 
67
66
  &.bonusCharacterMultiplier2 {
68
67
  &::before {
69
- background-color: var(--color--light-blue--light);
68
+ background-color: var(--color--bonus--character-multiplier--2);
70
69
  }
71
70
  }
72
71
 
73
72
  &.bonusCharacterMultiplier3 {
74
73
  &::before {
75
- background-color: var(--color--dark-blue--light);
74
+ background-color: var(--color--bonus--character-multiplier--3);
76
75
  }
77
76
  }
78
77
 
79
78
  &.bonusWord2 {
80
79
  &::before {
81
80
  content: 'x2';
82
- background-color: var(--color--orange);
81
+ background-color: var(--color--bonus--word-multiplier--2);
83
82
  }
84
83
  }
85
84
 
86
85
  &.bonusWord3 {
87
86
  &::before {
88
87
  content: 'x3';
89
- background-color: var(--color--pink);
88
+ background-color: var(--color--bonus--word-multiplier--3);
90
89
  }
91
90
  }
92
91
 
93
- &.candidate {
92
+ &.filtered {
94
93
  &::before {
95
94
  content: ' ';
96
- background-color: var(--color--primary);
95
+ background-color: var(--color--foreground--secondary);
97
96
  }
98
97
  }
99
98
 
@@ -112,169 +111,27 @@ $icon-size: 16px;
112
111
  pointer-events: none;
113
112
  font-size: 60%;
114
113
  font-weight: bold;
115
- color: white;
114
+ color: var(--color--white);
116
115
  content: ' ';
117
116
 
118
117
  [lang='fa-IR'] & {
119
- font-family: 'Open Sans', sans-serif;
118
+ font-family: var(--font--family--latin);
120
119
  }
121
120
  }
122
121
 
123
122
  &:focus-within {
124
- z-index: 1;
125
-
126
- .actions {
127
- display: flex;
128
- }
129
-
130
- .action {
131
- user-select: initial;
132
- pointer-events: auto;
133
- }
134
- }
135
- }
136
-
137
- .actions {
138
- display: none;
139
- position: absolute;
140
- top: -$icon-size;
141
- z-index: 2;
142
- transition: var(--transition);
143
- pointer-events: none;
144
- box-shadow: var(--box-shadow);
145
- border-radius: var(--border--radius);
146
-
147
- [dir='ltr'] & {
148
- left: calc(100% + var(--spacing--s) - #{$icon-size});
149
- }
150
-
151
- [dir='rtl'] & {
152
- right: calc(100% + var(--spacing--s) - #{$icon-size});
123
+ z-index: 2;
153
124
  }
154
125
  }
155
126
 
156
- .action {
157
- @include button-reset;
158
-
159
- display: flex;
160
- justify-content: center;
161
- padding: var(--spacing--s);
162
- user-select: none;
163
- pointer-events: none;
164
- box-sizing: content-box;
165
- background-color: white;
166
- border: var(--border);
167
- font-size: var(--font--size--m);
168
- line-height: $icon-size;
169
- color: var(--color--foreground--secondary);
170
- transition: var(--transition);
171
- cursor: pointer;
172
-
173
- & + & {
174
- [dir='ltr'] & {
175
- border-left: none;
176
- }
177
-
178
- [dir='rtl'] & {
179
- border-right: none;
180
- }
181
- }
182
-
183
- [dir='ltr'] & {
184
- &:first-child {
185
- border-top-left-radius: var(--border--radius);
186
- border-bottom-left-radius: var(--border--radius);
187
- }
188
-
189
- &:last-child {
190
- border-top-right-radius: var(--border--radius);
191
- border-bottom-right-radius: var(--border--radius);
192
- }
193
- }
194
-
195
- [dir='rtl'] & {
196
- &:first-child {
197
- border-top-right-radius: var(--border--radius);
198
- border-bottom-right-radius: var(--border--radius);
199
- }
200
-
201
- &:last-child {
202
- border-top-left-radius: var(--border--radius);
203
- border-bottom-left-radius: var(--border--radius);
204
- }
205
- }
206
-
207
- &,
208
- .filterCell,
209
- .toggleDirection {
210
- width: $icon-size;
211
- height: $icon-size;
212
- }
213
-
214
- &:active,
215
- &:hover {
216
- color: var(--color--foreground);
217
- }
218
- }
219
-
220
- .toggleDirection {
221
- transition: var(--transition);
222
-
223
- &.right {
224
- transform: rotate(-90deg);
225
-
226
- [dir='rtl'] & {
227
- transform: rotate(90deg);
228
- }
229
- }
230
- }
231
-
232
- .blank {
233
- user-select: none;
234
-
235
- &.active {
236
- font-weight: bold;
237
- }
238
- }
239
-
240
- .filterCell {
241
- color: var(--color--inactive);
242
-
243
- &.filtered {
244
- color: var(--color--foreground--secondary);
245
- }
246
- }
247
-
248
- .iconContainer {
249
- position: absolute;
250
- top: 0;
251
- right: 0;
252
- bottom: 0;
253
- left: 0;
254
- display: flex;
255
- align-items: center;
256
- justify-content: center;
257
- }
258
-
259
- .flagContainer {
260
- background-color: var(--color--primary);
261
- }
262
-
263
- .flag,
264
- .star {
265
- color: white;
266
- }
267
-
268
- .star {
127
+ .icon {
269
128
  $size: 40%;
270
129
 
130
+ position: absolute;
131
+ top: 50%;
132
+ left: 50%;
271
133
  width: $size;
272
134
  height: $size;
273
- }
274
-
275
- .flag {
276
- $size: 50%;
277
-
278
- width: $size;
279
- height: $size;
135
+ transform: translate(-50%, -50%);
136
+ color: var(--color--white);
280
137
  }
@@ -1,12 +1,9 @@
1
1
  import { EMPTY_CELL } from '@scrabble-solver/constants';
2
2
  import { Cell as CellModel } from '@scrabble-solver/types';
3
3
  import { ChangeEventHandler, FunctionComponent, RefObject, useCallback, useMemo } from 'react';
4
- import { useDispatch } from 'react-redux';
5
4
 
6
5
  import { getTileSizes } from 'lib';
7
6
  import {
8
- boardSlice,
9
- cellFilterSlice,
10
7
  selectCellBonus,
11
8
  selectCellIsFiltered,
12
9
  selectCellIsValid,
@@ -21,32 +18,27 @@ import CellPure from './CellPure';
21
18
  interface Props {
22
19
  cell: CellModel;
23
20
  className?: string;
24
- direction: 'horizontal' | 'vertical';
25
21
  inputRef: RefObject<HTMLInputElement>;
26
22
  isBottom: boolean;
27
23
  isCenter: boolean;
28
24
  isRight: boolean;
29
25
  size: number;
30
26
  onChange: ChangeEventHandler<HTMLInputElement>;
31
- onDirectionToggle: () => void;
32
27
  onFocus: (x: number, y: number) => void;
33
28
  }
34
29
 
35
30
  const Cell: FunctionComponent<Props> = ({
36
31
  cell,
37
32
  className,
38
- direction,
39
33
  inputRef,
40
34
  isBottom,
41
35
  isCenter,
42
36
  isRight,
43
37
  size,
44
38
  onChange,
45
- onDirectionToggle,
46
39
  onFocus,
47
40
  }) => {
48
41
  const { tile, x, y } = cell;
49
- const dispatch = useDispatch();
50
42
  const translate = useTranslate();
51
43
  const locale = useTypedSelector(selectLocale);
52
44
  const bonus = useTypedSelector((state) => selectCellBonus(state, cell));
@@ -57,32 +49,8 @@ const Cell: FunctionComponent<Props> = ({
57
49
  const isEmpty = tile.character === EMPTY_CELL;
58
50
  const style = useMemo(() => ({ fontSize: tileFontSize }), [tileFontSize]);
59
51
 
60
- const handleDirectionToggleClick = useCallback(() => {
61
- if (inputRef.current) {
62
- inputRef.current.focus();
63
- }
64
-
65
- onDirectionToggle();
66
- }, [onDirectionToggle]);
67
-
68
52
  const handleFocus = useCallback(() => onFocus(x, y), [x, y, onFocus]);
69
53
 
70
- const handleToggleBlankClick = useCallback(() => {
71
- if (inputRef.current) {
72
- inputRef.current.focus();
73
- }
74
-
75
- dispatch(boardSlice.actions.toggleCellIsBlank({ x, y }));
76
- }, [dispatch, x, y]);
77
-
78
- const handleToggleFilterCellClick = useCallback(() => {
79
- if (inputRef.current) {
80
- inputRef.current.focus();
81
- }
82
-
83
- dispatch(cellFilterSlice.actions.toggle({ x, y }));
84
- }, [dispatch, x, y]);
85
-
86
54
  return (
87
55
  <CellPure
88
56
  aria-label={translate('cell.tile.location', {
@@ -92,7 +60,6 @@ const Cell: FunctionComponent<Props> = ({
92
60
  bonus={bonus}
93
61
  cell={cell}
94
62
  className={className}
95
- direction={direction}
96
63
  inputRef={inputRef}
97
64
  isBottom={isBottom}
98
65
  isCenter={isCenter}
@@ -104,12 +71,8 @@ const Cell: FunctionComponent<Props> = ({
104
71
  size={size}
105
72
  style={style}
106
73
  tile={tile}
107
- translate={translate}
108
74
  onChange={onChange}
109
- onDirectionToggleClick={handleDirectionToggleClick}
110
75
  onFocus={handleFocus}
111
- onToggleBlankClick={handleToggleBlankClick}
112
- onToggleFilterCellClick={handleToggleFilterCellClick}
113
76
  />
114
77
  );
115
78
  };
@@ -1,21 +1,11 @@
1
1
  import { Bonus, Cell, Tile as TileModel } from '@scrabble-solver/types';
2
2
  import classNames from 'classnames';
3
- import {
4
- ChangeEventHandler,
5
- CSSProperties,
6
- FocusEventHandler,
7
- FunctionComponent,
8
- memo,
9
- MouseEventHandler,
10
- RefObject,
11
- } from 'react';
3
+ import { ChangeEventHandler, CSSProperties, FocusEventHandler, FunctionComponent, memo, RefObject } from 'react';
12
4
 
13
- import { ArrowDown, Flag, Star } from 'icons';
14
- import { Translate } from 'types';
5
+ import { FlagFill, Star } from 'icons';
15
6
 
16
7
  import Tile from '../../../Tile';
17
8
 
18
- import Button from './Button';
19
9
  import styles from './Cell.module.scss';
20
10
  import { getBonusClassname } from './lib';
21
11
 
@@ -24,7 +14,6 @@ interface Props {
24
14
  bonus: Bonus | undefined;
25
15
  cell: Cell;
26
16
  className?: string;
27
- direction: 'horizontal' | 'vertical';
28
17
  inputRef: RefObject<HTMLInputElement>;
29
18
  isBottom: boolean;
30
19
  isCenter: boolean;
@@ -36,12 +25,8 @@ interface Props {
36
25
  size: number;
37
26
  style?: CSSProperties;
38
27
  tile: TileModel;
39
- translate: Translate;
40
28
  onChange: ChangeEventHandler<HTMLInputElement>;
41
- onDirectionToggleClick: MouseEventHandler<HTMLButtonElement>;
42
29
  onFocus: FocusEventHandler<HTMLInputElement>;
43
- onToggleBlankClick: MouseEventHandler<HTMLButtonElement>;
44
- onToggleFilterCellClick: MouseEventHandler<HTMLButtonElement>;
45
30
  }
46
31
 
47
32
  const CellPure: FunctionComponent<Props> = ({
@@ -49,7 +34,6 @@ const CellPure: FunctionComponent<Props> = ({
49
34
  bonus,
50
35
  cell,
51
36
  className,
52
- direction,
53
37
  inputRef,
54
38
  isBottom,
55
39
  isCenter,
@@ -61,32 +45,20 @@ const CellPure: FunctionComponent<Props> = ({
61
45
  size,
62
46
  style,
63
47
  tile,
64
- translate,
65
48
  onChange,
66
- onDirectionToggleClick,
67
49
  onFocus,
68
- onToggleBlankClick,
69
- onToggleFilterCellClick,
70
50
  }) => (
71
51
  <div
72
52
  className={classNames(styles.cell, className, getBonusClassname(cell, bonus, isCenter), {
73
53
  [styles.bottom]: isBottom,
74
- [styles.candidate]: cell.isCandidate(),
54
+ [styles.filtered]: isFiltered,
75
55
  [styles.right]: isRight,
76
56
  })}
77
57
  style={style}
78
58
  >
79
- {isCenter && isEmpty && (
80
- <div className={classNames(styles.iconContainer)}>
81
- <Star className={styles.star} />
82
- </div>
83
- )}
59
+ {isCenter && isEmpty && !isFiltered && <Star className={styles.icon} />}
84
60
 
85
- {isFiltered && (
86
- <div className={classNames(styles.iconContainer, styles.flagContainer)}>
87
- <Flag className={styles.flag} />
88
- </div>
89
- )}
61
+ {isFiltered && <FlagFill className={styles.icon} />}
90
62
 
91
63
  <Tile
92
64
  aria-label={ariaLabel}
@@ -103,48 +75,6 @@ const CellPure: FunctionComponent<Props> = ({
103
75
  onChange={onChange}
104
76
  onFocus={onFocus}
105
77
  />
106
-
107
- {!cell.isCandidate() && (
108
- <div className={styles.actions}>
109
- <Button
110
- aria-label={translate('cell.toggle-direction')}
111
- tooltip={translate('cell.toggle-direction')}
112
- onClick={onDirectionToggleClick}
113
- >
114
- <ArrowDown
115
- className={classNames(styles.toggleDirection, {
116
- [styles.right]: direction === 'horizontal',
117
- })}
118
- />
119
- </Button>
120
-
121
- {isEmpty && (
122
- <Button
123
- aria-label={translate('cell.filter-cell')}
124
- className={classNames(styles.filterCell, {
125
- [styles.filtered]: isFiltered,
126
- })}
127
- tooltip={translate('cell.filter-cell')}
128
- onClick={onToggleFilterCellClick}
129
- >
130
- <Flag />
131
- </Button>
132
- )}
133
-
134
- {!isEmpty && (
135
- <Button
136
- aria-label={tile.isBlank ? translate('cell.set-not-blank') : translate('cell.set-blank')}
137
- className={classNames(styles.blank, {
138
- [styles.active]: tile.isBlank,
139
- })}
140
- tooltip={tile.isBlank ? translate('cell.set-not-blank') : translate('cell.set-blank')}
141
- onClick={onToggleBlankClick}
142
- >
143
- B
144
- </Button>
145
- )}
146
- </div>
147
- )}
148
78
  </div>
149
79
  );
150
80
 
@@ -1 +1,2 @@
1
+ export { default as Actions } from './Actions';
1
2
  export { default as Cell } from './Cell';
@@ -2,16 +2,15 @@
2
2
  import { BLANK, EMPTY_CELL } from '@scrabble-solver/constants';
3
3
  import { Board, Cell } from '@scrabble-solver/types';
4
4
  import {
5
+ ChangeEvent,
6
+ ChangeEventHandler,
7
+ ClipboardEventHandler,
5
8
  createRef,
6
9
  KeyboardEventHandler,
7
10
  RefObject,
8
11
  useCallback,
9
12
  useMemo,
10
13
  useState,
11
- useRef,
12
- ChangeEventHandler,
13
- ChangeEvent,
14
- ClipboardEventHandler,
15
14
  } from 'react';
16
15
  import { useDispatch } from 'react-redux';
17
16
  import { useLatest } from 'react-use';
@@ -28,8 +27,9 @@ import { Point } from '../types';
28
27
  const toggleDirection = (direction: Direction) => (direction === 'vertical' ? 'horizontal' : 'vertical');
29
28
 
30
29
  interface State {
30
+ activeIndex: Point;
31
31
  direction: Direction;
32
- refs: RefObject<HTMLInputElement>[][];
32
+ inputRefs: RefObject<HTMLInputElement>[][];
33
33
  }
34
34
 
35
35
  interface Actions {
@@ -46,29 +46,29 @@ const useGrid = (rows: Cell[][]): [State, Actions] => {
46
46
  const dispatch = useDispatch();
47
47
  const config = useTypedSelector(selectConfig);
48
48
  const locale = useTypedSelector(selectLocale);
49
- const refs = useMemo(
49
+ const inputRefs = useMemo(
50
50
  () => createGridOf<RefObject<HTMLInputElement>>(width, height, () => createRef()),
51
51
  [width, height],
52
52
  );
53
- const activeIndexRef = useRef<Point>({ x: 0, y: 0 });
53
+ const [activeIndex, setActiveIndex] = useState<Point>({ x: 0, y: 0 });
54
54
  const [direction, setLastDirection] = useState<Direction>('horizontal');
55
55
  const directionRef = useLatest(direction);
56
56
 
57
57
  const changeActiveIndex = useCallback(
58
58
  (offsetX: number, offsetY: number) => {
59
- const x = Math.min(Math.max(activeIndexRef.current.x + offsetX, 0), width - 1);
60
- const y = Math.min(Math.max(activeIndexRef.current.y + offsetY, 0), height - 1);
61
- activeIndexRef.current = { x, y };
62
- refs[y][x].current?.focus();
59
+ const x = Math.min(Math.max(activeIndex.x + offsetX, 0), width - 1);
60
+ const y = Math.min(Math.max(activeIndex.y + offsetY, 0), height - 1);
61
+ setActiveIndex({ x, y });
62
+ inputRefs[y][x].current?.focus();
63
63
  },
64
- [activeIndexRef, refs],
64
+ [activeIndex, inputRefs],
65
65
  );
66
66
 
67
67
  const getInputRefPosition = useCallback(
68
68
  (inputRef: HTMLInputElement): Point | undefined => {
69
- return getPositionInGrid(refs, (ref) => ref.current === inputRef);
69
+ return getPositionInGrid(inputRefs, (ref) => ref.current === inputRef);
70
70
  },
71
- [refs],
71
+ [inputRefs],
72
72
  );
73
73
 
74
74
  const moveFocus = useCallback(
@@ -217,7 +217,7 @@ const useGrid = (rows: Cell[][]): [State, Actions] => {
217
217
  const onDirectionToggle = useCallback(() => setLastDirection(toggleDirection), []);
218
218
 
219
219
  const onFocus = useCallback((x: number, y: number) => {
220
- activeIndexRef.current = { x, y };
220
+ setActiveIndex({ x, y });
221
221
  }, []);
222
222
 
223
223
  const onKeyDown = useMemo(() => {
@@ -356,7 +356,7 @@ const useGrid = (rows: Cell[][]): [State, Actions] => {
356
356
  );
357
357
 
358
358
  return [
359
- { direction, refs },
359
+ { activeIndex, direction, inputRefs },
360
360
  { onChange, onDirectionToggle, onFocus, onKeyDown, onPaste },
361
361
  ];
362
362
  };
@@ -21,15 +21,15 @@
21
21
 
22
22
  &.primary {
23
23
  background-color: var(--color--primary);
24
- color: white;
24
+ color: var(--color--primary--opposite);
25
25
  }
26
26
 
27
27
  &.default {
28
- background-color: var(--color--background--overlay);
28
+ background-color: var(--color--background--element);
29
29
  color: var(--color--foreground);
30
30
 
31
31
  .icon {
32
- color: var(--color--inactive);
32
+ color: var(--color--foreground--secondary);
33
33
  }
34
34
  }
35
35
  }
@@ -10,23 +10,20 @@ interface Props {
10
10
  children?: ReactNode;
11
11
  className?: string;
12
12
  disabled?: boolean;
13
- id: string;
14
13
  name: string;
15
14
  onChange: ChangeEventHandler<HTMLInputElement>;
16
15
  }
17
16
 
18
- const Checkbox: FunctionComponent<Props> = ({ checked, children, className, disabled, id, name, onChange }) => (
17
+ const Checkbox: FunctionComponent<Props> = ({ checked, children, className, disabled, name, onChange }) => (
19
18
  <label
20
19
  className={classNames(styles.checkbox, className, {
21
20
  [styles.checked]: checked,
22
21
  })}
23
- htmlFor={id}
24
22
  >
25
23
  <input
26
24
  checked={checked}
27
25
  className={styles.input}
28
26
  disabled={disabled}
29
- id={id}
30
27
  name={name}
31
28
  type="checkbox"
32
29
  onChange={onChange}