@nuskin/foundation-ui-components 1.9.2 → 1.9.4
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/package.json +6 -6
- package/src/common/autocomplete/NsAutocomplete.spec.tsx +22 -28
- package/src/common/autocomplete/NsAutocomplete.styled.tsx +6 -8
- package/src/common/autocomplete/NsAutocomplete.tsx +14 -8
- package/src/common/autocomplete/helper/LineLoader.tsx +37 -0
- package/src/common/autocomplete/helper/RecentClearAll.tsx +36 -0
- package/src/common/autocomplete/helper/SeeMoreButton.tsx +31 -4
- package/src/common/autocomplete/helper/index.ts +4 -0
- package/src/common/autocomplete/helper/renderGroupName.tsx +0 -1
- package/src/common/autocomplete/mock/MockData.ts +13 -14
- package/src/common/autocomplete/mock/MockUI.tsx +4 -5
- package/src/common/autocomplete/types.d.ts +1 -0
- package/src/common/card/CardButton.tsx +31 -0
- package/src/common/card/NsAwardCard.tsx +8 -5
- package/src/common/card/NsBrandCard.tsx +8 -17
- package/src/common/card/NsCheckoutCard.tsx +8 -7
- package/src/common/card/NsHeroCardLevel1.tsx +39 -50
- package/src/common/card/NsHeroCardLevel2.tsx +28 -67
- package/src/common/card/NsIconText.tsx +4 -4
- package/src/common/card/NsLargeCard.tsx +28 -55
- package/src/common/card/NsMediumCard.tsx +10 -21
- package/src/common/card/NsPost.tsx +13 -8
- package/src/common/card/NsSmallFullCard.tsx +13 -22
- package/src/common/card/NsXLargeCard.tsx +12 -11
- package/src/common/card/cardSizes.ts +4 -4
- package/src/common/card/specs/NsAwardCard.spec.tsx +29 -0
- package/src/common/card/specs/NsBrandCard.spec.tsx +18 -31
- package/src/common/card/specs/NsCheckoutCard.spec.tsx +4 -15
- package/src/common/card/specs/NsHeroCardLevel1.spec.tsx +16 -24
- package/src/common/card/specs/NsHeroCardLevel2.spec.tsx +18 -20
- package/src/common/card/specs/NsIconText.spec.tsx +0 -3
- package/src/common/card/specs/NsLargeCard.spec.tsx +26 -19
- package/src/common/card/specs/NsMediumCard.spec.tsx +28 -12
- package/src/common/card/specs/NsPost.spec.tsx +8 -11
- package/src/common/card/specs/NsSmallFullCard.spec.tsx +23 -12
- package/src/common/card/specs/NsXLargeCard.spec.tsx +23 -11
- package/src/common/card/stories/NsAwardCard.stories.tsx +0 -3
- package/src/common/card/stories/NsBrandCard.stories.tsx +8 -3
- package/src/common/card/stories/NsCheckoutCard.stories.tsx +3 -4
- package/src/common/card/stories/NsHeroCardLevel1.stories.tsx +11 -24
- package/src/common/card/stories/NsHeroCardLevel2.stories.tsx +10 -29
- package/src/common/card/stories/NsIconText.stories.tsx +2 -20
- package/src/common/card/stories/NsLargeCard.stories.tsx +8 -7
- package/src/common/card/stories/NsMediumCard.stories.tsx +7 -6
- package/src/common/card/stories/NsPost.stories.tsx +2 -19
- package/src/common/card/stories/NsSmallFullCard.stories.tsx +7 -4
- package/src/common/card/stories/NsXLargeCard.stories.tsx +8 -4
- package/src/common/card/types.d.ts +12 -0
- package/src/common/carousal/RenderBrand.tsx +0 -1
- package/src/common/autocomplete/helper/AutoCompleteButton.tsx +0 -24
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuskin/foundation-ui-components",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.4",
|
|
4
4
|
"description": "It is a foundation library written in react, that provides common components to all UI pages",
|
|
5
5
|
"main": "src/common/index.ts",
|
|
6
6
|
"repository": {
|
|
@@ -42,12 +42,12 @@
|
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@emotion/react": "^11.11.1",
|
|
44
44
|
"@emotion/styled": "^11.11.0",
|
|
45
|
-
"@mui/icons-material": "^5.14.
|
|
46
|
-
"@mui/material": "5.14.
|
|
47
|
-
"@mui/utils": "^5.14.
|
|
45
|
+
"@mui/icons-material": "^5.14.16",
|
|
46
|
+
"@mui/material": "5.14.16",
|
|
47
|
+
"@mui/utils": "^5.14.16",
|
|
48
48
|
"@next/font": "13.5.6",
|
|
49
49
|
"@nuskin/foundation-theme": "1.2.0",
|
|
50
|
-
"@types/react": "^18.2.
|
|
50
|
+
"@types/react": "^18.2.34",
|
|
51
51
|
"@types/react-dom": "^18.2.14",
|
|
52
52
|
"cliui": "^8.0.1",
|
|
53
53
|
"framer-motion": "^10.16.4",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"@testing-library/jest-dom": "^6.1.4",
|
|
80
80
|
"@testing-library/react": "^14.0.0",
|
|
81
81
|
"@testing-library/react-hooks": "^8.0.1",
|
|
82
|
-
"@types/jest": "^29.5.
|
|
82
|
+
"@types/jest": "^29.5.7",
|
|
83
83
|
"@types/lodash": "^4.14.200",
|
|
84
84
|
"@types/node": "^20.8.7",
|
|
85
85
|
"@types/ramda": "^0.29.7",
|
|
@@ -2,9 +2,9 @@ import { render, screen, waitFor } from '@/test-utils/index';
|
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
|
|
5
|
-
import { AutocompleteMockList } from '
|
|
6
|
-
import { OptionUiComponent } from '
|
|
7
|
-
import NsAutocomplete from '
|
|
5
|
+
import { AutocompleteMockList } from '../autocomplete/mock/MockData';
|
|
6
|
+
import { OptionUiComponent } from '../autocomplete/mock/MockUI';
|
|
7
|
+
import NsAutocomplete from '../autocomplete/NsAutocomplete';
|
|
8
8
|
|
|
9
9
|
const commonProps = {
|
|
10
10
|
value: '',
|
|
@@ -14,6 +14,7 @@ const commonProps = {
|
|
|
14
14
|
options: AutocompleteMockList,
|
|
15
15
|
placeholder: 'autocomplete-input',
|
|
16
16
|
OptionsUI: OptionUiComponent,
|
|
17
|
+
// renderOption: (props: any) => <li {...props}>{props.value}</li>,
|
|
17
18
|
};
|
|
18
19
|
describe('CustomAutocomplete', () => {
|
|
19
20
|
it('1. should render autocomplete component', () => {
|
|
@@ -47,7 +48,7 @@ describe('CustomAutocomplete', () => {
|
|
|
47
48
|
it('4. selects an option when clicking on it', async () => {
|
|
48
49
|
const onChangeMock = jest.fn();
|
|
49
50
|
render(<NsAutocomplete {...commonProps} onChange={onChangeMock} />);
|
|
50
|
-
const autocompleteInput = screen.getByPlaceholderText(
|
|
51
|
+
const autocompleteInput = screen.getByPlaceholderText(commonProps.placeholder);
|
|
51
52
|
await userEvent.type(autocompleteInput, 'GS Facial');
|
|
52
53
|
await waitFor(async () => {
|
|
53
54
|
const optionLi = screen.getByText('GS Facial Spa');
|
|
@@ -57,39 +58,32 @@ describe('CustomAutocomplete', () => {
|
|
|
57
58
|
}, 40000);
|
|
58
59
|
|
|
59
60
|
it('5. should load more options when clicking load more button', async () => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
{...commonProps}
|
|
68
|
-
/>
|
|
69
|
-
);
|
|
70
|
-
const autocompleteInput = screen.getByPlaceholderText('autocomplete-input');
|
|
61
|
+
const seeMore = {
|
|
62
|
+
text: 'See More',
|
|
63
|
+
show: true,
|
|
64
|
+
onSeeMore: jest.fn(),
|
|
65
|
+
};
|
|
66
|
+
render(<NsAutocomplete seeMore={seeMore} {...commonProps} />);
|
|
67
|
+
const autocompleteInput = screen.getByPlaceholderText(commonProps.placeholder);
|
|
71
68
|
await userEvent.type(autocompleteInput, 'GS Facial');
|
|
72
69
|
await waitFor(async () => {
|
|
73
|
-
const loadMoreButton = screen.
|
|
70
|
+
const loadMoreButton = screen.getByText(seeMore.text);
|
|
74
71
|
await userEvent.click(loadMoreButton);
|
|
75
72
|
});
|
|
73
|
+
expect(seeMore.onSeeMore).toHaveBeenCalled();
|
|
76
74
|
}, 40000);
|
|
77
75
|
|
|
78
76
|
it('6. should clear options when clicking clear button', async () => {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
{...commonProps}
|
|
87
|
-
/>
|
|
88
|
-
);
|
|
89
|
-
const autocompleteInput = screen.getByPlaceholderText('autocomplete-input');
|
|
77
|
+
const clear = {
|
|
78
|
+
text: 'Clear All',
|
|
79
|
+
show: true,
|
|
80
|
+
onClear: jest.fn(),
|
|
81
|
+
};
|
|
82
|
+
render(<NsAutocomplete clear={clear} {...commonProps} />);
|
|
83
|
+
const autocompleteInput = screen.getByPlaceholderText(commonProps.placeholder);
|
|
90
84
|
await userEvent.type(autocompleteInput, 'GS Facial');
|
|
91
85
|
await waitFor(async () => {
|
|
92
|
-
const clearButton = screen.
|
|
86
|
+
const clearButton = screen.getByText(clear.text);
|
|
93
87
|
await userEvent.click(clearButton);
|
|
94
88
|
});
|
|
95
89
|
}, 40000);
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import { styled } from '@nuskin/foundation-theme';
|
|
2
|
-
|
|
1
|
+
import { styled, ColorUtils } from '@nuskin/foundation-theme';
|
|
3
2
|
import { NsInputField } from '../input';
|
|
3
|
+
const { getGenomeColor } = ColorUtils;
|
|
4
4
|
|
|
5
|
-
// TODO: why is .muiautocomplete-popupindicator added?
|
|
6
|
-
// TODO: ${({ theme }) => getGenomeColor(theme, 'N100')}; use forceMode light
|
|
7
5
|
export const StyledTextField = styled(NsInputField)`
|
|
8
6
|
.MuiAutocomplete-inputRoot {
|
|
9
7
|
padding-right: 10px !important;
|
|
10
8
|
}
|
|
11
|
-
.muiautocomplete-popupindicator {
|
|
12
|
-
display: none;
|
|
13
|
-
}
|
|
14
9
|
.styled-text-field.MuiOutlinedInput-root input#custom_autocomplete_dropdown::placeholder {
|
|
15
10
|
opacity: 1;
|
|
16
|
-
color:
|
|
11
|
+
color: ${({ theme }) => getGenomeColor(theme, 'N100', 'light')};
|
|
17
12
|
}
|
|
18
13
|
`;
|
|
14
|
+
// .muiautocomplete-popupindicator {
|
|
15
|
+
// display: none;
|
|
16
|
+
// }
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Autocomplete, AutocompleteRenderInputParams } from '@mui/material';
|
|
2
2
|
import React, { PropsWithChildren, useEffect, useRef, useState } from 'react';
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { LineLoader } from './helper/LineLoader';
|
|
5
|
+
import { RecentClearAll } from './helper/RecentClearAll';
|
|
5
6
|
import { renderGroupBy, renderGroupName, renderOptionLabel } from './helper/renderGroupName';
|
|
6
7
|
import { SeeMoreButton } from './helper/SeeMoreButton';
|
|
7
8
|
import { StyledTextField } from './NsAutocomplete.styled';
|
|
@@ -48,11 +49,14 @@ const NsAutocomplete = ({
|
|
|
48
49
|
/>
|
|
49
50
|
);
|
|
50
51
|
|
|
51
|
-
const renderOption = (props: ComponentBoxProps, option: OptionsProps) =>
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
const renderOption = (props: ComponentBoxProps, option: OptionsProps) =>
|
|
53
|
+
OptionsUI ? (
|
|
54
|
+
<OptionsUI {...props} option={option} key={props.id} />
|
|
55
|
+
) : (
|
|
56
|
+
<li {...props} key={props.id}>
|
|
57
|
+
{option.value}
|
|
58
|
+
</li>
|
|
59
|
+
);
|
|
56
60
|
|
|
57
61
|
const renderListBoxComponent = ({ children, ...rest }: ComponentBoxProps) => {
|
|
58
62
|
return (
|
|
@@ -64,11 +68,12 @@ const NsAutocomplete = ({
|
|
|
64
68
|
className={rest.className}
|
|
65
69
|
ref={listboxRef}
|
|
66
70
|
>
|
|
67
|
-
<
|
|
71
|
+
<RecentClearAll
|
|
68
72
|
show={clear?.show ?? false}
|
|
69
73
|
text={clear?.text ?? 'Clear All'}
|
|
70
74
|
onClick={clear?.onClear ?? noop}
|
|
71
75
|
testId="autocomplete-clear-id"
|
|
76
|
+
recentSearchText={clear?.recentSearchText ?? 'Your Recent Searches'}
|
|
72
77
|
/>
|
|
73
78
|
{children}
|
|
74
79
|
<SeeMoreButton
|
|
@@ -82,10 +87,11 @@ const NsAutocomplete = ({
|
|
|
82
87
|
</ul>
|
|
83
88
|
);
|
|
84
89
|
};
|
|
85
|
-
|
|
86
90
|
return (
|
|
87
91
|
<>
|
|
92
|
+
<LineLoader show={loading ?? false} />
|
|
88
93
|
<Autocomplete
|
|
94
|
+
openOnFocus
|
|
89
95
|
id={id}
|
|
90
96
|
disablePortal
|
|
91
97
|
className={className}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { styled } from '@nuskin/foundation-theme';
|
|
2
|
+
|
|
3
|
+
const StyledLine = styled.div`
|
|
4
|
+
position: fixed;
|
|
5
|
+
top: 0px;
|
|
6
|
+
left: 0;
|
|
7
|
+
width: 100%;
|
|
8
|
+
height: 2px;
|
|
9
|
+
background: #fff;
|
|
10
|
+
z-index: 99999;
|
|
11
|
+
overflow: hidden;
|
|
12
|
+
.dot {
|
|
13
|
+
position: absolute;
|
|
14
|
+
height: 100%;
|
|
15
|
+
width: 150px;
|
|
16
|
+
background: #f00;
|
|
17
|
+
animation: dotleft 1s cubic-bezier(0.72, 0.03, 0.75, 0.54) infinite;
|
|
18
|
+
}
|
|
19
|
+
@keyframes dotleft {
|
|
20
|
+
0% {
|
|
21
|
+
left: 0%;
|
|
22
|
+
width: 150px;
|
|
23
|
+
}
|
|
24
|
+
100% {
|
|
25
|
+
left: 100%;
|
|
26
|
+
width: 900px;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
export const LineLoader = ({ show }: { show: boolean }) => {
|
|
32
|
+
return (
|
|
33
|
+
<StyledLine className={`${show ? '' : 'hidden '} line`}>
|
|
34
|
+
<div className="dot">{show}</div>
|
|
35
|
+
</StyledLine>
|
|
36
|
+
);
|
|
37
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { styled } from '@nuskin/foundation-theme';
|
|
2
|
+
import { NsTypography } from '../../typography';
|
|
3
|
+
|
|
4
|
+
type AutoCompleteButtonProps = {
|
|
5
|
+
text: string;
|
|
6
|
+
show: boolean;
|
|
7
|
+
onClick(): void;
|
|
8
|
+
testId?: string;
|
|
9
|
+
recentSearchText: string;
|
|
10
|
+
};
|
|
11
|
+
export const StyledClear = styled(NsTypography)`
|
|
12
|
+
:hover {
|
|
13
|
+
opacity: 0.5;
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
export const RecentClearAll = (props: AutoCompleteButtonProps) => {
|
|
17
|
+
const { show, onClick, text, testId, recentSearchText } = props;
|
|
18
|
+
if (!show) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return (
|
|
22
|
+
<li className="justify-between flex p-3" onClick={onClick}>
|
|
23
|
+
<NsTypography data-testid={testId} variant="body-m" weight="bold">
|
|
24
|
+
{recentSearchText}
|
|
25
|
+
</NsTypography>
|
|
26
|
+
<StyledClear
|
|
27
|
+
data-testid={testId}
|
|
28
|
+
variant="body-m"
|
|
29
|
+
weight="bold"
|
|
30
|
+
className="cursor-pointer hover:opacity-40"
|
|
31
|
+
>
|
|
32
|
+
{text}
|
|
33
|
+
</StyledClear>
|
|
34
|
+
</li>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
@@ -1,7 +1,20 @@
|
|
|
1
1
|
import { Dispatch, MutableRefObject, SetStateAction, useCallback } from 'react';
|
|
2
|
+
import { styled, ColorUtils } from '@nuskin/foundation-theme';
|
|
2
3
|
|
|
3
|
-
import { OptionsProps } from '../..';
|
|
4
|
-
|
|
4
|
+
import { NsTypography, OptionsProps } from '../..';
|
|
5
|
+
const { getGenomeColor } = ColorUtils;
|
|
6
|
+
export const ListStyled = styled.div`
|
|
7
|
+
display: flex;
|
|
8
|
+
width: 100%;
|
|
9
|
+
flex-direction: row;
|
|
10
|
+
align-items: center;
|
|
11
|
+
gap: 10px;
|
|
12
|
+
padding: 4px 12px;
|
|
13
|
+
cursor: pointer;
|
|
14
|
+
&:hover {
|
|
15
|
+
background: ${({ theme }) => getGenomeColor(theme, 'A10')};
|
|
16
|
+
}
|
|
17
|
+
`;
|
|
5
18
|
|
|
6
19
|
type SeeMoreButtonProps = {
|
|
7
20
|
text?: string;
|
|
@@ -30,9 +43,23 @@ export const SeeMoreButton = (props: SeeMoreButtonProps) => {
|
|
|
30
43
|
setScrollTopPosition(lastScrollPosition);
|
|
31
44
|
}
|
|
32
45
|
}
|
|
33
|
-
if (
|
|
46
|
+
if (typeof onSeeMore === 'function') {
|
|
34
47
|
onSeeMore();
|
|
35
48
|
}
|
|
36
49
|
}, [listboxRef, onSeeMore, options?.length, setScrollTopPosition]);
|
|
37
|
-
|
|
50
|
+
if (!show) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return (
|
|
54
|
+
<ListStyled className="text-left p-3" onClick={handleSeeMore}>
|
|
55
|
+
<NsTypography
|
|
56
|
+
data-testid="autocomplete-loadmore-id"
|
|
57
|
+
variant="body-m"
|
|
58
|
+
decoration="underline"
|
|
59
|
+
className="cursor-pointer"
|
|
60
|
+
>
|
|
61
|
+
{text}
|
|
62
|
+
</NsTypography>
|
|
63
|
+
</ListStyled>
|
|
64
|
+
);
|
|
38
65
|
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable max-len */
|
|
2
1
|
import { OptionsProps } from '../types';
|
|
3
2
|
|
|
4
3
|
export const AutocompleteMockList: OptionsProps[] = [
|
|
@@ -6,19 +5,19 @@ export const AutocompleteMockList: OptionsProps[] = [
|
|
|
6
5
|
id: '1',
|
|
7
6
|
value: 'GS Facial Gels 2pk Subscription',
|
|
8
7
|
group: 'Popular Searches',
|
|
9
|
-
image: 'https://www.nuskin.com/content/products/86/99/01/86990168/_jcr_content/fullImage.img.160.160.png.64.64.png'
|
|
8
|
+
image: 'https://www.nuskin.com/content/products/86/99/01/86990168/_jcr_content/fullImage.img.160.160.png.64.64.png'
|
|
10
9
|
},
|
|
11
10
|
{
|
|
12
11
|
id: '2',
|
|
13
12
|
value: 'GS Facial',
|
|
14
13
|
group: 'Popular Searches',
|
|
15
|
-
image: 'https://www.nuskin.com/content/products/01/55/00/01550014/_jcr_content/fullImage.img.160.160.png.64.64.png'
|
|
14
|
+
image: 'https://www.nuskin.com/content/products/01/55/00/01550014/_jcr_content/fullImage.img.160.160.png.64.64.png'
|
|
16
15
|
},
|
|
17
16
|
{
|
|
18
17
|
id: '3',
|
|
19
18
|
value: 'GS Facial Spa',
|
|
20
19
|
group: 'Popular Searches',
|
|
21
|
-
image: 'https://www.nuskin.com/content/products/01/10/12/01101251/_jcr_content/fullImage.img.160.160.png.64.64.png'
|
|
20
|
+
image: 'https://www.nuskin.com/content/products/01/10/12/01101251/_jcr_content/fullImage.img.160.160.png.64.64.png'
|
|
22
21
|
},
|
|
23
22
|
{
|
|
24
23
|
id: '4',
|
|
@@ -26,7 +25,7 @@ export const AutocompleteMockList: OptionsProps[] = [
|
|
|
26
25
|
group: 'Popular Searches',
|
|
27
26
|
image: 'https://www.nuskin.com/content/products/01/55/00/01550013/_jcr_content/fullImage.img.160.160.png.64.64.png',
|
|
28
27
|
icon: 'cart',
|
|
29
|
-
groupBgColor: '#000'
|
|
28
|
+
groupBgColor: '#000'
|
|
30
29
|
},
|
|
31
30
|
{
|
|
32
31
|
id: '5',
|
|
@@ -34,7 +33,7 @@ export const AutocompleteMockList: OptionsProps[] = [
|
|
|
34
33
|
group: 'Popular Searches',
|
|
35
34
|
image: 'https://www.nuskin.com/content/products/86/99/01/86990100/_jcr_content/fullImage.img.160.160.png.64.64.png',
|
|
36
35
|
icon: 'cart',
|
|
37
|
-
groupBgColor: '#000'
|
|
36
|
+
groupBgColor: '#000'
|
|
38
37
|
},
|
|
39
38
|
{
|
|
40
39
|
id: '6',
|
|
@@ -42,26 +41,26 @@ export const AutocompleteMockList: OptionsProps[] = [
|
|
|
42
41
|
group: 'Popular Searches',
|
|
43
42
|
image: 'https://www.nuskin.com/content/products/01/00/16/01001647/jcr:content/fullImage.img.160.160.png/1611763135883-cache.png.64.64.png',
|
|
44
43
|
icon: 'cart',
|
|
45
|
-
groupBgColor: '#000'
|
|
44
|
+
groupBgColor: '#000'
|
|
46
45
|
},
|
|
47
46
|
|
|
48
47
|
{
|
|
49
48
|
id: '7',
|
|
50
49
|
value: 'Rejuvenating Cream',
|
|
51
50
|
group: 'Popular Searches',
|
|
52
|
-
image: 'https://www.nuskin.com/content/products/86/99/01/86990168/_jcr_content/fullImage.img.160.160.png.64.64.png'
|
|
51
|
+
image: 'https://www.nuskin.com/content/products/86/99/01/86990168/_jcr_content/fullImage.img.160.160.png.64.64.png'
|
|
53
52
|
},
|
|
54
53
|
{
|
|
55
54
|
id: '8',
|
|
56
55
|
value: 'Epoch® Firewalker® Foot Cream',
|
|
57
56
|
group: 'Popular Searches',
|
|
58
|
-
image: 'https://www.nuskin.com/content/products/01/55/00/01550014/_jcr_content/fullImage.img.160.160.png.64.64.png'
|
|
57
|
+
image: 'https://www.nuskin.com/content/products/01/55/00/01550014/_jcr_content/fullImage.img.160.160.png.64.64.png'
|
|
59
58
|
},
|
|
60
59
|
{
|
|
61
60
|
id: '9',
|
|
62
61
|
value: 'Tri-Phasic White® Night Cream',
|
|
63
62
|
group: 'Popular Searches',
|
|
64
|
-
image: 'https://www.nuskin.com/content/products/01/10/12/01101251/_jcr_content/fullImage.img.160.160.png.64.64.png'
|
|
63
|
+
image: 'https://www.nuskin.com/content/products/01/10/12/01101251/_jcr_content/fullImage.img.160.160.png.64.64.png'
|
|
65
64
|
},
|
|
66
65
|
{
|
|
67
66
|
id: '10',
|
|
@@ -69,7 +68,7 @@ export const AutocompleteMockList: OptionsProps[] = [
|
|
|
69
68
|
group: 'Popular Searches',
|
|
70
69
|
image: 'https://www.nuskin.com/content/products/01/55/00/01550013/_jcr_content/fullImage.img.160.160.png.64.64.png',
|
|
71
70
|
icon: 'cart',
|
|
72
|
-
groupBgColor: '#000'
|
|
71
|
+
groupBgColor: '#000'
|
|
73
72
|
},
|
|
74
73
|
{
|
|
75
74
|
id: '11',
|
|
@@ -77,7 +76,7 @@ export const AutocompleteMockList: OptionsProps[] = [
|
|
|
77
76
|
group: 'Popular Searches',
|
|
78
77
|
image: 'https://www.nuskin.com/content/products/86/99/01/86990100/_jcr_content/fullImage.img.160.160.png.64.64.png',
|
|
79
78
|
icon: 'cart',
|
|
80
|
-
groupBgColor: '#000'
|
|
79
|
+
groupBgColor: '#000'
|
|
81
80
|
},
|
|
82
81
|
{
|
|
83
82
|
id: '12',
|
|
@@ -85,6 +84,6 @@ export const AutocompleteMockList: OptionsProps[] = [
|
|
|
85
84
|
group: 'Popular Searches',
|
|
86
85
|
image: 'https://www.nuskin.com/content/products/01/00/16/01001647/jcr:content/fullImage.img.160.160.png/1611763135883-cache.png.64.64.png',
|
|
87
86
|
icon: 'cart',
|
|
88
|
-
groupBgColor: '#000'
|
|
89
|
-
}
|
|
87
|
+
groupBgColor: '#000'
|
|
88
|
+
}
|
|
90
89
|
];
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/* eslint-disable @next/next/no-img-element */
|
|
2
|
+
import { ListUiProps, NsIcon, NsTypography } from '../..';
|
|
2
3
|
import { ListStyled } from './Mock.styled';
|
|
3
|
-
import { NsTypography } from '../../typography';
|
|
4
|
-
import { NsIcon } from '../../icon';
|
|
5
|
-
import { ListUiProps } from '../types';
|
|
6
4
|
|
|
7
|
-
const OptionUiComponent = (
|
|
5
|
+
const OptionUiComponent = (props: ListUiProps) => {
|
|
6
|
+
const { option } = props;
|
|
8
7
|
return (
|
|
9
|
-
<ListStyled>
|
|
8
|
+
<ListStyled {...props}>
|
|
10
9
|
<div className="item-description" role="link" tabIndex={0}>
|
|
11
10
|
<NsTypography aria-label="Nu Skin Tumbler" variant="body-m" colorOverride="#63666A">
|
|
12
11
|
<img src={option.image} alt="No-image" />
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { NsButton, NsIcon } from '..';
|
|
2
|
+
import { NsCardButton } from './types';
|
|
3
|
+
|
|
4
|
+
const CardButton = ({
|
|
5
|
+
url,
|
|
6
|
+
endIcon,
|
|
7
|
+
buttonText,
|
|
8
|
+
showButton = true,
|
|
9
|
+
buttonVariant = 'outlined',
|
|
10
|
+
buttonColor = 'primary',
|
|
11
|
+
fullWidth = false,
|
|
12
|
+
}: NsCardButton) => {
|
|
13
|
+
if (showButton && url) {
|
|
14
|
+
return (
|
|
15
|
+
<div className="cta">
|
|
16
|
+
<NsButton
|
|
17
|
+
href={url}
|
|
18
|
+
color={buttonColor}
|
|
19
|
+
variant={buttonVariant}
|
|
20
|
+
fullWidth={fullWidth}
|
|
21
|
+
endIcon={endIcon ? <NsIcon name={endIcon} color={buttonColor} /> : null}
|
|
22
|
+
>
|
|
23
|
+
{buttonText}
|
|
24
|
+
</NsButton>
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
return null;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default CardButton;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Box from '@mui/material/Box';
|
|
2
2
|
import { styled } from '@nuskin/foundation-theme';
|
|
3
|
-
import { NsImage } from '
|
|
3
|
+
import { NsImage } from '../';
|
|
4
4
|
|
|
5
5
|
type NsAwardCardProps = {
|
|
6
6
|
title: string;
|
|
@@ -8,6 +8,7 @@ type NsAwardCardProps = {
|
|
|
8
8
|
mediaOutlet: string;
|
|
9
9
|
backgroundImageUrl: string;
|
|
10
10
|
backgroundImageAlt: string;
|
|
11
|
+
className?: string;
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
const CardContainer = styled(Box)(() => {
|
|
@@ -15,17 +16,18 @@ const CardContainer = styled(Box)(() => {
|
|
|
15
16
|
display: 'flex',
|
|
16
17
|
flexDirection: 'column',
|
|
17
18
|
position: 'relative',
|
|
18
|
-
backgroundColor: '#fff',
|
|
19
19
|
alignItems: 'center',
|
|
20
|
+
width: '160px',
|
|
21
|
+
height: 'auto',
|
|
20
22
|
'.image': {
|
|
21
|
-
width: '
|
|
23
|
+
width: '160px',
|
|
22
24
|
height: 'auto',
|
|
23
25
|
objectFit: 'cover',
|
|
24
|
-
backgroundColor: 'red',
|
|
25
26
|
},
|
|
26
27
|
'.content': {
|
|
27
28
|
display: 'flex',
|
|
28
29
|
flexDirection: 'column',
|
|
30
|
+
textAlign: 'center',
|
|
29
31
|
alignItems: 'center',
|
|
30
32
|
},
|
|
31
33
|
'.title': {
|
|
@@ -57,9 +59,10 @@ export default function NsAwardCard({
|
|
|
57
59
|
mediaOutlet,
|
|
58
60
|
backgroundImageUrl,
|
|
59
61
|
backgroundImageAlt,
|
|
62
|
+
className,
|
|
60
63
|
}: NsAwardCardProps) {
|
|
61
64
|
return (
|
|
62
|
-
<CardContainer role="award-card" component="div" data-testid="award-card">
|
|
65
|
+
<CardContainer className={className} role="award-card" component="div" data-testid="award-card">
|
|
63
66
|
<NsImage alt={backgroundImageAlt} src={backgroundImageUrl} className="image" />
|
|
64
67
|
<div className="content">
|
|
65
68
|
<article className="title">{title}</article>
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
import { ShoppingCart } from '@mui/icons-material';
|
|
2
1
|
import Box from '@mui/material/Box';
|
|
3
2
|
import { styled } from '@nuskin/foundation-theme';
|
|
4
3
|
import { NsTypography } from '../';
|
|
5
4
|
import NsBrandWrapper from './NsBrandWrapper';
|
|
6
5
|
import NsBrandLogo from './NsBrandLogo';
|
|
7
6
|
import NsBgCard from './NsBgCard';
|
|
8
|
-
import NsButton from '../button/NsButton';
|
|
9
7
|
import cardSizes from './cardSizes';
|
|
8
|
+
import CardButton from './CardButton';
|
|
9
|
+
import { NsCardButton } from './types';
|
|
10
10
|
|
|
11
11
|
type NsBrandCardProps = {
|
|
12
12
|
title?: string;
|
|
13
13
|
brandImageUrl: string;
|
|
14
14
|
backgroundImageUrl: string;
|
|
15
15
|
size?: 'small' | 'large';
|
|
16
|
-
button?:
|
|
17
|
-
|
|
16
|
+
button?: NsCardButton;
|
|
17
|
+
className?: string;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
const CardContainer = styled((props: any) => <Box {...props} />)(({ size }) => {
|
|
@@ -49,6 +49,7 @@ const CardContainer = styled((props: any) => <Box {...props} />)(({ size }) => {
|
|
|
49
49
|
},
|
|
50
50
|
'.cta': {
|
|
51
51
|
marginTop: '15px',
|
|
52
|
+
width: '100%',
|
|
52
53
|
},
|
|
53
54
|
'.image': {
|
|
54
55
|
width,
|
|
@@ -64,10 +65,10 @@ export default function NsBrandCard({
|
|
|
64
65
|
backgroundImageUrl,
|
|
65
66
|
button,
|
|
66
67
|
size,
|
|
67
|
-
|
|
68
|
+
className,
|
|
68
69
|
}: NsBrandCardProps) {
|
|
69
70
|
return (
|
|
70
|
-
<CardContainer role="brand-card" component="div" data-testid="brand-card" size={size}
|
|
71
|
+
<CardContainer className={className} role="brand-card" component="div" data-testid="brand-card" size={size}>
|
|
71
72
|
<NsBgCard backgroundImageUrl={backgroundImageUrl} className="image">
|
|
72
73
|
<NsBrandWrapper>
|
|
73
74
|
<NsBrandLogo component="img" image={brandImageUrl} />
|
|
@@ -78,17 +79,7 @@ export default function NsBrandCard({
|
|
|
78
79
|
{title}
|
|
79
80
|
</NsTypography>
|
|
80
81
|
) : null}
|
|
81
|
-
{button ?
|
|
82
|
-
<NsButton
|
|
83
|
-
className="cta"
|
|
84
|
-
darkModeEnabled={false}
|
|
85
|
-
variant="outlined"
|
|
86
|
-
fullWidth={true}
|
|
87
|
-
endIcon={<ShoppingCart />}
|
|
88
|
-
>
|
|
89
|
-
Add to Cart
|
|
90
|
-
</NsButton>
|
|
91
|
-
) : null}
|
|
82
|
+
{button ? <CardButton {...button} /> : null}
|
|
92
83
|
</CardContainer>
|
|
93
84
|
);
|
|
94
85
|
}
|
|
@@ -6,8 +6,9 @@ import { useState } from 'react';
|
|
|
6
6
|
type NsCheckoutCardProps = {
|
|
7
7
|
icon: NsIconNameType;
|
|
8
8
|
title: string;
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
linkText: string;
|
|
10
|
+
url: string;
|
|
11
|
+
className?: string;
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
const CardContainer = styled(Box)(() => {
|
|
@@ -58,14 +59,14 @@ const CardContainer = styled(Box)(() => {
|
|
|
58
59
|
};
|
|
59
60
|
});
|
|
60
61
|
|
|
61
|
-
export default function NsCheckoutCard({ title,
|
|
62
|
+
export default function NsCheckoutCard({ title, icon, linkText, url, className }: NsCheckoutCardProps) {
|
|
62
63
|
const [dropdownIcon, setDropdownIcon] = useState(false);
|
|
63
64
|
const handleClick = () => {
|
|
64
65
|
setDropdownIcon(!dropdownIcon);
|
|
65
66
|
};
|
|
66
67
|
|
|
67
68
|
return (
|
|
68
|
-
<CardContainer role="checkout-card" component="div" data-testid="checkout-card"
|
|
69
|
+
<CardContainer className={className} role="checkout-card" component="div" data-testid="checkout-card">
|
|
69
70
|
<div className="left-bar"></div>
|
|
70
71
|
<div className="content">
|
|
71
72
|
<span>
|
|
@@ -73,9 +74,9 @@ export default function NsCheckoutCard({ title, address, icon, onClick }: NsChec
|
|
|
73
74
|
</span>
|
|
74
75
|
<div className="text-content">
|
|
75
76
|
<article className="title">{title}</article>
|
|
76
|
-
<article className="address">
|
|
77
|
-
<NsLink className="action-link" href={
|
|
78
|
-
|
|
77
|
+
<article className="address">Address</article>
|
|
78
|
+
<NsLink className="action-link" href={url}>
|
|
79
|
+
{linkText}
|
|
79
80
|
</NsLink>
|
|
80
81
|
</div>
|
|
81
82
|
<span className="icon-right">
|