@nyris/nyris-webapp 0.3.42 → 0.3.44

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 (65) hide show
  1. package/build/asset-manifest.json +16 -12
  2. package/build/index.html +1 -1
  3. package/build/{precache-manifest.009e864ff0764cf3cf8a9b290c334099.js → precache-manifest.c92406fe2e3b0feaf429c551125e2d95.js} +26 -10
  4. package/build/service-worker.js +1 -1
  5. package/build/static/css/main.1b40c5ff.chunk.css +2 -0
  6. package/build/static/css/main.1b40c5ff.chunk.css.map +1 -0
  7. package/build/static/js/2.82ef1cd4.chunk.js +3 -0
  8. package/build/static/js/2.82ef1cd4.chunk.js.map +1 -0
  9. package/build/static/js/main.7cdac2fb.chunk.js +3 -0
  10. package/build/static/js/main.7cdac2fb.chunk.js.map +1 -0
  11. package/build/static/media/avatar.4c5346ed.svg +3 -0
  12. package/build/static/media/logout.07b9ef7f.svg +3 -0
  13. package/build/static/media/powered_by_nyris.e6766baf.svg +3 -0
  14. package/build/static/media/powered_by_nyris_colored.08d00bae.svg +9 -0
  15. package/package.json +3 -3
  16. package/public/index.html +4 -16
  17. package/src/Router.tsx +1 -0
  18. package/src/Store/Store.ts +2 -4
  19. package/src/Store/constants.ts +6 -0
  20. package/src/Store/search/Search.ts +10 -3
  21. package/src/Store/search/types.ts +1 -0
  22. package/src/common/assets/icons/avatar.svg +3 -0
  23. package/src/common/assets/icons/logout.svg +3 -0
  24. package/src/common/assets/images/powered_by_nyris.svg +3 -0
  25. package/src/common/assets/images/powered_by_nyris_colored.svg +9 -0
  26. package/src/components/AppMobile.tsx +1 -0
  27. package/src/components/AuthenticatedRoute.tsx +4 -1
  28. package/src/components/DragDropFile.tsx +3 -4
  29. package/src/components/FooterMobile.tsx +137 -24
  30. package/src/components/Header.tsx +120 -1
  31. package/src/components/HeaderMobile.tsx +230 -163
  32. package/src/components/ImagePreviewMobile.tsx +57 -8
  33. package/src/components/Layout.tsx +10 -53
  34. package/src/components/NoAccess.tsx +66 -0
  35. package/src/components/PoweredByNyris.tsx +49 -0
  36. package/src/components/ProductDetailView.tsx +16 -10
  37. package/src/components/ProductList/index.tsx +16 -93
  38. package/src/components/ProductList/useProductList.ts +114 -0
  39. package/src/components/Provider/InstantSearchProvider.tsx +66 -0
  40. package/src/components/appMobile.scss +2 -2
  41. package/src/components/common.scss +8 -1
  42. package/src/components/drawer/cameraCustom.tsx +3 -3
  43. package/src/components/input/inputSearch.tsx +86 -17
  44. package/src/components/pre-filter/index.tsx +58 -7
  45. package/src/components/results/ItemResult.tsx +6 -1
  46. package/src/index.tsx +1 -1
  47. package/src/page/landingPage/common.scss +4 -1
  48. package/src/page/result/index.tsx +154 -131
  49. package/src/services/Feedback.ts +1 -1
  50. package/src/services/image.ts +8 -5
  51. package/src/types.ts +13 -12
  52. package/build/static/css/main.86d40309.chunk.css +0 -2
  53. package/build/static/css/main.86d40309.chunk.css.map +0 -1
  54. package/build/static/js/2.1757789c.chunk.js +0 -3
  55. package/build/static/js/2.1757789c.chunk.js.map +0 -1
  56. package/build/static/js/main.1d184393.chunk.js +0 -3
  57. package/build/static/js/main.1d184393.chunk.js.map +0 -1
  58. package/src/Store/auth/Auth.ts +0 -33
  59. package/src/Store/auth/types.ts +0 -11
  60. package/src/Store/nyris/Nyris.ts +0 -67
  61. package/src/Store/nyris/types.ts +0 -11
  62. package/src/components/Feedback.tsx +0 -91
  63. /package/build/static/js/{2.1757789c.chunk.js.LICENSE.txt → 2.82ef1cd4.chunk.js.LICENSE.txt} +0 -0
  64. /package/build/static/js/{main.1d184393.chunk.js.LICENSE.txt → main.7cdac2fb.chunk.js.LICENSE.txt} +0 -0
  65. /package/src/components/{AuthProvider.tsx → Provider/AuthProvider.tsx} +0 -0
