@scrabble-solver/scrabble-solver 2.13.6 → 2.13.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +11 -11
- package/.next/cache/.tsbuildinfo +1 -1
- package/.next/cache/eslint/.cache_8dgz12 +1 -1
- package/.next/cache/webpack/client-production/0.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/edge-server-production/0.pack +0 -0
- package/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/0.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/prerender-manifest.js +1 -1
- package/.next/prerender-manifest.json +1 -1
- package/.next/routes-manifest.json +1 -1
- package/.next/server/chunks/577.js +1 -1
- package/.next/server/chunks/807.js +1 -1
- package/.next/server/chunks/977.js +1 -1
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/pages/_app.js +1 -1
- package/.next/server/pages/_error.js +1 -1
- package/.next/server/pages/api/solve.js +1 -1
- package/.next/server/pages/index.html +1 -1
- package/.next/server/pages/index.js +1 -1
- package/.next/server/pages/index.json +1 -1
- package/.next/server/pages-manifest.json +1 -1
- package/.next/static/7zESQYo9UAqNh9LV0b7Sd/_buildManifest.js +1 -0
- package/.next/static/chunks/{main-6e708370ad13b1f9.js → main-b5b360c6afb66b05.js} +1 -1
- package/.next/static/chunks/pages/{404-129e0943628b6fab.js → 404-63b972b24be99c62.js} +1 -1
- package/.next/static/chunks/pages/_app-a2848b7efa6bb6b0.js +17 -0
- package/.next/static/chunks/pages/index-7b73be2915cc7099.js +1 -0
- package/.next/static/css/6682db14f926d4c7.css +1 -0
- package/.next/static/css/b37850c8d5270d91.css +2 -0
- package/.next/trace +44 -44
- package/package.json +12 -13
- package/src/components/Alert/Alert.module.scss +3 -12
- package/src/components/Board/Board.module.scss +1 -4
- package/src/components/Board/BoardPure.tsx +1 -1
- package/src/components/Board/components/Actions/Actions.module.scss +7 -27
- package/src/components/Board/components/Cell/Cell.module.scss +5 -32
- package/src/components/Board/components/InputPrompt/InputPrompt.module.scss +4 -18
- package/src/components/Board/hooks/useBackgroundImage.tsx +15 -4
- package/src/components/Board/hooks/useGrid.ts +13 -5
- package/src/components/Board/lib/index.ts +0 -1
- package/src/components/Button/Button.module.scss +1 -8
- package/src/components/Button/Button.tsx +16 -17
- package/src/components/Button/Link.tsx +15 -16
- package/src/components/Dictionary/Dictionary.module.scss +1 -8
- package/src/components/IconButton/IconButton.tsx +8 -8
- package/src/components/IconButton/Link.tsx +8 -8
- package/src/components/Loading/Loading.module.scss +1 -4
- package/src/components/Modal/Modal.module.scss +2 -16
- package/src/components/Rack/Rack.module.scss +4 -18
- package/src/components/Rack/components/InputPrompt/InputPrompt.module.scss +1 -4
- package/src/components/Results/Cell.tsx +4 -5
- package/src/components/Results/HeaderButton.tsx +25 -22
- package/src/components/Results/Result.tsx +15 -3
- package/src/components/Results/Results.module.scss +31 -48
- package/src/components/Results/Results.tsx +1 -1
- package/src/components/Results/getCoordinatesColumn.ts +15 -0
- package/src/components/Results/getLocaleColumns.ts +7 -0
- package/src/components/Results/types.ts +1 -0
- package/src/components/Results/useColumns.ts +10 -7
- package/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.module.scss +9 -40
- package/src/components/Tile/Tile.module.scss +6 -26
- package/src/components/Tooltip/Tooltip.tsx +28 -0
- package/src/components/Tooltip/TooltipContent.tsx +53 -0
- package/src/components/Tooltip/TooltipTrigger.tsx +26 -0
- package/src/components/Tooltip/context.ts +17 -0
- package/src/components/Tooltip/index.ts +1 -1
- package/src/components/Tooltip/useTooltip.ts +54 -0
- package/src/components/index.ts +1 -2
- package/src/hooks/index.ts +0 -1
- package/src/i18n/languages/german.json +1 -1
- package/src/icons/index.ts +0 -2
- package/src/lib/getCoordinates.ts +18 -0
- package/src/lib/groupResults.ts +16 -11
- package/src/lib/index.ts +2 -1
- package/src/lib/sortResults.ts +1 -0
- package/src/modals/KeyMapModal/components/Mapping/Mapping.module.scss +2 -2
- package/src/modals/MenuModal/MenuModal.module.scss +2 -15
- package/src/modals/RemainingTilesModal/RemainingTilesModal.module.scss +1 -7
- package/src/modals/WordsModal/WordsModal.module.scss +2 -15
- package/src/pages/_app.tsx +5 -1
- package/src/parameters/index.ts +1 -0
- package/src/styles/mixins.scss +2 -5
- package/src/types/index.ts +1 -0
- package/.next/static/4GWIKe7khKxREyq3ZamDK/_buildManifest.js +0 -1
- package/.next/static/chunks/pages/_app-cccda36d00fa2328.js +0 -17
- package/.next/static/chunks/pages/index-caaf20b2488cb10e.js +0 -1
- package/.next/static/css/11366b7489cf90ac.css +0 -1
- package/.next/static/css/f549d7823f599b8d.css +0 -2
- package/src/components/Checkbox/Checkbox.module.scss +0 -45
- package/src/components/Checkbox/Checkbox.tsx +0 -38
- package/src/components/Checkbox/index.ts +0 -1
- package/src/components/Tooltip/useTooltip.tsx +0 -134
- package/src/hooks/usePortal.tsx +0 -47
- package/src/icons/CheckboxChecked.svg +0 -4
- package/src/icons/CheckboxEmpty.svg +0 -4
- package/src/lib/canUseDom.ts +0 -3
- /package/.next/static/{4GWIKe7khKxREyq3ZamDK → 7zESQYo9UAqNh9LV0b7Sd}/_ssgManifest.js +0 -0
- /package/src/{components/Board/lib → lib}/getCoordinate.ts +0 -0
|
@@ -6,45 +6,48 @@ import { SortDown, SortUp } from 'icons';
|
|
|
6
6
|
import { resultsSlice, selectResultsSort, useTranslate, useTypedSelector } from 'state';
|
|
7
7
|
import { SortDirection } from 'types';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { Tooltip } from '../Tooltip';
|
|
10
10
|
|
|
11
11
|
import styles from './Results.module.scss';
|
|
12
12
|
import { Column } from './types';
|
|
13
13
|
|
|
14
14
|
interface Props {
|
|
15
15
|
column: Column;
|
|
16
|
+
sortable?: boolean;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
const HeaderButton = ({ column }: Props): ReactElement => {
|
|
19
|
+
const HeaderButton = ({ column, sortable }: Props): ReactElement => {
|
|
19
20
|
const dispatch = useDispatch();
|
|
20
21
|
const translate = useTranslate();
|
|
21
22
|
const sort = useTypedSelector(selectResultsSort);
|
|
22
|
-
const triggerProps = useTooltip(translate(column.translationKey));
|
|
23
23
|
|
|
24
24
|
const handleClick = useCallback(() => {
|
|
25
25
|
dispatch(resultsSlice.actions.sort(column.id));
|
|
26
26
|
}, [column.id, dispatch]);
|
|
27
27
|
|
|
28
28
|
return (
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
29
|
+
<Tooltip tooltip={translate(column.translationKey)}>
|
|
30
|
+
<button
|
|
31
|
+
aria-label={translate(column.translationKey)}
|
|
32
|
+
className={classNames(styles.headerButton, column.className, {
|
|
33
|
+
[styles.sortable]: sortable,
|
|
34
|
+
})}
|
|
35
|
+
key={column.id}
|
|
36
|
+
type="button"
|
|
37
|
+
onClick={sortable ? handleClick : undefined}
|
|
38
|
+
>
|
|
39
|
+
<span className={styles.cell}>
|
|
40
|
+
<span className={styles.headerButtonLabel}>{translate(column.translationKey)}</span>
|
|
41
|
+
|
|
42
|
+
{sort.column === column.id && (
|
|
43
|
+
<>
|
|
44
|
+
{sort.direction === SortDirection.Ascending && <SortUp className={styles.sortIcon} />}
|
|
45
|
+
{sort.direction === SortDirection.Descending && <SortDown className={styles.sortIcon} />}
|
|
46
|
+
</>
|
|
47
|
+
)}
|
|
48
|
+
</span>
|
|
49
|
+
</button>
|
|
50
|
+
</Tooltip>
|
|
48
51
|
);
|
|
49
52
|
};
|
|
50
53
|
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import classNames from 'classnames';
|
|
2
|
-
import { CSSProperties, FocusEventHandler, MouseEventHandler, ReactElement, useRef } from 'react';
|
|
2
|
+
import { CSSProperties, FocusEventHandler, MouseEventHandler, ReactElement, useMemo, useRef } from 'react';
|
|
3
3
|
import Highlighter from 'react-highlight-words';
|
|
4
4
|
|
|
5
5
|
import { LOCALE_FEATURES } from 'i18n';
|
|
6
|
-
import { noop } from 'lib';
|
|
7
|
-
import {
|
|
6
|
+
import { getCoordinates, noop } from 'lib';
|
|
7
|
+
import {
|
|
8
|
+
selectIsResultMatching,
|
|
9
|
+
selectLocale,
|
|
10
|
+
selectResultsQuery,
|
|
11
|
+
selectShowCoordinates,
|
|
12
|
+
useTypedSelector,
|
|
13
|
+
} from 'state';
|
|
8
14
|
import { ResultColumn } from 'types';
|
|
9
15
|
|
|
10
16
|
import Cell from './Cell';
|
|
@@ -31,12 +37,14 @@ const Result = ({ data, index, style }: Props): ReactElement => {
|
|
|
31
37
|
const ref = useRef<HTMLButtonElement>(null);
|
|
32
38
|
const columns = useColumns();
|
|
33
39
|
const locale = useTypedSelector(selectLocale);
|
|
40
|
+
const showCoordinates = useTypedSelector(selectShowCoordinates);
|
|
34
41
|
const query = useTypedSelector(selectResultsQuery);
|
|
35
42
|
const { consonants, direction, separator, vowels } = LOCALE_FEATURES[locale];
|
|
36
43
|
const result = results[index];
|
|
37
44
|
const isMatching = useTypedSelector((state) => selectIsResultMatching(state, index));
|
|
38
45
|
const words = direction === 'rtl' ? [...result.words].reverse() : result.words;
|
|
39
46
|
const enabledColumns = Object.fromEntries(columns.map((column) => [column.id, true]));
|
|
47
|
+
const coordinates = useMemo(() => getCoordinates(result, showCoordinates), [result, showCoordinates]);
|
|
40
48
|
|
|
41
49
|
const handleClick: MouseEventHandler = (event) => onClick(result, event);
|
|
42
50
|
const handleMouseEnter: MouseEventHandler = (event) => onMouseEnter(result, event);
|
|
@@ -61,6 +69,10 @@ const Result = ({ data, index, style }: Props): ReactElement => {
|
|
|
61
69
|
onMouseLeave={handleMouseLeave}
|
|
62
70
|
>
|
|
63
71
|
<span className={styles.resultContent}>
|
|
72
|
+
{enabledColumns[ResultColumn.Coordinates] && (
|
|
73
|
+
<Cell className={styles.coordinates} translationKey="settings.showCoordinates" value={coordinates} />
|
|
74
|
+
)}
|
|
75
|
+
|
|
64
76
|
{enabledColumns[ResultColumn.Word] && (
|
|
65
77
|
<Cell className={styles.word} translationKey="common.word" value={result.word}>
|
|
66
78
|
<Highlighter highlightClassName={styles.highlight} searchWords={[query]} textToHighlight={result.word} />
|
|
@@ -24,10 +24,7 @@ $row-padding-horizontal: calc(var(--spacing--m) + var(--spacing--s));
|
|
|
24
24
|
|
|
25
25
|
.listContainer {
|
|
26
26
|
position: absolute;
|
|
27
|
-
|
|
28
|
-
left: 0;
|
|
29
|
-
right: 0;
|
|
30
|
-
bottom: 0;
|
|
27
|
+
inset: 0;
|
|
31
28
|
}
|
|
32
29
|
|
|
33
30
|
.list {
|
|
@@ -55,37 +52,29 @@ $row-padding-horizontal: calc(var(--spacing--m) + var(--spacing--s));
|
|
|
55
52
|
|
|
56
53
|
.headerButton {
|
|
57
54
|
@include button-reset;
|
|
58
|
-
@include focus-effect;
|
|
59
55
|
|
|
60
|
-
cursor: pointer;
|
|
61
56
|
text-transform: uppercase;
|
|
62
57
|
transition: var(--transition);
|
|
63
58
|
background-color: var(--color--background);
|
|
64
59
|
|
|
65
|
-
&:focus,
|
|
66
|
-
&:hover {
|
|
67
|
-
background-color: var(--color--primary);
|
|
68
|
-
color: var(--color--primary--opposite);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
60
|
&:first-child {
|
|
72
|
-
|
|
73
|
-
border-top-left-radius: inherit;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
[dir='rtl'] & {
|
|
77
|
-
border-top-right-radius: inherit;
|
|
78
|
-
}
|
|
61
|
+
border-start-start-radius: inherit;
|
|
79
62
|
}
|
|
80
63
|
|
|
81
64
|
&:last-child {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
65
|
+
border-start-end-radius: inherit;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
85
68
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
69
|
+
.sortable {
|
|
70
|
+
@include focus-effect;
|
|
71
|
+
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
|
|
74
|
+
&:focus,
|
|
75
|
+
&:hover {
|
|
76
|
+
background-color: var(--color--primary);
|
|
77
|
+
color: var(--color--primary--opposite);
|
|
89
78
|
}
|
|
90
79
|
}
|
|
91
80
|
|
|
@@ -93,11 +82,7 @@ $row-padding-horizontal: calc(var(--spacing--m) + var(--spacing--s));
|
|
|
93
82
|
@include ellipsis;
|
|
94
83
|
|
|
95
84
|
flex: 0 1 auto;
|
|
96
|
-
text-align:
|
|
97
|
-
|
|
98
|
-
[dir='rtl'] & {
|
|
99
|
-
text-align: right;
|
|
100
|
-
}
|
|
85
|
+
text-align: start;
|
|
101
86
|
}
|
|
102
87
|
|
|
103
88
|
.result {
|
|
@@ -139,6 +124,7 @@ $row-padding-horizontal: calc(var(--spacing--m) + var(--spacing--s));
|
|
|
139
124
|
|
|
140
125
|
.word {
|
|
141
126
|
@include ellipsis;
|
|
127
|
+
display: flex;
|
|
142
128
|
}
|
|
143
129
|
}
|
|
144
130
|
|
|
@@ -151,30 +137,20 @@ $row-padding-horizontal: calc(var(--spacing--m) + var(--spacing--s));
|
|
|
151
137
|
gap: var(--spacing--s);
|
|
152
138
|
line-height: var(--results--item--height);
|
|
153
139
|
|
|
154
|
-
|
|
155
|
-
.headerButton
|
|
140
|
+
&.word,
|
|
141
|
+
.headerButton.word & {
|
|
156
142
|
justify-content: flex-start;
|
|
143
|
+
}
|
|
157
144
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
[dir='rtl'] & {
|
|
164
|
-
padding-right: $row-padding-horizontal;
|
|
165
|
-
text-align: right;
|
|
166
|
-
}
|
|
145
|
+
.result &:first-child,
|
|
146
|
+
.headerButton:first-child & {
|
|
147
|
+
text-align: start;
|
|
148
|
+
padding-inline-start: $row-padding-horizontal;
|
|
167
149
|
}
|
|
168
150
|
|
|
169
151
|
.result &:last-child,
|
|
170
152
|
.headerButton:last-child & {
|
|
171
|
-
|
|
172
|
-
padding-right: $row-padding-horizontal;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
[dir='rtl'] & {
|
|
176
|
-
padding-left: $row-padding-horizontal;
|
|
177
|
-
}
|
|
153
|
+
padding-inline-end: $row-padding-horizontal;
|
|
178
154
|
}
|
|
179
155
|
|
|
180
156
|
&:last-child {
|
|
@@ -203,6 +179,13 @@ $row-padding-horizontal: calc(var(--spacing--m) + var(--spacing--s));
|
|
|
203
179
|
font-weight: bold;
|
|
204
180
|
}
|
|
205
181
|
|
|
182
|
+
.coordinates {
|
|
183
|
+
$width: 50px;
|
|
184
|
+
|
|
185
|
+
flex: 0 0 $width;
|
|
186
|
+
max-width: $width;
|
|
187
|
+
}
|
|
188
|
+
|
|
206
189
|
.solveButton {
|
|
207
190
|
display: block;
|
|
208
191
|
margin: var(--spacing--xl) auto 0;
|
|
@@ -69,7 +69,7 @@ const Results: FunctionComponent<Props> = ({ callbacks, className, highlightedIn
|
|
|
69
69
|
<div className={classNames(styles.results, className)}>
|
|
70
70
|
<div className={styles.header}>
|
|
71
71
|
{columns.map((column) => (
|
|
72
|
-
<HeaderButton column={column} key={column.id} />
|
|
72
|
+
<HeaderButton column={column} key={column.id} sortable={column.sortable} />
|
|
73
73
|
))}
|
|
74
74
|
</div>
|
|
75
75
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ResultColumn } from 'types';
|
|
2
|
+
|
|
3
|
+
import styles from './Results.module.scss';
|
|
4
|
+
import { Column } from './types';
|
|
5
|
+
|
|
6
|
+
const getCoordinatesColumn = (): Column => {
|
|
7
|
+
return {
|
|
8
|
+
className: styles.coordinates,
|
|
9
|
+
id: ResultColumn.Coordinates,
|
|
10
|
+
translationKey: 'settings.showCoordinates',
|
|
11
|
+
sortable: false,
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default getCoordinatesColumn;
|
|
@@ -10,11 +10,13 @@ const getLocaleColumns = (options: { consonants: boolean; vowels: boolean }): Co
|
|
|
10
10
|
className: styles.word,
|
|
11
11
|
id: ResultColumn.Word,
|
|
12
12
|
translationKey: 'common.word',
|
|
13
|
+
sortable: true,
|
|
13
14
|
},
|
|
14
15
|
{
|
|
15
16
|
className: styles.stat,
|
|
16
17
|
id: ResultColumn.TilesCount,
|
|
17
18
|
translationKey: 'common.tiles',
|
|
19
|
+
sortable: true,
|
|
18
20
|
},
|
|
19
21
|
];
|
|
20
22
|
|
|
@@ -23,6 +25,7 @@ const getLocaleColumns = (options: { consonants: boolean; vowels: boolean }): Co
|
|
|
23
25
|
className: styles.stat,
|
|
24
26
|
id: ResultColumn.ConsonantsCount,
|
|
25
27
|
translationKey: 'common.consonants',
|
|
28
|
+
sortable: true,
|
|
26
29
|
});
|
|
27
30
|
}
|
|
28
31
|
|
|
@@ -31,6 +34,7 @@ const getLocaleColumns = (options: { consonants: boolean; vowels: boolean }): Co
|
|
|
31
34
|
className: styles.stat,
|
|
32
35
|
id: ResultColumn.VowelsCount,
|
|
33
36
|
translationKey: 'common.vowels',
|
|
37
|
+
sortable: true,
|
|
34
38
|
});
|
|
35
39
|
}
|
|
36
40
|
|
|
@@ -39,16 +43,19 @@ const getLocaleColumns = (options: { consonants: boolean; vowels: boolean }): Co
|
|
|
39
43
|
className: styles.stat,
|
|
40
44
|
id: ResultColumn.BlanksCount,
|
|
41
45
|
translationKey: 'common.blanks',
|
|
46
|
+
sortable: true,
|
|
42
47
|
},
|
|
43
48
|
{
|
|
44
49
|
className: styles.stat,
|
|
45
50
|
id: ResultColumn.WordsCount,
|
|
46
51
|
translationKey: 'common.words',
|
|
52
|
+
sortable: true,
|
|
47
53
|
},
|
|
48
54
|
{
|
|
49
55
|
className: styles.points,
|
|
50
56
|
id: ResultColumn.Points,
|
|
51
57
|
translationKey: 'common.points',
|
|
58
|
+
sortable: true,
|
|
52
59
|
},
|
|
53
60
|
);
|
|
54
61
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { useMediaQueries } from 'hooks';
|
|
2
2
|
import { LOCALE_FEATURES } from 'i18n';
|
|
3
|
-
import { selectLocale, useTypedSelector } from 'state';
|
|
3
|
+
import { selectLocale, selectShowCoordinates, useTypedSelector } from 'state';
|
|
4
4
|
import { ResultColumn } from 'types';
|
|
5
5
|
|
|
6
|
+
import getCoordinatesColumn from './getCoordinatesColumn';
|
|
6
7
|
import getLocaleColumns from './getLocaleColumns';
|
|
7
8
|
import { Column } from './types';
|
|
8
9
|
|
|
9
|
-
const COLUMNS_XS = [ResultColumn.Word, ResultColumn.Points];
|
|
10
|
+
const COLUMNS_XS = [ResultColumn.Coordinates, ResultColumn.Word, ResultColumn.Points];
|
|
10
11
|
|
|
11
12
|
const COLUMNS_S = [...COLUMNS_XS, ResultColumn.BlanksCount, ResultColumn.WordsCount];
|
|
12
13
|
|
|
@@ -17,25 +18,27 @@ const COLUMNS_L = [...COLUMNS_XS];
|
|
|
17
18
|
const useColumns = (): Column[] => {
|
|
18
19
|
const locale = useTypedSelector(selectLocale);
|
|
19
20
|
const localeColumns = getLocaleColumns(LOCALE_FEATURES[locale]);
|
|
21
|
+
const showCoordinates = useTypedSelector(selectShowCoordinates);
|
|
22
|
+
const columns = showCoordinates === 'hidden' ? localeColumns : [getCoordinatesColumn(), ...localeColumns];
|
|
20
23
|
const { isLessThanXs, isLessThanS, isLessThanM, isLessThanL } = useMediaQueries();
|
|
21
24
|
|
|
22
25
|
if (isLessThanXs) {
|
|
23
|
-
return
|
|
26
|
+
return columns.filter((column) => COLUMNS_XS.includes(column.id));
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
if (isLessThanS) {
|
|
27
|
-
return
|
|
30
|
+
return columns.filter((column) => COLUMNS_S.includes(column.id));
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
if (isLessThanM) {
|
|
31
|
-
return
|
|
34
|
+
return columns.filter((column) => COLUMNS_M.includes(column.id));
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
if (isLessThanL) {
|
|
35
|
-
return
|
|
38
|
+
return columns.filter((column) => COLUMNS_L.includes(column.id));
|
|
36
39
|
}
|
|
37
40
|
|
|
38
|
-
return
|
|
41
|
+
return columns;
|
|
39
42
|
};
|
|
40
43
|
|
|
41
44
|
export default useColumns;
|
package/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.module.scss
CHANGED
|
@@ -82,23 +82,11 @@
|
|
|
82
82
|
.points {
|
|
83
83
|
flex: 0 0 auto;
|
|
84
84
|
font-weight: bold;
|
|
85
|
+
border-inline-end: var(--border);
|
|
85
86
|
|
|
86
|
-
|
|
87
|
-
border-
|
|
88
|
-
|
|
89
|
-
@include media('<xs') {
|
|
90
|
-
border-right: none;
|
|
91
|
-
padding-right: var(--spacing--xs);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
[dir='rtl'] & {
|
|
96
|
-
border-left: var(--border);
|
|
97
|
-
|
|
98
|
-
@include media('<xs') {
|
|
99
|
-
border-left: none;
|
|
100
|
-
padding-left: var(--spacing--xs);
|
|
101
|
-
}
|
|
87
|
+
@include media('<xs') {
|
|
88
|
+
border-inline-end: none;
|
|
89
|
+
padding-inline-end: var(--spacing--xs);
|
|
102
90
|
}
|
|
103
91
|
}
|
|
104
92
|
|
|
@@ -110,40 +98,21 @@
|
|
|
110
98
|
text-align: center;
|
|
111
99
|
white-space: pre-wrap;
|
|
112
100
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
text-align: left;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
[dir='rtl'] & {
|
|
121
|
-
@include media('<xs') {
|
|
122
|
-
padding: var(--spacing--m);
|
|
123
|
-
text-align: right;
|
|
124
|
-
}
|
|
101
|
+
@include media('<xs') {
|
|
102
|
+
padding: var(--spacing--m);
|
|
103
|
+
text-align: start;
|
|
125
104
|
}
|
|
126
105
|
}
|
|
127
106
|
|
|
128
107
|
.iconContainer {
|
|
129
108
|
flex: 0 0 auto;
|
|
130
109
|
display: flex;
|
|
131
|
-
|
|
132
|
-
[dir='ltr'] & {
|
|
133
|
-
padding-right: var(--spacing--l);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
[dir='rtl'] & {
|
|
137
|
-
padding-left: var(--spacing--l);
|
|
138
|
-
}
|
|
110
|
+
padding-inline-end: var(--spacing--l);
|
|
139
111
|
}
|
|
140
112
|
|
|
141
113
|
.spinnerContainer {
|
|
142
114
|
position: absolute;
|
|
143
|
-
|
|
144
|
-
right: 0;
|
|
145
|
-
bottom: 0;
|
|
146
|
-
left: 0;
|
|
115
|
+
inset: 0;
|
|
147
116
|
display: flex;
|
|
148
117
|
align-items: center;
|
|
149
118
|
justify-content: center;
|
|
@@ -76,10 +76,7 @@
|
|
|
76
76
|
|
|
77
77
|
.input {
|
|
78
78
|
position: absolute;
|
|
79
|
-
|
|
80
|
-
right: 0;
|
|
81
|
-
bottom: 0;
|
|
82
|
-
left: 0;
|
|
79
|
+
inset: 0;
|
|
83
80
|
width: 100%;
|
|
84
81
|
height: 100%;
|
|
85
82
|
border: none;
|
|
@@ -98,6 +95,8 @@
|
|
|
98
95
|
@include text-stroke(var(--background-color), 1px);
|
|
99
96
|
|
|
100
97
|
position: absolute;
|
|
98
|
+
inset-block-end: 1%;
|
|
99
|
+
inset-inline-end: 9%;
|
|
101
100
|
font-weight: bold;
|
|
102
101
|
user-select: none;
|
|
103
102
|
pointer-events: none;
|
|
@@ -106,16 +105,6 @@
|
|
|
106
105
|
@include media('<xs') {
|
|
107
106
|
display: none;
|
|
108
107
|
}
|
|
109
|
-
|
|
110
|
-
[dir='ltr'] & {
|
|
111
|
-
bottom: 1%;
|
|
112
|
-
right: 9%;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
[dir='rtl'] & {
|
|
116
|
-
top: 1%;
|
|
117
|
-
left: 9%;
|
|
118
|
-
}
|
|
119
108
|
}
|
|
120
109
|
|
|
121
110
|
.alert {
|
|
@@ -124,6 +113,9 @@
|
|
|
124
113
|
position: absolute;
|
|
125
114
|
width: var(--size);
|
|
126
115
|
height: var(--size);
|
|
116
|
+
inset-block-start: 0;
|
|
117
|
+
inset-inline-end: 0;
|
|
118
|
+
border-start-end-radius: inherit;
|
|
127
119
|
background: radial-gradient(
|
|
128
120
|
var(--color--error--opposite),
|
|
129
121
|
var(--color--error--opposite) 85%,
|
|
@@ -132,16 +124,4 @@
|
|
|
132
124
|
);
|
|
133
125
|
color: var(--color--error);
|
|
134
126
|
pointer-events: none;
|
|
135
|
-
|
|
136
|
-
[dir='ltr'] & {
|
|
137
|
-
top: 0;
|
|
138
|
-
right: 0;
|
|
139
|
-
border-top-right-radius: inherit;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
[dir='rtl'] & {
|
|
143
|
-
top: 0;
|
|
144
|
-
left: 0;
|
|
145
|
-
border-top-left-radius: inherit;
|
|
146
|
-
}
|
|
147
127
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Placement } from '@floating-ui/react';
|
|
2
|
+
import { FunctionComponent, ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
import { TooltipContext } from './context';
|
|
5
|
+
import { TooltipContent } from './TooltipContent';
|
|
6
|
+
import { TooltipTrigger } from './TooltipTrigger';
|
|
7
|
+
import { useTooltip } from './useTooltip';
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
placement?: Placement;
|
|
12
|
+
tooltip?: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const Tooltip: FunctionComponent<Props> = ({ children, placement, tooltip }) => {
|
|
16
|
+
const state = useTooltip({ placement });
|
|
17
|
+
|
|
18
|
+
if (!tooltip) {
|
|
19
|
+
return children;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<TooltipContext.Provider value={state}>
|
|
24
|
+
<TooltipTrigger>{children}</TooltipTrigger>
|
|
25
|
+
<TooltipContent>{tooltip}</TooltipContent>
|
|
26
|
+
</TooltipContext.Provider>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { FloatingArrow, FloatingPortal, useDelayGroup, useMergeRefs, useTransitionStyles } from '@floating-ui/react';
|
|
2
|
+
import { forwardRef, HTMLProps } from 'react';
|
|
3
|
+
|
|
4
|
+
import { TOOLTIP_DURATION } from 'parameters';
|
|
5
|
+
|
|
6
|
+
import { useTooltipContext } from './context';
|
|
7
|
+
import styles from './Tooltip.module.scss';
|
|
8
|
+
|
|
9
|
+
type Props = HTMLProps<HTMLDivElement>;
|
|
10
|
+
|
|
11
|
+
const INSTANT_DURATION = 0;
|
|
12
|
+
|
|
13
|
+
export const TooltipContent = forwardRef<HTMLDivElement, Props>((props, ref) => {
|
|
14
|
+
const state = useTooltipContext();
|
|
15
|
+
const { context } = state;
|
|
16
|
+
const { isInstantPhase, currentId } = useDelayGroup(context, { id: context.floatingId });
|
|
17
|
+
const finalRef = useMergeRefs([state.refs.setFloating, ref]);
|
|
18
|
+
|
|
19
|
+
const instantPhaseDuration = {
|
|
20
|
+
open: INSTANT_DURATION,
|
|
21
|
+
close: currentId === context.floatingId ? TOOLTIP_DURATION : INSTANT_DURATION,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const { isMounted, styles: transitionStyles } = useTransitionStyles(context, {
|
|
25
|
+
duration: isInstantPhase ? instantPhaseDuration : TOOLTIP_DURATION,
|
|
26
|
+
initial: {
|
|
27
|
+
opacity: 0,
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (!isMounted) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<FloatingPortal>
|
|
37
|
+
<div
|
|
38
|
+
className={styles.tooltip}
|
|
39
|
+
ref={finalRef}
|
|
40
|
+
style={{
|
|
41
|
+
...state.floatingStyles,
|
|
42
|
+
...props.style,
|
|
43
|
+
...transitionStyles,
|
|
44
|
+
}}
|
|
45
|
+
{...state.getFloatingProps(props)}
|
|
46
|
+
>
|
|
47
|
+
<div>{props.children}</div>
|
|
48
|
+
|
|
49
|
+
<FloatingArrow className={styles.arrow} context={context} ref={state.arrowRef} />
|
|
50
|
+
</div>
|
|
51
|
+
</FloatingPortal>
|
|
52
|
+
);
|
|
53
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useMergeRefs } from '@floating-ui/react';
|
|
2
|
+
import { HTMLProps, cloneElement, forwardRef, isValidElement } from 'react';
|
|
3
|
+
|
|
4
|
+
import { useTooltipContext } from './context';
|
|
5
|
+
|
|
6
|
+
type Props = HTMLProps<HTMLElement>;
|
|
7
|
+
|
|
8
|
+
export const TooltipTrigger = forwardRef<HTMLElement, Props>(({ children, ...props }, ref) => {
|
|
9
|
+
const state = useTooltipContext();
|
|
10
|
+
const childrenElement = children as any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
11
|
+
const finalRef = useMergeRefs([state.refs.setReference, ref, childrenElement.ref]);
|
|
12
|
+
|
|
13
|
+
if (!isValidElement(children)) {
|
|
14
|
+
throw new Error("TooltipTrigger's children are not a valid element");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return cloneElement(
|
|
18
|
+
children,
|
|
19
|
+
state.getReferenceProps({
|
|
20
|
+
ref: finalRef,
|
|
21
|
+
...props,
|
|
22
|
+
...children.props,
|
|
23
|
+
'data-state': state.open ? 'open' : 'closed',
|
|
24
|
+
}),
|
|
25
|
+
);
|
|
26
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
import { useTooltip } from './useTooltip';
|
|
4
|
+
|
|
5
|
+
type TooltipContextType = ReturnType<typeof useTooltip> | null;
|
|
6
|
+
|
|
7
|
+
export const TooltipContext = createContext<TooltipContextType>(null);
|
|
8
|
+
|
|
9
|
+
export const useTooltipContext = () => {
|
|
10
|
+
const context = useContext(TooltipContext);
|
|
11
|
+
|
|
12
|
+
if (context === null) {
|
|
13
|
+
throw new Error('Tooltip components must be wrapped in <Tooltip />');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return context;
|
|
17
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { Tooltip } from './Tooltip';
|