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/.nx/cache/d/server-process.json +1 -0
- package/.nx/cache/file-map.json +1293 -1298
- package/.nx/cache/lockfile.hash +1 -1
- package/.nx/cache/nx_files.nxt +0 -0
- package/.nx/cache/parsed-lock-file.json +306 -361
- package/.nx/cache/project-graph.json +316 -382
- package/.nx/workspace-data/file-map.json +2594 -0
- package/.nx/workspace-data/lockfile.hash +1 -0
- package/.nx/workspace-data/parsed-lock-file.json +31666 -0
- package/.nx/workspace-data/project-graph.json +31937 -0
- package/README.md +10 -19
- package/bump-version.js +15 -9
- package/lerna.json +1 -1
- package/package.json +9 -9
- package/packages/configs/package.json +3 -3
- package/packages/constants/package.json +1 -1
- package/packages/dictionaries/package-lock.json +2 -2
- package/packages/dictionaries/package.json +4 -4
- package/packages/logger/package-lock.json +2 -2
- package/packages/logger/package.json +1 -1
- package/packages/scrabble-solver/.next/BUILD_ID +1 -1
- package/packages/scrabble-solver/.next/build-manifest.json +11 -11
- package/packages/scrabble-solver/.next/cache/.tsbuildinfo +1 -1
- package/packages/scrabble-solver/.next/cache/eslint/.cache_8dgz12 +1 -1
- package/packages/scrabble-solver/.next/cache/webpack/client-production/0.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/client-production/index.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/0.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/server-production/0.pack +0 -0
- package/packages/scrabble-solver/.next/cache/webpack/server-production/index.pack +0 -0
- package/packages/scrabble-solver/.next/prerender-manifest.js +1 -1
- package/packages/scrabble-solver/.next/prerender-manifest.json +1 -1
- package/packages/scrabble-solver/.next/routes-manifest.json +1 -1
- package/packages/scrabble-solver/.next/server/chunks/577.js +1 -1
- package/packages/scrabble-solver/.next/server/chunks/807.js +1 -1
- package/packages/scrabble-solver/.next/server/chunks/977.js +1 -1
- package/packages/scrabble-solver/.next/server/middleware-build-manifest.js +1 -1
- package/packages/scrabble-solver/.next/server/pages/404.html +1 -1
- package/packages/scrabble-solver/.next/server/pages/500.html +1 -1
- package/packages/scrabble-solver/.next/server/pages/_app.js +1 -1
- package/packages/scrabble-solver/.next/server/pages/_error.js +1 -1
- package/packages/scrabble-solver/.next/server/pages/api/solve.js +1 -1
- package/packages/scrabble-solver/.next/server/pages/index.html +1 -1
- package/packages/scrabble-solver/.next/server/pages/index.js +1 -1
- package/packages/scrabble-solver/.next/server/pages/index.json +1 -1
- package/packages/scrabble-solver/.next/server/pages-manifest.json +1 -1
- package/packages/scrabble-solver/.next/static/7zESQYo9UAqNh9LV0b7Sd/_buildManifest.js +1 -0
- package/packages/scrabble-solver/.next/static/chunks/{main-6e708370ad13b1f9.js → main-b5b360c6afb66b05.js} +1 -1
- package/packages/scrabble-solver/.next/static/chunks/pages/{404-129e0943628b6fab.js → 404-63b972b24be99c62.js} +1 -1
- package/packages/scrabble-solver/.next/static/chunks/pages/_app-a2848b7efa6bb6b0.js +17 -0
- package/packages/scrabble-solver/.next/static/chunks/pages/index-7b73be2915cc7099.js +1 -0
- package/packages/scrabble-solver/.next/static/css/6682db14f926d4c7.css +1 -0
- package/packages/scrabble-solver/.next/static/css/b37850c8d5270d91.css +2 -0
- package/packages/scrabble-solver/.next/trace +44 -44
- package/packages/scrabble-solver/package-lock.json +5 -6
- package/packages/scrabble-solver/package.json +11 -12
- package/packages/scrabble-solver/public/service-worker.js +1 -1
- package/packages/scrabble-solver/src/components/Alert/Alert.module.scss +3 -12
- package/packages/scrabble-solver/src/components/Board/Board.module.scss +1 -4
- package/packages/scrabble-solver/src/components/Board/BoardPure.tsx +1 -1
- package/packages/scrabble-solver/src/components/Board/components/Actions/Actions.module.scss +7 -27
- package/packages/scrabble-solver/src/components/Board/components/Cell/Cell.module.scss +5 -32
- package/packages/scrabble-solver/src/components/Board/components/InputPrompt/InputPrompt.module.scss +4 -18
- package/packages/scrabble-solver/src/components/Board/hooks/useBackgroundImage.tsx +15 -4
- package/packages/scrabble-solver/src/components/Board/hooks/useGrid.ts +13 -5
- package/packages/scrabble-solver/src/components/Board/lib/index.ts +0 -1
- package/packages/scrabble-solver/src/components/Button/Button.module.scss +1 -8
- package/packages/scrabble-solver/src/components/Button/Button.tsx +16 -17
- package/packages/scrabble-solver/src/components/Button/Link.tsx +15 -16
- package/packages/scrabble-solver/src/components/Dictionary/Dictionary.module.scss +1 -8
- package/packages/scrabble-solver/src/components/IconButton/IconButton.tsx +8 -8
- package/packages/scrabble-solver/src/components/IconButton/Link.tsx +8 -8
- package/packages/scrabble-solver/src/components/Loading/Loading.module.scss +1 -4
- package/packages/scrabble-solver/src/components/Modal/Modal.module.scss +2 -16
- package/packages/scrabble-solver/src/components/Rack/Rack.module.scss +4 -18
- package/packages/scrabble-solver/src/components/Rack/components/InputPrompt/InputPrompt.module.scss +1 -4
- package/packages/scrabble-solver/src/components/Results/Cell.tsx +4 -5
- package/packages/scrabble-solver/src/components/Results/HeaderButton.tsx +25 -22
- package/packages/scrabble-solver/src/components/Results/Result.tsx +15 -3
- package/packages/scrabble-solver/src/components/Results/Results.module.scss +31 -48
- package/packages/scrabble-solver/src/components/Results/Results.tsx +1 -1
- package/packages/scrabble-solver/src/components/Results/getCoordinatesColumn.ts +15 -0
- package/packages/scrabble-solver/src/components/Results/getLocaleColumns.ts +7 -0
- package/packages/scrabble-solver/src/components/Results/types.ts +1 -0
- package/packages/scrabble-solver/src/components/Results/useColumns.ts +10 -7
- package/packages/scrabble-solver/src/components/Solver/components/ResultCandidatePicker/ResultCandidatePicker.module.scss +9 -40
- package/packages/scrabble-solver/src/components/Tile/Tile.module.scss +6 -26
- package/packages/scrabble-solver/src/components/Tooltip/Tooltip.tsx +28 -0
- package/packages/scrabble-solver/src/components/Tooltip/TooltipContent.tsx +53 -0
- package/packages/scrabble-solver/src/components/Tooltip/TooltipTrigger.tsx +26 -0
- package/packages/scrabble-solver/src/components/Tooltip/context.ts +17 -0
- package/packages/scrabble-solver/src/components/Tooltip/index.ts +1 -1
- package/packages/scrabble-solver/src/components/Tooltip/useTooltip.ts +54 -0
- package/packages/scrabble-solver/src/components/index.ts +1 -2
- package/packages/scrabble-solver/src/hooks/index.ts +0 -1
- package/packages/scrabble-solver/src/i18n/languages/german.json +1 -1
- package/packages/scrabble-solver/src/icons/index.ts +0 -2
- package/packages/scrabble-solver/src/lib/getCoordinates.ts +18 -0
- package/packages/scrabble-solver/src/lib/groupResults.ts +16 -11
- package/packages/scrabble-solver/src/lib/index.ts +2 -1
- package/packages/scrabble-solver/src/lib/sortResults.ts +1 -0
- package/packages/scrabble-solver/src/modals/KeyMapModal/components/Mapping/Mapping.module.scss +2 -2
- package/packages/scrabble-solver/src/modals/MenuModal/MenuModal.module.scss +2 -15
- package/packages/scrabble-solver/src/modals/RemainingTilesModal/RemainingTilesModal.module.scss +1 -7
- package/packages/scrabble-solver/src/modals/WordsModal/WordsModal.module.scss +2 -15
- package/packages/scrabble-solver/src/pages/_app.tsx +5 -1
- package/packages/scrabble-solver/src/parameters/index.ts +1 -0
- package/packages/scrabble-solver/src/styles/mixins.scss +2 -5
- package/packages/scrabble-solver/src/types/index.ts +1 -0
- package/packages/solver/package-lock.json +2 -2
- package/packages/solver/package.json +5 -5
- package/packages/types/package.json +2 -2
- package/packages/word-definitions/package-lock.json +2 -2
- package/packages/word-definitions/package.json +2 -2
- package/packages/word-lists/package-lock.json +3 -3
- package/packages/word-lists/package.json +3 -3
- package/packages/scrabble-solver/.next/static/4GWIKe7khKxREyq3ZamDK/_buildManifest.js +0 -1
- package/packages/scrabble-solver/.next/static/chunks/pages/_app-cccda36d00fa2328.js +0 -17
- package/packages/scrabble-solver/.next/static/chunks/pages/index-caaf20b2488cb10e.js +0 -1
- package/packages/scrabble-solver/.next/static/css/11366b7489cf90ac.css +0 -1
- package/packages/scrabble-solver/.next/static/css/f549d7823f599b8d.css +0 -2
- package/packages/scrabble-solver/src/components/Checkbox/Checkbox.module.scss +0 -45
- package/packages/scrabble-solver/src/components/Checkbox/Checkbox.tsx +0 -38
- package/packages/scrabble-solver/src/components/Checkbox/index.ts +0 -1
- package/packages/scrabble-solver/src/components/Tooltip/useTooltip.tsx +0 -134
- package/packages/scrabble-solver/src/hooks/usePortal.tsx +0 -47
- package/packages/scrabble-solver/src/icons/CheckboxChecked.svg +0 -4
- package/packages/scrabble-solver/src/icons/CheckboxEmpty.svg +0 -4
- package/packages/scrabble-solver/src/lib/canUseDom.ts +0 -3
- /package/packages/scrabble-solver/.next/static/{4GWIKe7khKxREyq3ZamDK → 7zESQYo9UAqNh9LV0b7Sd}/_ssgManifest.js +0 -0
- /package/packages/scrabble-solver/src/{components/Board/lib → lib}/getCoordinate.ts +0 -0
|
@@ -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;
|
|
@@ -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';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Placement,
|
|
3
|
+
arrow,
|
|
4
|
+
autoUpdate,
|
|
5
|
+
flip,
|
|
6
|
+
offset,
|
|
7
|
+
shift,
|
|
8
|
+
useDelayGroup,
|
|
9
|
+
useDismiss,
|
|
10
|
+
useFloating,
|
|
11
|
+
useFocus,
|
|
12
|
+
useHover,
|
|
13
|
+
useInteractions,
|
|
14
|
+
useRole,
|
|
15
|
+
} from '@floating-ui/react';
|
|
16
|
+
import { useMemo, useRef, useState } from 'react';
|
|
17
|
+
|
|
18
|
+
const ARROW_SIZE = 7;
|
|
19
|
+
const ARROW_GAP = 3;
|
|
20
|
+
const PADDING = 10;
|
|
21
|
+
|
|
22
|
+
interface TooltipOptions {
|
|
23
|
+
placement?: Placement;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const useTooltip = ({ placement = 'top' }: TooltipOptions = {}) => {
|
|
27
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
28
|
+
const arrowRef = useRef(null);
|
|
29
|
+
const data = useFloating({
|
|
30
|
+
placement,
|
|
31
|
+
open: isOpen,
|
|
32
|
+
onOpenChange: setIsOpen,
|
|
33
|
+
whileElementsMounted: autoUpdate,
|
|
34
|
+
middleware: [flip(), shift({ padding: PADDING }), offset(ARROW_SIZE + ARROW_GAP), arrow({ element: arrowRef })],
|
|
35
|
+
});
|
|
36
|
+
const { context } = data;
|
|
37
|
+
const { delay } = useDelayGroup(context);
|
|
38
|
+
const hover = useHover(context, { move: false, delay });
|
|
39
|
+
const focus = useFocus(context);
|
|
40
|
+
const dismiss = useDismiss(context);
|
|
41
|
+
const role = useRole(context, { role: 'tooltip' });
|
|
42
|
+
const interactions = useInteractions([hover, focus, dismiss, role]);
|
|
43
|
+
|
|
44
|
+
return useMemo(
|
|
45
|
+
() => ({
|
|
46
|
+
arrowRef,
|
|
47
|
+
open: isOpen,
|
|
48
|
+
setOpen: setIsOpen,
|
|
49
|
+
...interactions,
|
|
50
|
+
...data,
|
|
51
|
+
}),
|
|
52
|
+
[arrowRef, isOpen, setIsOpen, interactions, data],
|
|
53
|
+
);
|
|
54
|
+
};
|
|
@@ -2,7 +2,6 @@ export { default as Alert } from './Alert';
|
|
|
2
2
|
export { default as Badge } from './Badge';
|
|
3
3
|
export { default as Board } from './Board';
|
|
4
4
|
export { default as Button } from './Button';
|
|
5
|
-
export { default as Checkbox } from './Checkbox';
|
|
6
5
|
export { default as Dictionary } from './Dictionary';
|
|
7
6
|
export { default as DictionaryInput } from './DictionaryInput';
|
|
8
7
|
export { default as EmptyState } from './EmptyState';
|
|
@@ -23,4 +22,4 @@ export { default as SeoMessage } from './SeoMessage';
|
|
|
23
22
|
export { default as Solver } from './Solver';
|
|
24
23
|
export { default as Spinner } from './Spinner';
|
|
25
24
|
export { default as Tile } from './Tile';
|
|
26
|
-
export
|
|
25
|
+
export * from './Tooltip';
|
|
@@ -9,5 +9,4 @@ export { default as useMedia } from './useMedia';
|
|
|
9
9
|
export { default as useMediaQueries } from './useMediaQueries';
|
|
10
10
|
export { default as useMediaQuery } from './useMediaQuery';
|
|
11
11
|
export { default as useOnWindowResize } from './useOnWindowResize';
|
|
12
|
-
export { default as usePortal } from './usePortal';
|
|
13
12
|
export { default as useViewportSize } from './useViewportSize';
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"dictionary.empty-state.no-definitions": "Wort existiert im Wörterbuch aber hat keine Definition.",
|
|
23
23
|
"dictionary.empty-state.no-results": "Wort kann nicht im Wörterbuch gefunden werden.",
|
|
24
24
|
"dictionary.empty-state.not-allowed": "Dieses Wort ist nicht erlaubt.",
|
|
25
|
-
"dictionary.empty-state.uninitialized": "Die
|
|
25
|
+
"dictionary.empty-state.uninitialized": "Die Wörterbuchdefinition wird hier angezeigt.",
|
|
26
26
|
"dictionary.input.placeholder": "Durchsuche Wörterbuch…",
|
|
27
27
|
"dictionary.input.title": "Durch Kommas getrennte Wörter",
|
|
28
28
|
"empty-state.error": "Fehler",
|
|
@@ -5,8 +5,6 @@ export { default as ArrowUp } from './ArrowUp.svg';
|
|
|
5
5
|
export { default as BookHalf } from './BookHalf.svg';
|
|
6
6
|
export { default as CardChecklist } from './CardChecklist.svg';
|
|
7
7
|
export { default as Check } from './Check.svg';
|
|
8
|
-
export { default as CheckboxChecked } from './CheckboxChecked.svg';
|
|
9
|
-
export { default as CheckboxEmpty } from './CheckboxEmpty.svg';
|
|
10
8
|
export { default as ChevronDown } from './ChevronDown.svg';
|
|
11
9
|
export { default as ChevronLeft } from './ChevronLeft.svg';
|
|
12
10
|
export { default as ChevronRight } from './ChevronRight.svg';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Result, ShowCoordinates } from '@scrabble-solver/types';
|
|
2
|
+
|
|
3
|
+
import getCoordinate from './getCoordinate';
|
|
4
|
+
|
|
5
|
+
const getCoordinates = (result: Result, showCoordinates: ShowCoordinates): string => {
|
|
6
|
+
if (showCoordinates === 'hidden') {
|
|
7
|
+
return '';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const firstCell = result.cells[0];
|
|
11
|
+
const isHorizontal = firstCell.x !== result.cells[1].x;
|
|
12
|
+
const x = getCoordinate(firstCell.x, showCoordinates === 'original' ? 'letter' : 'number');
|
|
13
|
+
const y = getCoordinate(firstCell.y, showCoordinates === 'original' ? 'number' : 'letter');
|
|
14
|
+
|
|
15
|
+
return isHorizontal ? `${y}${x}` : `${x}${y}`;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default getCoordinates;
|
|
@@ -18,18 +18,23 @@ const groupResults = (
|
|
|
18
18
|
return results;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
const regExp = createRegExp(query);
|
|
22
|
+
|
|
21
23
|
return results.reduce<GroupedResults>(
|
|
22
|
-
(
|
|
23
|
-
const matchesQuery =
|
|
24
|
-
const matchesCellFilter =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
matching
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
(groupedResults, result) => {
|
|
25
|
+
const matchesQuery = () => regExp.test(result.word);
|
|
26
|
+
const matchesCellFilter = () =>
|
|
27
|
+
cellFilter.every(({ x, y }) => {
|
|
28
|
+
return result.cells.some((cell) => cell.x === x && cell.y === y);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (matchesCellFilter() && matchesQuery()) {
|
|
32
|
+
groupedResults.matching.push(result);
|
|
33
|
+
} else {
|
|
34
|
+
groupedResults.other.push(result);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return groupedResults;
|
|
33
38
|
},
|
|
34
39
|
{ matching: [], other: [] },
|
|
35
40
|
);
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { default as arrayEquals } from './arrayEquals';
|
|
2
|
-
export { default as canUseDom } from './canUseDom';
|
|
3
2
|
export { default as createArray } from './createArray';
|
|
4
3
|
export { default as createComparator } from './createComparator';
|
|
5
4
|
export { default as createGridOf } from './createGridOf';
|
|
@@ -15,6 +14,8 @@ export { default as extractCharactersByCase } from './extractCharactersByCase';
|
|
|
15
14
|
export { default as extractInputValue } from './extractInputValue';
|
|
16
15
|
export { default as findCell } from './findCell';
|
|
17
16
|
export { default as getCellSize } from './getCellSize';
|
|
17
|
+
export { default as getCoordinate } from './getCoordinate';
|
|
18
|
+
export { default as getCoordinates } from './getCoordinates';
|
|
18
19
|
export { default as getRemainingTiles } from './getRemainingTiles';
|
|
19
20
|
export { default as getRemainingTilesCount } from './getRemainingTilesCount';
|
|
20
21
|
export { default as getRemainingTilesGroups } from './getRemainingTilesGroups';
|
|
@@ -8,6 +8,7 @@ import reverseComparator from './reverseComparator';
|
|
|
8
8
|
const comparators: Record<ResultColumn, (locale: string) => Comparator<Result>> = {
|
|
9
9
|
[ResultColumn.BlanksCount]: (locale: string) => createKeyComparator('blanksCount', locale),
|
|
10
10
|
[ResultColumn.ConsonantsCount]: (locale: string) => createKeyComparator('consonantsCount', locale),
|
|
11
|
+
[ResultColumn.Coordinates]: () => () => 0,
|
|
11
12
|
[ResultColumn.Points]: (locale: string) => createKeyComparator('points', locale),
|
|
12
13
|
[ResultColumn.TilesCount]: (locale: string) => createKeyComparator('tilesCount', locale),
|
|
13
14
|
[ResultColumn.VowelsCount]: (locale: string) => createKeyComparator('vowelsCount', locale),
|
|
@@ -31,13 +31,7 @@
|
|
|
31
31
|
--aspect-ratio: var(--highest-flag-aspect-ratio);
|
|
32
32
|
--padding: calc(var(--spacing--l) + var(--button--icon--size) * var(--aspect-ratio));
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
padding-right: var(--padding);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
[dir='rtl'] & {
|
|
39
|
-
padding-left: var(--padding);
|
|
40
|
-
}
|
|
34
|
+
padding-inline-end: var(--padding);
|
|
41
35
|
}
|
|
42
36
|
|
|
43
37
|
.flag {
|
|
@@ -45,12 +39,5 @@
|
|
|
45
39
|
height: var(--button--icon--size);
|
|
46
40
|
border-radius: var(--border--radius);
|
|
47
41
|
box-shadow: 0 0 0 1px var(--box-shadow--color);
|
|
48
|
-
|
|
49
|
-
[dir='ltr'] & {
|
|
50
|
-
right: calc(2 * var(--spacing--l));
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
[dir='rtl'] & {
|
|
54
|
-
left: calc(2 * var(--spacing--l));
|
|
55
|
-
}
|
|
42
|
+
inset-inline-end: calc(2 * var(--spacing--l));
|
|
56
43
|
}
|
|
@@ -6,13 +6,7 @@
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
.badge {
|
|
9
|
-
|
|
10
|
-
margin-left: var(--spacing--m);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
[dir='rtl'] & {
|
|
14
|
-
margin-right: var(--spacing--m);
|
|
15
|
-
}
|
|
9
|
+
margin-inline-start: var(--spacing--m);
|
|
16
10
|
}
|
|
17
11
|
|
|
18
12
|
.word {
|
|
@@ -37,12 +31,5 @@
|
|
|
37
31
|
|
|
38
32
|
width: $size;
|
|
39
33
|
height: $size;
|
|
40
|
-
|
|
41
|
-
[dir='ltr'] & {
|
|
42
|
-
margin-right: var(--spacing--s);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
[dir='rtl'] & {
|
|
46
|
-
margin-left: var(--spacing--s);
|
|
47
|
-
}
|
|
34
|
+
margin-inline-end: var(--spacing--s);
|
|
48
35
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { FloatingDelayGroup } from '@floating-ui/react';
|
|
1
2
|
import { AppProps } from 'next/app';
|
|
2
3
|
import Head from 'next/head';
|
|
3
4
|
import { FunctionComponent } from 'react';
|
|
@@ -64,7 +65,10 @@ const App: FunctionComponent<AppProps> = ({ Component, pageProps }) => (
|
|
|
64
65
|
|
|
65
66
|
<Provider store={store}>
|
|
66
67
|
<SeoMessage />
|
|
67
|
-
|
|
68
|
+
|
|
69
|
+
<FloatingDelayGroup delay={0}>
|
|
70
|
+
<Component {...pageProps} />
|
|
71
|
+
</FloatingDelayGroup>
|
|
68
72
|
</Provider>
|
|
69
73
|
</>
|
|
70
74
|
);
|
|
@@ -90,6 +90,7 @@ export const MODAL_HEADER_HEIGHT = 45;
|
|
|
90
90
|
export const NAV_PADDING = SPACING_L;
|
|
91
91
|
|
|
92
92
|
export const TILE_SIZE = 80;
|
|
93
|
+
export const TOOLTIP_DURATION = TRANSITION_DURATION;
|
|
93
94
|
|
|
94
95
|
export const PLAIN_TILES_COLOR_DEFAULT = COLOR_GREEN;
|
|
95
96
|
export const PLAIN_TILES_PADDING_HORIZONTAL = 0;
|
|
@@ -14,7 +14,7 @@ $media-expressions: (
|
|
|
14
14
|
|
|
15
15
|
@mixin scrollbars {
|
|
16
16
|
scrollbar-color: var(--scrollbar--thumb--color) var(--scrollbar--thumb--track);
|
|
17
|
-
scrollbar-width:
|
|
17
|
+
scrollbar-width: thin;
|
|
18
18
|
|
|
19
19
|
&::-webkit-scrollbar {
|
|
20
20
|
width: var(--scrollbar--size);
|
|
@@ -44,10 +44,7 @@ $media-expressions: (
|
|
|
44
44
|
|
|
45
45
|
&::after {
|
|
46
46
|
position: absolute;
|
|
47
|
-
|
|
48
|
-
right: 0;
|
|
49
|
-
bottom: 0;
|
|
50
|
-
left: 0;
|
|
47
|
+
inset: 0;
|
|
51
48
|
z-index: var(--z-index--focus-effect);
|
|
52
49
|
transition: var(--transition);
|
|
53
50
|
border-radius: var(--border--radius);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scrabble-solver/solver",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.8",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@scrabble-solver/solver",
|
|
9
|
-
"version": "2.13.
|
|
9
|
+
"version": "2.13.8",
|
|
10
10
|
"license": "CC-BY-NC-ND-4.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@kamilmielnik/trie": "^3.0.0"
|