@@ -1,13 +1,65 @@
1
- import { Box } from '@material-ui/core';
1
+ import { Box, Menu, MenuProps, withStyles } from '@material-ui/core';
2
2
  import React from 'react';
3
3
  import { NavLink } from 'react-router-dom';
4
4
  import './common.scss';
5
5
  import { useAppDispatch, useAppSelector } from 'Store/Store';
6
6
  import { reset, setPreFilter } from 'Store/search/Search';
7
+ import { useAuth0 } from '@auth0/auth0-react';
8
+ import { ReactComponent as AvatarIcon } from 'common/assets/icons/avatar.svg';
9
+ import MenuItem from '@material-ui/core/MenuItem';
7
10
 
8
11
  function Header(): JSX.Element {
9
12
  const dispatch = useAppDispatch();
10
13
  const { settings } = useAppSelector(state => state);
14
+ const { user, isAuthenticated, logout } = useAuth0();
15
+ const auth0 = settings.auth0;
16
+
17
+ const [anchorEl, setAnchorEl] = React.useState(null);
18
+
19
+ const handleClick = (event: any) => {
20
+ setAnchorEl(event.currentTarget);
21
+ };
22
+
23
+ const handleClose = () => {
24
+ setAnchorEl(null);
25
+ };
26
+
27
+ const StyledMenu = withStyles({
28
+ root: {},
29
+ paper: {
30
+ border: '0px',
31
+ boxShadow: '0px 0px 8px 0px rgba(0, 0, 0, 0.20)',
32
+ top: '58px !important',
33
+ borderRadius: '0px !important',
34
+ },
35
+ })((props: MenuProps) => (
36
+ <Menu
37
+ elevation={0}
38
+ getContentAnchorEl={null}
39
+ anchorOrigin={{
40
+ vertical: 'bottom',
41
+ horizontal: 'center',
42
+ }}
43
+ transformOrigin={{
44
+ vertical: 'top',
45
+ horizontal: 'center',
46
+ }}
47
+ {...props}
48
+ />
49
+ ));
50
+
51
+ const StyledMenuItem = withStyles(theme => ({
52
+ root: {
53
+ '&:focus': {
54
+ backgroundColor: theme.palette.primary.main,
55
+ '& .MuiListItemIcon-root, & .MuiListItemText-primary': {
56
+ color: theme.palette.common.white,
57
+ },
58
+ },
59
+ padding: '0px',
60
+ },
61
+ }))(MenuItem);
62
+
11
63
  return (
12
64
  <Box className="box-content" display={'flex'}>
13
65
  <NavLink
@@ -28,6 +80,73 @@ function Header(): JSX.Element {
28
80
  }}
29
81
  />
30
82
  </NavLink>
83
+
84
+ {auth0.enabled && isAuthenticated && (
85
+ <div style={{ position: 'relative' }}>
86
+ <div
87
+ style={{
88
+ display: 'flex',
89
+ columnGap: '16px',
90
+ alignItems: 'center',
91
+ paddingRight: '24px',
92
+ cursor: 'pointer',
93
+ }}
94
+ aria-controls="simple-menu"
95
+ aria-haspopup="true"
96
+ onClick={handleClick}
97
+ >
98
+ <p style={{ color: '#2B2C46' }}>{user?.email}</p>
99
+ <AvatarIcon />
100
+ </div>
101
+ <StyledMenu
102
+ id="simple-menu"
103
+ anchorEl={anchorEl}
104
+ keepMounted
105
+ open={Boolean(anchorEl)}
106
+ onClose={handleClose}
107
+ >
108
+ <StyledMenuItem>
109
+ <div
110
+ style={{
111
+ display: 'flex',
112
+ width: '152px',
113
+ paddingLeft: '8px',
114
+ paddingRight: '8px',
115
+ flexDirection: 'column',
116
+ alignItems: 'flex-start',
117
+ gap: '8px',
118
+ boxShadow: '0px 0px 8px 0px rgba(0, 0, 0, 0.20)',
119
+ // position: 'absolute',
120
+ // zIndex: 99,
121
+ // top: '50px',
122
+ backgroundColor: '#fff',
123
+ }}
124
+ >
125
+ <div
126
+ style={{
127
+ display: 'flex',
128
+ width: '75px',
129
+ height: '24px',
130
+ padding: '4px 8px',
131
+ alignItems: 'center',
132
+ backgroundColor: '#2B2C46',
133
+ color: '#fff',
134
+ fontSize: '10px',
135
+ cursor: 'pointer',
136
+ }}
137
+ onClick={() => {
138
+ logout({
139
+ logoutParams: { returnTo: window.location.origin },
140
+ });
141
+ }}
142
+ >
143
+ Sign out
144
+ </div>
145
+ </div>
146
+ </StyledMenuItem>
147
+ </StyledMenu>
148
+ </div>
149
+ )}
31
150
  </Box>
32
151
  );
33
152
  }
@@ -17,6 +17,9 @@ import {
17
17
  updateValueTextSearchMobile,
18
18
  setPreFilterDropdown,
19
19
  setPreFilter,
20
+ updateQueryText,
21
+ updateStatusLoading,
22
+ setSearchResults,
20
23
  } from 'Store/search/Search';
21
24
  import { useAppDispatch, useAppSelector } from 'Store/Store';
22
25
  import { AppState } from 'types';
@@ -26,6 +29,8 @@ import { ReactComponent as FilterIcon } from 'common/assets/icons/filter.svg';
26
29
  import { debounce, isEmpty } from 'lodash';
27
30
  import { useQuery } from 'hooks/useQuery';
28
31
  import { useTranslation } from 'react-i18next';
32
+ import { find } from 'services/image';
33
+ import { useAuth0 } from '@auth0/auth0-react';
29
34
 
30
35
  interface Props {
31
36
  onToggleFilterMobile?: any;
@@ -34,6 +39,9 @@ interface Props {
34
39
  }
35
40
 
36
41
  function HeaderMobileComponent(props: Props): JSX.Element {
42
+ const { user } = useAuth0();
43
+ const { auth0 } = useAppSelector(state => state.settings);
44
+
37
45
  const { onToggleFilterMobile, refine } = props;
38
46
  const dispatch = useAppDispatch();
39
47
  const stateGlobal = useAppSelector(state => state);
@@ -44,14 +52,18 @@ function HeaderMobileComponent(props: Props): JSX.Element {
44
52
  preFilter,
45
53
  preFilterDropdown,
46
54
  valueTextSearch,
55
+ queryText,
56
+ requestImage,
57
+ selectedRegion,
47
58
  } = search;
48
59
 
49
60
  const query = useQuery();
50
- const searchQuery = query.get('query') || '';
51
61
  const containerRefInputMobile = useRef<HTMLDivElement>(null);
52
62
  const [isShowFilter, setShowFilter] = useState<boolean>(false);
53
63
  const history = useHistory();
54
64
  const { settings } = useAppSelector<AppState>((state: any) => state);
65
+ const [valueInput, setValueInput] = useState<string>(queryText || '');
66
+ const searchQuery = query.get('query') || '';
55
67
 
56
68
  useEffect(() => {
57
69
  if (
@@ -68,23 +80,75 @@ function HeaderMobileComponent(props: Props): JSX.Element {
68
80
  if (imageThumbSearchInput !== '') {
69
81
  history.push('/result');
70
82
  dispatch(updateValueTextSearchMobile(''));
71
- refine('');
83
+ if (settings.algolia?.enabled) {
84
+ refine('');
85
+ } else {
86
+ dispatch(updateQueryText(''));
87
+ setValueInput('');
88
+ }
72
89
  }
73
- }, [imageThumbSearchInput, dispatch, refine, history]);
90
+ }, [imageThumbSearchInput, dispatch, refine, history, settings.algolia]);
74
91
 
75
92
  useEffect(() => {
76
93
  if (!isEmpty(searchQuery)) {
77
94
  dispatch(updateValueTextSearchMobile(searchQuery));
78
- refine(searchQuery);
79
- // not an ideal solution: fixes text search not working from landing page
80
- setTimeout(() => {
95
+ if (settings.algolia?.enabled) {
81
96
  refine(searchQuery);
82
- }, 100);
97
+ // not an ideal solution: fixes text search not working from landing page
98
+ setTimeout(() => {
99
+ refine(searchQuery);
100
+ }, 100);
101
+ } else {
102
+ dispatch(updateQueryText(searchQuery));
103
+ }
83
104
  }
84
- }, [query, refine, dispatch, searchQuery]);
105
+ }, [query, refine, dispatch, searchQuery, settings.algolia]);
85
106
 
86
107
  const searchOrRedirect = useCallback(
87
108
  debounce((value: any) => {
109
+ if (!settings.algolia?.enabled) {
110
+ dispatch(updateQueryText(value));
111
+ let payload: any;
112
+ let filters: any[] = [];
113
+ const preFilterValues = [
114
+ {
115
+ key: settings.visualSearchFilterKey,
116
+ values: Object.keys(preFilter) as string[],
117
+ },
118
+ ];
119
+
120
+ if (value || requestImage) {
121
+ dispatch(updateStatusLoading(true));
122
+ find({
123
+ image: requestImage?.canvas as HTMLCanvasElement,
124
+ settings,
125
+ filters: !isEmpty(preFilter) ? preFilterValues : undefined,
126
+ region: selectedRegion,
127
+ text: value,
128
+ })
129
+ .then((res: any) => {
130
+ res?.results.map((item: any) => {
131
+ filters.push({
132
+ sku: item.sku,
133
+ score: item.score,
134
+ });
135
+ });
136
+ payload = {
137
+ ...res,
138
+ filters,
139
+ };
140
+ dispatch(setSearchResults(payload));
141
+ dispatch(updateStatusLoading(false));
142
+ })
143
+ .catch((e: any) => {
144
+ console.log('error input search', e);
145
+ dispatch(updateStatusLoading(false));
146
+ });
147
+ } else {
148
+ dispatch(setSearchResults([]));
149
+ }
150
+ }
151
+
88
152
  if (value) {
89
153
  history.push({
90
154
  pathname: '/result',
@@ -94,7 +158,7 @@ function HeaderMobileComponent(props: Props): JSX.Element {
94
158
  history.push('/result');
95
159
  }
96
160
  }, 500),
97
- [],
161
+ [requestImage],
98
162
  );
99
163
  const isPostFilterApplied = useMemo(() => {
100
164
  let isApplied = false;
@@ -127,7 +191,7 @@ function HeaderMobileComponent(props: Props): JSX.Element {
127
191
  }, [settings.postFilterOption, props.allSearchResults?.hits]);
128
192
 
129
193
  return (
130
- <div style={{ width: '100%', background: '#fafafa' }}>
194
+ <div style={{ width: '100%', background: '#fff' }}>
131
195
  {history.location?.pathname !== '/result' && (
132
196
  <Box
133
197
  className="box-content"
@@ -135,7 +199,6 @@ function HeaderMobileComponent(props: Props): JSX.Element {
135
199
  display: 'flex',
136
200
  alignItems: 'center',
137
201
  height: '48px',
138
- borderBottom: '1px solid #e9e9ec',
139
202
  background: settings.theme?.headerColor,
140
203
  }}
141
204
  >
@@ -159,189 +222,193 @@ function HeaderMobileComponent(props: Props): JSX.Element {
159
222
  </NavLink>
160
223
  </Box>
161
224
  )}
162
- <div
163
- style={{
164
- margin: '16px 8px',
165
- display: 'flex',
166
- columnGap: '8px',
167
- alignItems: 'center',
168
- }}
169
- >
170
- <div className="wrap-header-mobile" style={{ height: '56px' }}>
171
- <div
172
- style={{
173
- display: 'flex',
174
- alignItems: 'center',
175
- height: '100%',
176
- }}
177
- >
225
+
226
+ {((auth0.enabled && user?.email_verified) || !auth0.enabled) && (
227
+ <div
228
+ style={{
229
+ margin: '16px 8px',
230
+ display: 'flex',
231
+ columnGap: '8px',
232
+ alignItems: 'center',
233
+ }}
234
+ >
235
+ <div className="wrap-header-mobile" style={{ height: '56px' }}>
178
236
  <div
179
- ref={containerRefInputMobile}
180
- id="box-input-search"
181
- className="d-flex w-100"
182
237
  style={{
238
+ display: 'flex',
183
239
  alignItems: 'center',
184
240
  height: '100%',
185
241
  }}
186
242
  >
187
- <Box
188
- className="pre-filter-icon"
189
- onClick={() => {
190
- if (settings.preFilterOption) {
191
- onToggleFilterMobile(false);
192
- dispatch(setPreFilterDropdown(!preFilterDropdown));
193
- }
243
+ <div
244
+ ref={containerRefInputMobile}
245
+ id="box-input-search"
246
+ className="d-flex w-100"
247
+ style={{
248
+ alignItems: 'center',
249
+ height: '100%',
194
250
  }}
195
- style={{ cursor: settings.preFilterOption ? 'pointer' : '' }}
196
251
  >
197
- {settings.preFilterOption && (
198
- <div
199
- className="icon-hover"
200
- style={{
201
- ...(!isEmpty(preFilter)
202
- ? {
203
- backgroundColor: `${settings.theme?.primaryColor}`,
204
- }
205
- : {
206
- backgroundColor: `#2B2C46`,
207
- }),
208
- }}
209
- >
210
- <IconFilter color="white" />
211
- </div>
212
- )}
213
- {!settings.preFilterOption && (
214
- <IconSearch width={16} height={16} />
215
- )}
216
- {!isEmpty(preFilter) && (
217
- <div
218
- style={{
219
- position: 'absolute',
220
- top: '7px',
221
- left: '35px',
222
- display: 'flex',
223
- justifyContent: 'center',
224
- alignItems: 'center',
225
- background: 'white',
226
- width: '10px',
227
- height: '10px',
228
- borderRadius: '100%',
229
- }}
230
- >
252
+ <Box
253
+ className="pre-filter-icon"
254
+ onClick={() => {
255
+ if (settings.preFilterOption) {
256
+ onToggleFilterMobile(false);
257
+ dispatch(setPreFilterDropdown(!preFilterDropdown));
258
+ }
259
+ }}
260
+ style={{ cursor: settings.preFilterOption ? 'pointer' : '' }}
261
+ >
262
+ {settings.preFilterOption && (
263
+ <div
264
+ className="icon-hover"
265
+ style={{
266
+ ...(!isEmpty(preFilter)
267
+ ? {
268
+ backgroundColor: `${settings.theme?.primaryColor}`,
269
+ }
270
+ : {
271
+ backgroundColor: `#2B2C46`,
272
+ }),
273
+ }}
274
+ >
275
+ <IconFilter color="white" />
276
+ </div>
277
+ )}
278
+ {!settings.preFilterOption && (
279
+ <IconSearch width={16} height={16} />
280
+ )}
281
+ {!isEmpty(preFilter) && (
231
282
  <div
232
283
  style={{
233
- width: '8px',
234
- height: '8px',
235
- background: settings.theme?.primaryColor,
284
+ position: 'absolute',
285
+ top: '7px',
286
+ left: '35px',
287
+ display: 'flex',
288
+ justifyContent: 'center',
289
+ alignItems: 'center',
290
+ background: 'white',
291
+ width: '10px',
292
+ height: '10px',
236
293
  borderRadius: '100%',
237
294
  }}
238
- ></div>
239
- </div>
240
- )}
241
- </Box>
295
+ >
296
+ <div
297
+ style={{
298
+ width: '8px',
299
+ height: '8px',
300
+ background: settings.theme?.primaryColor,
301
+ borderRadius: '100%',
302
+ }}
303
+ ></div>
304
+ </div>
305
+ )}
306
+ </Box>
242
307
 
243
- <Input
244
- value={textSearchInputMobile || searchQuery}
245
- onChange={onChangeText}
246
- />
308
+ <Input
309
+ value={textSearchInputMobile || searchQuery || valueInput}
310
+ onChange={onChangeText}
311
+ />
247
312
 
248
- {history.location?.pathname !== '/' && textSearchInputMobile && (
249
- <Button
250
- onClick={() => {
251
- if (imageThumbSearchInput) {
252
- history.push('/result');
253
- dispatch(updateValueTextSearchMobile(''));
254
- refine('');
255
- return;
256
- }
257
- dispatch(updateValueTextSearchMobile(''));
258
- dispatch(reset(''));
259
- refine('');
260
- history.push('/');
261
- }}
262
- style={{
263
- // background: '#fff',
264
- marginRight: '8px',
265
- border: 0,
266
- width: '40px',
267
- height: '40px',
268
- }}
269
- >
270
- <CloseIcon
271
- style={{
272
- fontSize: 16,
273
- color: settings.theme?.secondaryColor,
274
- }}
275
- />
276
- </Button>
277
- )}
313
+ {history.location?.pathname !== '/' &&
314
+ textSearchInputMobile && (
315
+ <Button
316
+ onClick={() => {
317
+ if (imageThumbSearchInput) {
318
+ history.push('/result');
319
+ dispatch(updateValueTextSearchMobile(''));
320
+ refine('');
321
+ return;
322
+ }
323
+ dispatch(updateValueTextSearchMobile(''));
324
+ dispatch(reset(''));
325
+ refine('');
326
+ history.push('/');
327
+ }}
328
+ style={{
329
+ // background: '#fff',
330
+ marginRight: '8px',
331
+ border: 0,
332
+ width: '40px',
333
+ height: '40px',
334
+ }}
335
+ >
336
+ <CloseIcon
337
+ style={{
338
+ fontSize: 16,
339
+ color: settings.theme?.secondaryColor,
340
+ }}
341
+ />
342
+ </Button>
343
+ )}
344
+ </div>
278
345
  </div>
279
346
  </div>
280
- </div>
281
- {isShowFilter && settings.postFilterOption && (
282
- <div
283
- style={{
284
- position: 'relative',
285
- width: '56px',
286
- height: '56px',
287
- padding: ' 8px',
288
- flexShrink: 0,
289
- borderRadius: '32px',
290
- background: '#FAFAFA',
291
- boxShadow: ' 0px 0px 8px 0px rgba(0, 0, 0, 0.15)',
292
- }}
293
- onClick={() => {
294
- if (disablePostFilter) return;
295
- onToggleFilterMobile();
296
- dispatch(setPreFilterDropdown(false));
297
- }}
298
- >
347
+ {isShowFilter && settings.postFilterOption && (
299
348
  <div
300
349
  style={{
301
- display: 'flex',
302
- background: `${
303
- disablePostFilter ? '#F3F3F5' : settings.theme?.primaryColor
304
- }`,
305
- borderRadius: '40px',
306
- width: '40px',
307
- height: '40px',
308
- justifyContent: 'center',
309
- alignItems: 'center',
350
+ position: 'relative',
351
+ width: '56px',
352
+ height: '56px',
353
+ padding: ' 8px',
354
+ flexShrink: 0,
355
+ borderRadius: '32px',
356
+ background: '#FAFAFA',
357
+ boxShadow: ' 0px 0px 8px 0px rgba(0, 0, 0, 0.15)',
358
+ }}
359
+ onClick={() => {
360
+ if (disablePostFilter) return;
361
+ onToggleFilterMobile();
362
+ dispatch(setPreFilterDropdown(false));
310
363
  }}
311
364
  >
312
- <FilterIcon
313
- color={`${disablePostFilter ? '#E0E0E0' : 'white'}`}
314
- />
315
- </div>
316
-
317
- {isPostFilterApplied && !disablePostFilter && (
318
365
  <div
319
366
  style={{
320
- position: 'absolute',
321
- top: '8px',
322
- left: '37px',
323
367
  display: 'flex',
368
+ background: `${
369
+ disablePostFilter ? '#F3F3F5' : settings.theme?.primaryColor
370
+ }`,
371
+ borderRadius: '40px',
372
+ width: '40px',
373
+ height: '40px',
324
374
  justifyContent: 'center',
325
375
  alignItems: 'center',
326
- background: 'white',
327
- width: '10px',
328
- height: '10px',
329
- borderRadius: '100%',
330
376
  }}
331
377
  >
378
+ <FilterIcon
379
+ color={`${disablePostFilter ? '#E0E0E0' : 'white'}`}
380
+ />
381
+ </div>
382
+
383
+ {isPostFilterApplied && !disablePostFilter && (
332
384
  <div
333
385
  style={{
334
- width: '8px',
335
- height: '8px',
336
- background: settings.theme?.primaryColor,
386
+ position: 'absolute',
387
+ top: '8px',
388
+ left: '37px',
389
+ display: 'flex',
390
+ justifyContent: 'center',
391
+ alignItems: 'center',
392
+ background: 'white',
393
+ width: '10px',
394
+ height: '10px',
337
395
  borderRadius: '100%',
338
396
  }}
339
- ></div>
340
- </div>
341
- )}
342
- </div>
343
- )}
344
- </div>
397
+ >
398
+ <div
399
+ style={{
400
+ width: '8px',
401
+ height: '8px',
402
+ background: settings.theme?.primaryColor,
403
+ borderRadius: '100%',
404
+ }}
405
+ ></div>
406
+ </div>
407
+ )}
408
+ </div>
409
+ )}
410
+ </div>
411
+ )}
345
412
  </div>
346
413
  );
347
414
  }