@nuskin/foundation-ui-components 1.0.0-cft-35.13 → 1.0.0-develop.2
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 +1 -1
- package/src/common/alert/NsAlert.spec.tsx +17 -16
- package/src/common/alert/NsAlert.stories.tsx +2 -2
- package/src/common/alert/NsAlert.styled.ts +20 -20
- package/src/common/alert/NsAlert.tsx +21 -40
- package/src/common/alert/index.ts +2 -2
- package/src/common/auth-dropdown/NsAuthDropdown.spec.tsx +1 -1
- package/src/common/auth-dropdown/NsAuthDropdown.tsx +1 -1
- package/src/common/auth-dropdown/index.ts +1 -1
- package/src/common/autocomplete/NsAutocomplete.spec.tsx +5 -5
- package/src/common/autocomplete/NsAutocomplete.stories.tsx +1 -1
- package/src/common/autocomplete/NsAutocomplete.tsx +1 -1
- package/src/common/autocomplete/index.ts +2 -1
- package/src/common/banner/NsBanner.spec.tsx +1 -1
- package/src/common/banner/NsBanner.styled.tsx +1 -1
- package/src/common/banner/NsBanner.tsx +1 -1
- package/src/common/banner/index.ts +1 -1
- package/src/common/brand-components/NsBrandComponent.tsx +1 -1
- package/src/common/brand-components/index.ts +1 -1
- package/src/common/breadcrumb/NsBreadcrumb.spec.tsx +1 -1
- package/src/common/breadcrumb/NsBreadcrumb.tsx +1 -1
- package/src/common/breadcrumb/index.ts +1 -1
- package/src/common/button/NsButton.spec.tsx +1 -1
- package/src/common/button/NsButton.styled.tsx +10 -13
- package/src/common/button/NsButton.tsx +1 -1
- package/src/common/button/index.ts +1 -1
- package/src/common/card/NsFfgCard.tsx +1 -1
- package/src/common/carousal/NsScrollingCarousal.tsx +37 -0
- package/src/common/carousal/index.ts +3 -0
- package/src/common/carousal/stories/NSCarousal.stories.tsx +1 -1
- package/src/common/carousal/stories/NsScrollingCarousal.stories.tsx +52 -0
- package/src/common/carousal/tests/NsCarousal.spec.tsx +2 -2
- package/src/common/carousal/tests/NsScrollingCarousal.spec.tsx +61 -0
- package/src/common/carousal/types.d.ts +21 -0
- package/src/common/cart-icon/NsCartIcon.spec.tsx +1 -1
- package/src/common/cart-icon/NsCartIcon.tsx +1 -1
- package/src/common/cart-icon/index.ts +1 -1
- package/src/common/checkbox/NsCheckbox.spec.tsx +2 -2
- package/src/common/checkbox/NsCheckbox.tsx +1 -1
- package/src/common/checkbox/index.ts +1 -1
- package/src/common/checkbox/types.d.ts +1 -7
- package/src/common/column-control/NsColumnControl.tsx +1 -1
- package/src/common/column-control/NsFlexColumns.tsx +27 -0
- package/src/common/column-control/NsGridColumns.tsx +27 -0
- package/src/common/column-control/index.ts +3 -1
- package/src/common/column-control/{NsColumnControl.spec.tsx → specs/NsColumnControl.spec.tsx} +3 -3
- package/src/common/column-control/specs/NsFlexColumns.spec.tsx +24 -0
- package/src/common/column-control/specs/NsGridColumns.spec.tsx +24 -0
- package/src/common/column-control/{NDivs.story.tsx → stories/NDivs.story.tsx} +1 -1
- package/src/common/column-control/{NsColumnControl.stories.tsx → stories/NsColumnControl.stories.tsx} +4 -14
- package/src/common/column-control/stories/NsFlexColumns.stories.tsx +59 -0
- package/src/common/column-control/stories/NsGridColumns.stories.tsx +59 -0
- package/src/common/column-control/stories/common.tsx +14 -0
- package/src/common/column-control/styled/StyledFlex.tsx +41 -0
- package/src/common/column-control/styled/StyledGrid.tsx +33 -0
- package/src/common/column-control/styled/common.ts +27 -0
- package/src/common/column-control/utils.ts +1 -1
- package/src/common/dropdown/NsDropdown.spec.tsx +1 -1
- package/src/common/dropdown/NsDropdown.tsx +1 -1
- package/src/common/dropdown/NsDropdownOption.tsx +1 -1
- package/src/common/dropdown/index.ts +1 -1
- package/src/common/flag/NsFlag.spec.tsx +1 -1
- package/src/common/flag/NsFlag.styled.tsx +3 -5
- package/src/common/flag/NsFlag.tsx +1 -1
- package/src/common/flag/index.ts +1 -1
- package/src/common/flag/types.d.ts +0 -2
- package/src/common/icon/NsIcon.spec.tsx +1 -1
- package/src/common/icon/NsIcon.styled.tsx +1 -1
- package/src/common/icon/NsIcon.tsx +1 -1
- package/src/common/icon/NsIconVariants.ts +8 -4
- package/src/common/icon/icons/AlertErrorIcon.tsx +15 -6
- package/src/common/icon/icons/HamburgerIcon.tsx +29 -0
- package/src/common/icon/icons/UserIcon.tsx +30 -0
- package/src/common/icon/icons/WarningIcon.tsx +14 -5
- package/src/common/icon/index.ts +1 -1
- package/src/common/image/NsImage.spec.tsx +1 -1
- package/src/common/image/NsImage.tsx +1 -1
- package/src/common/image/NsNextImage.spec.tsx +1 -1
- package/src/common/image/NsNextImage.tsx +1 -1
- package/src/common/image/index.ts +1 -1
- package/src/common/index.ts +7 -10
- package/src/common/input/InputWrapper.tsx +1 -1
- package/src/common/input/NsInputField.tsx +1 -1
- package/src/common/input/getAdornmentProps.tsx +1 -1
- package/src/common/input/index.ts +1 -1
- package/src/common/label/NsLabel.tsx +1 -1
- package/src/common/label/index.ts +1 -1
- package/src/common/link/NsLink.spec.tsx +1 -1
- package/src/common/link/NsLink.tsx +1 -1
- package/src/common/link/index.ts +1 -1
- package/src/common/nav-product-card/NsNavProductCard.spec.tsx +1 -1
- package/src/common/nav-product-card/NsNavProductCard.tsx +1 -1
- package/src/common/nav-product-card/index.ts +1 -1
- package/src/common/nav-tab/NsNavTab.spec.tsx +2 -2
- package/src/common/nav-tab/NsNavTab.tsx +1 -1
- package/src/common/nav-tab/index.ts +1 -1
- package/src/common/search-bar/NsSeachBar.spec.tsx +1 -1
- package/src/common/table/NsTable.spec.tsx +146 -0
- package/src/common/table/NsTable.stories.tsx +123 -0
- package/src/common/table/NsTable.styled.ts +33 -0
- package/src/common/table/NsTable.tsx +161 -0
- package/src/common/table/NsTableHeader.tsx +48 -0
- package/src/common/table/NsTablePagination.tsx +20 -0
- package/src/common/table/helper.ts +33 -0
- package/src/common/table/index.ts +2 -0
- package/src/common/table/types.d.ts +44 -0
- package/src/common/text-strip/NsTextStrip.spec.tsx +30 -0
- package/src/common/text-strip/NsTextStrip.stories.tsx +32 -0
- package/src/common/text-strip/NsTextStrip.tsx +41 -0
- package/src/common/text-strip/index.ts +2 -0
- package/src/common/text-strip/types.d.ts +14 -0
- package/src/common/typography/NsTypography.tsx +1 -1
- package/src/common/typography/Typography.styled.tsx +1 -1
- package/src/common/typography/index.ts +1 -1
- package/src/common/videos/NsVideo.tsx +1 -1
- package/src/common/videos/index.ts +1 -1
- /package/src/common/autocomplete/{types.ts → types.d.ts} +0 -0
- /package/src/common/{common.types.ts → common.types.d.ts} +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NsScrollingText.stories.tsx
|
|
3
|
+
* @description NsScrollingText component.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { StoryObj, Meta } from '@storybook/react';
|
|
7
|
+
import { withCenterDecorator } from '../../../stories/decorators/withCenterDecorator';
|
|
8
|
+
import { NsScrollingCarousal, NsTextStrip } from '@/common/';
|
|
9
|
+
|
|
10
|
+
type ComponentType = typeof NsScrollingCarousal;
|
|
11
|
+
type Story = StoryObj<ComponentType>;
|
|
12
|
+
type MetaStory = Meta<ComponentType>;
|
|
13
|
+
|
|
14
|
+
export const renderSlide = (slide: any, i: number) => <NsTextStrip key={i} {...slide} />;
|
|
15
|
+
|
|
16
|
+
export const slides = [
|
|
17
|
+
{
|
|
18
|
+
text: 'Hello Nike App',
|
|
19
|
+
description: 'Download the app to access everything Nike',
|
|
20
|
+
link: { href: 'https://www.nike.com/in/help/a/shipping-delivery-gs', title: 'Get Your Great' },
|
|
21
|
+
alignment: 'center',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
text: 'New Styles on Sale: Up to 40% Off',
|
|
25
|
+
// description: 'Download the app to access everything Nike',
|
|
26
|
+
link: { href: 'https://www.nike.com/in/help/a/shipping-delivery-gs', title: 'Shop All Our New Markdowns' },
|
|
27
|
+
alignment: 'center',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
text: 'Free Delivery',
|
|
31
|
+
// description: 'Applies to orders of ₹ 14 000.00 or more. ',
|
|
32
|
+
// link: { href: 'https://www.nike.com/in/help/a/shipping-delivery-gs', title: 'View Details' },
|
|
33
|
+
alignment: 'center',
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
export default {
|
|
37
|
+
title: 'Components/NsCarousal/NsScrollingCarousal',
|
|
38
|
+
component: NsScrollingCarousal,
|
|
39
|
+
decorators: [withCenterDecorator],
|
|
40
|
+
argTypes: {},
|
|
41
|
+
args: {
|
|
42
|
+
slides,
|
|
43
|
+
renderSlide,
|
|
44
|
+
stillSeconds: 3,
|
|
45
|
+
scrollSeconds: 1,
|
|
46
|
+
additionalProps: {
|
|
47
|
+
testid: 'scrolling-carousal',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
} as MetaStory;
|
|
51
|
+
|
|
52
|
+
export const ScrollingText: Story = {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { render, screen, fireEvent } from '
|
|
2
|
-
import NsCarousal from '
|
|
1
|
+
import { render, screen, fireEvent } from '@/test-utils/index';
|
|
2
|
+
import { NsCarousal } from '@/common/';
|
|
3
3
|
|
|
4
4
|
const mockEntries = [
|
|
5
5
|
{ id: 1, title: 'First entry' },
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { render, screen, fireEvent } from '@/test-utils/index';
|
|
2
|
+
import { NsScrollingCarousal } from '@/common/';
|
|
3
|
+
|
|
4
|
+
const mockEntries = [
|
|
5
|
+
{ id: 1, title: 'First entry' },
|
|
6
|
+
{ id: 2, title: 'Second entry' },
|
|
7
|
+
{ id: 3, title: 'Third entry' },
|
|
8
|
+
{ id: 4, title: 'Fourth entry' },
|
|
9
|
+
{ id: 5, title: 'Fifth entry' },
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
const mockRenderEntry = (entry: any, index: number) => {
|
|
13
|
+
return <div key={index}>{entry.title}</div>;
|
|
14
|
+
};
|
|
15
|
+
const mockSettings = {
|
|
16
|
+
slidesToShow: 2,
|
|
17
|
+
slidesToScroll: 1,
|
|
18
|
+
};
|
|
19
|
+
const testId = 'scrolling-carousal';
|
|
20
|
+
describe('NsScrollingCarousal', () => {
|
|
21
|
+
it('should have slides', () => {
|
|
22
|
+
render(
|
|
23
|
+
<NsScrollingCarousal
|
|
24
|
+
slides={mockEntries}
|
|
25
|
+
renderSlide={mockRenderEntry}
|
|
26
|
+
settings={mockSettings}
|
|
27
|
+
scrollSeconds={1}
|
|
28
|
+
stillSeconds={9}
|
|
29
|
+
additionalProps={{
|
|
30
|
+
testid: testId,
|
|
31
|
+
}}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
const el = screen.getAllByText(mockEntries[0].title);
|
|
35
|
+
expect(el).toHaveLength(2);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should change slides when clicking on prev or next buttons', () => {
|
|
39
|
+
const { container } = render(
|
|
40
|
+
<NsScrollingCarousal
|
|
41
|
+
slides={mockEntries}
|
|
42
|
+
renderSlide={mockRenderEntry}
|
|
43
|
+
settings={mockSettings}
|
|
44
|
+
scrollSeconds={1}
|
|
45
|
+
stillSeconds={9}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
let currentSlide = container.querySelector('.slick-slide.slick-current');
|
|
50
|
+
expect(currentSlide!.attributes['data-index' as any].value).toEqual('0');
|
|
51
|
+
|
|
52
|
+
/* this is library's button, not our button, it is used for changing slides,
|
|
53
|
+
clicking svg is not making any slide change in this test */
|
|
54
|
+
const nextButton = screen.getByRole('button', { name: /next/i });
|
|
55
|
+
fireEvent.click(nextButton);
|
|
56
|
+
|
|
57
|
+
let slickTrack = container.querySelector('.slick-track');
|
|
58
|
+
currentSlide = slickTrack!.querySelector('.slick-slide.slick-current');
|
|
59
|
+
expect(currentSlide!.attributes['data-index' as any].value).toEqual('1');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { AdditionalProps } from '../common.types';
|
|
3
|
+
|
|
4
|
+
export type NsCarousalProps<T = any> = {
|
|
5
|
+
entries: T[];
|
|
6
|
+
// eslint-disable-next-line no-unused-vars
|
|
7
|
+
renderEntry(entry: T, index: number): ReactNode;
|
|
8
|
+
allEntryLink: string;
|
|
9
|
+
settings: any;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type NsScrollingCarousalProps<T = any> = {
|
|
13
|
+
slides: T;
|
|
14
|
+
// eslint-disable-next-line no-unused-vars
|
|
15
|
+
renderSlide(slide: T, index: number): ReactNode;
|
|
16
|
+
/* time it takes while scrolling */
|
|
17
|
+
scrollSeconds: number;
|
|
18
|
+
/* time for which slide stays still before scrolling */
|
|
19
|
+
stillSeconds: number;
|
|
20
|
+
settings: any;
|
|
21
|
+
} & AdditionalProps;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NsIcon } from '../icon';
|
|
2
2
|
import { CartIconContainer, ItemCount } from './NsCartIcon.styled';
|
|
3
|
-
import { NsCartIconProps } from './types';
|
|
3
|
+
import { NsCartIconProps } from './types.d';
|
|
4
4
|
|
|
5
5
|
const NsCartIcon = ({ itemCount, size = 'large', color = 'primary' }: NsCartIconProps) => {
|
|
6
6
|
return (
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { default as NsCartIcon } from './NsCartIcon';
|
|
2
|
-
export type { NsCartIconProps } from './types';
|
|
2
|
+
export type { NsCartIconProps } from './types.d';
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import React from 'react';
|
|
8
8
|
|
|
9
|
-
import { render, fireEvent, noop } from '
|
|
9
|
+
import { render, fireEvent, noop } from '@/test-utils/index';
|
|
10
10
|
import NsCheckbox from './NsCheckbox';
|
|
11
11
|
|
|
12
12
|
// Test suite for CustomCheckbox
|
|
@@ -54,4 +54,4 @@ describe('CustomCheckbox', () => {
|
|
|
54
54
|
// Assert that the handleChange function has been called
|
|
55
55
|
expect(handleChange).toHaveBeenCalled();
|
|
56
56
|
});
|
|
57
|
-
});
|
|
57
|
+
});
|
|
@@ -9,7 +9,7 @@ import FormControlLabel from '@mui/material/FormControlLabel';
|
|
|
9
9
|
import { default as MUICheckbox } from '@mui/material/Checkbox';
|
|
10
10
|
|
|
11
11
|
import { BpCheckedIcon, BpIcon, StyledLabel, StyledFlagLabel } from './NsCheckbox.styled';
|
|
12
|
-
import { NsCheckboxProps } from './types';
|
|
12
|
+
import { NsCheckboxProps } from './types.d';
|
|
13
13
|
|
|
14
14
|
import { NsTypography } from '../';
|
|
15
15
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { default as NsCheckbox } from './NsCheckbox';
|
|
2
|
-
export type { NsCheckboxProps } from './types';
|
|
2
|
+
export type { NsCheckboxProps } from './types.d';
|
|
@@ -1,15 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author [vijayaprathap Kumar] (vpkumar@nuskin.com)
|
|
3
|
-
* types.d.ts
|
|
4
|
-
* @description NsCheckbox Props extending Mui CheckboxProps interface.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
1
|
import { CheckboxProps as MUICheckboxProps } from '@material-ui/core/Checkbox';
|
|
8
2
|
|
|
9
3
|
import { NsFlagProps } from '../flag';
|
|
10
4
|
|
|
11
5
|
// Define the props for the custom checkbox component
|
|
12
|
-
export type NsCheckboxProps = Pick<MUICheckboxProps, 'label' | 'onChange'
|
|
6
|
+
export type NsCheckboxProps = Partial<Pick<MUICheckboxProps, 'label' | 'onChange'>> & {
|
|
13
7
|
name: string;
|
|
14
8
|
className?: string;
|
|
15
9
|
checked: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
2
|
import { Box } from '@mui/material';
|
|
3
3
|
import { styled } from '@nuskin/foundation-theme';
|
|
4
|
-
import { NsColumnControlProps, sizeObjectType } from './types';
|
|
4
|
+
import { NsColumnControlProps, sizeObjectType } from './types.d';
|
|
5
5
|
import { getColumnSizes } from './utils';
|
|
6
6
|
|
|
7
7
|
const options = {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { PropsWithChildren, useMemo } from 'react';
|
|
2
|
+
import { getColumnSizes } from './utils';
|
|
3
|
+
import { StyledFlex } from './styled/StyledFlex';
|
|
4
|
+
import { AdditionalProps } from '../common.types';
|
|
5
|
+
|
|
6
|
+
type NsFlexColumnsProps = PropsWithChildren<{
|
|
7
|
+
columnClass: string;
|
|
8
|
+
gap: number;
|
|
9
|
+
}> &
|
|
10
|
+
AdditionalProps;
|
|
11
|
+
|
|
12
|
+
const NsFlexColumns = ({ columnClass, children, gap, additionalProps }: NsFlexColumnsProps) => {
|
|
13
|
+
const sizes = useMemo(() => {
|
|
14
|
+
return getColumnSizes(columnClass ?? 'ns-col-lg-1-1');
|
|
15
|
+
}, [columnClass]);
|
|
16
|
+
return (
|
|
17
|
+
<StyledFlex
|
|
18
|
+
gap={gap}
|
|
19
|
+
sizes={sizes}
|
|
20
|
+
className="styled-flex"
|
|
21
|
+
data-testid={additionalProps?.testid ?? 'ns-flex-columns'}
|
|
22
|
+
>
|
|
23
|
+
{children}
|
|
24
|
+
</StyledFlex>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
export default NsFlexColumns;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { PropsWithChildren, useMemo } from 'react';
|
|
2
|
+
import { getColumnSizes } from './utils';
|
|
3
|
+
import { StyledGrid } from './styled/StyledGrid';
|
|
4
|
+
import { AdditionalProps } from '../common.types';
|
|
5
|
+
|
|
6
|
+
type NsGridColumnsProps = PropsWithChildren<{
|
|
7
|
+
columnClass: string;
|
|
8
|
+
gap: number;
|
|
9
|
+
}> &
|
|
10
|
+
AdditionalProps;
|
|
11
|
+
|
|
12
|
+
const NsGridColumns = ({ columnClass, children, gap, additionalProps }: NsGridColumnsProps) => {
|
|
13
|
+
const sizes = useMemo(() => {
|
|
14
|
+
return getColumnSizes(columnClass ?? 'ns-col-lg-1-1');
|
|
15
|
+
}, [columnClass]);
|
|
16
|
+
return (
|
|
17
|
+
<StyledGrid
|
|
18
|
+
gap={gap}
|
|
19
|
+
sizes={sizes}
|
|
20
|
+
className="styled-grid"
|
|
21
|
+
data-testid={additionalProps?.testid ?? 'ns-grid-columns'}
|
|
22
|
+
>
|
|
23
|
+
{children}
|
|
24
|
+
</StyledGrid>
|
|
25
|
+
);
|
|
26
|
+
};
|
|
27
|
+
export default NsGridColumns;
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
export { default as NsColumnControl } from './NsColumnControl';
|
|
2
|
-
export
|
|
2
|
+
export { default as NsFlexColumns } from './NsFlexColumns';
|
|
3
|
+
export { default as NsGridColumns } from './NsGridColumns';
|
|
4
|
+
export type { NsColumnControlProps } from './types.d';
|
package/src/common/column-control/{NsColumnControl.spec.tsx → specs/NsColumnControl.spec.tsx}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { NsColumnControl } from '@/common/index';
|
|
2
|
+
import { DivArray } from '../stories/NDivs.story';
|
|
3
|
+
import { render, screen } from '@/test-utils/index';
|
|
4
4
|
|
|
5
5
|
describe('NsColumnControl component', () => {
|
|
6
6
|
it('renders an column with proper grid value for tablet', () => {
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { render, screen } from '../../../../test-utils';
|
|
2
|
+
import { NsFlexColumns } from '@/common/index';
|
|
3
|
+
import { DivArray } from '../stories/NDivs.story';
|
|
4
|
+
|
|
5
|
+
describe('NsFlexColumns component', () => {
|
|
6
|
+
it('renders an column with proper grid value for tablet', () => {
|
|
7
|
+
render(
|
|
8
|
+
<NsFlexColumns columnClass="ns-col-lg-1-1-1" gap={16}>
|
|
9
|
+
<DivArray elementsCount={4} />
|
|
10
|
+
</NsFlexColumns>
|
|
11
|
+
);
|
|
12
|
+
const element = screen.getByTestId('ns-flex-columns');
|
|
13
|
+
expect(element).toBeInTheDocument();
|
|
14
|
+
});
|
|
15
|
+
it('renders an column with proper grid value', () => {
|
|
16
|
+
console.warn = jest.fn();
|
|
17
|
+
render(
|
|
18
|
+
<NsFlexColumns columnClass="" gap={16}>
|
|
19
|
+
<DivArray elementsCount={4} />
|
|
20
|
+
</NsFlexColumns>
|
|
21
|
+
);
|
|
22
|
+
expect(console.warn).toHaveBeenCalledWith(expect.stringContaining('Received invalid className'));
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { render, screen } from '../../../../test-utils';
|
|
2
|
+
import { NsGridColumns } from '@/common/index';
|
|
3
|
+
import { DivArray } from '../stories/NDivs.story';
|
|
4
|
+
|
|
5
|
+
describe('NsGridColumns component', () => {
|
|
6
|
+
it('renders an column with proper grid value for tablet', () => {
|
|
7
|
+
render(
|
|
8
|
+
<NsGridColumns columnClass="ns-col-lg-1-1-1" gap={16}>
|
|
9
|
+
<DivArray elementsCount={4} />
|
|
10
|
+
</NsGridColumns>
|
|
11
|
+
);
|
|
12
|
+
const element = screen.getByTestId('ns-grid-columns');
|
|
13
|
+
expect(element).toBeInTheDocument();
|
|
14
|
+
});
|
|
15
|
+
it('renders an column with proper grid value', () => {
|
|
16
|
+
console.warn = jest.fn();
|
|
17
|
+
render(
|
|
18
|
+
<NsGridColumns columnClass="" gap={16}>
|
|
19
|
+
<DivArray elementsCount={4} />
|
|
20
|
+
</NsGridColumns>
|
|
21
|
+
);
|
|
22
|
+
expect(console.warn).toHaveBeenCalledWith(expect.stringContaining('Received invalid className'));
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { StoryObj, Meta } from '@storybook/react';
|
|
2
|
-
import { withCenterDecorator } from '
|
|
2
|
+
import { withCenterDecorator } from '../../../stories/decorators/withCenterDecorator';
|
|
3
3
|
|
|
4
4
|
type DivArrayProps = {
|
|
5
5
|
elementsCount: number;
|
|
@@ -1,25 +1,15 @@
|
|
|
1
1
|
import type { StoryObj, Meta } from '@storybook/react';
|
|
2
|
-
import { withCenterDecorator } from '
|
|
3
|
-
import { NsColumnControl } from '
|
|
2
|
+
import { withCenterDecorator } from '../../../stories/decorators/withCenterDecorator';
|
|
3
|
+
import { NsColumnControl } from '@/common/index';
|
|
4
4
|
import { DivArray } from './NDivs.story';
|
|
5
|
+
import { childrenMapping, selectDivOptions } from './common';
|
|
5
6
|
|
|
6
7
|
type ComponentType = typeof NsColumnControl;
|
|
7
8
|
type Story = StoryObj<ComponentType>;
|
|
8
9
|
type MetaStory = Meta<ComponentType>;
|
|
9
10
|
|
|
10
|
-
/* an array from 1 to n */
|
|
11
|
-
const selectDivOptions = Array(16)
|
|
12
|
-
.fill(0)
|
|
13
|
-
.map((e, i) => i + 1);
|
|
14
|
-
const childrenMapping = selectDivOptions.reduce((a, c) => {
|
|
15
|
-
return {
|
|
16
|
-
...a,
|
|
17
|
-
[c]: <DivArray elementsCount={c} />,
|
|
18
|
-
};
|
|
19
|
-
}, {});
|
|
20
|
-
|
|
21
11
|
export default {
|
|
22
|
-
title: 'Components/NsColumnControl',
|
|
12
|
+
title: 'Components/Column/NsColumnControl',
|
|
23
13
|
component: NsColumnControl,
|
|
24
14
|
decorators: [withCenterDecorator],
|
|
25
15
|
argTypes: {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { StoryObj, Meta } from '@storybook/react';
|
|
2
|
+
import { withCenterDecorator } from '../../../stories/decorators/withCenterDecorator';
|
|
3
|
+
import { NsFlexColumns } from '..';
|
|
4
|
+
import { DivArray } from './NDivs.story';
|
|
5
|
+
import {childrenMapping, selectDivOptions } from './common';
|
|
6
|
+
|
|
7
|
+
type ComponentType = typeof NsFlexColumns;
|
|
8
|
+
type Story = StoryObj<ComponentType>;
|
|
9
|
+
type MetaStory = Meta<ComponentType>;
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
title: 'Components/Column/NsFlexColumns',
|
|
13
|
+
component: NsFlexColumns,
|
|
14
|
+
decorators: [withCenterDecorator],
|
|
15
|
+
argTypes: {
|
|
16
|
+
columnClass: {
|
|
17
|
+
control: 'text',
|
|
18
|
+
defaultValue: 'ns-col-lg-1-1-1 ns-col-md-1-1 ns-col-sm-1',
|
|
19
|
+
},
|
|
20
|
+
gap: {
|
|
21
|
+
control: 'number',
|
|
22
|
+
defaultValue: 16,
|
|
23
|
+
},
|
|
24
|
+
children: {
|
|
25
|
+
control: {
|
|
26
|
+
type: 'select',
|
|
27
|
+
options: selectDivOptions,
|
|
28
|
+
},
|
|
29
|
+
defaultValue: <DivArray elementsCount={8} />,
|
|
30
|
+
mapping: childrenMapping,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
args: {
|
|
34
|
+
columnClass: 'ns-col-lg-1-1-1',
|
|
35
|
+
children: <DivArray elementsCount={12} />,
|
|
36
|
+
},
|
|
37
|
+
} as MetaStory;
|
|
38
|
+
|
|
39
|
+
export const SingleColumnControl: Story = {};
|
|
40
|
+
export const TwoColumn11: Story = {
|
|
41
|
+
args: { columnClass: 'ns-col-lg-1-1' },
|
|
42
|
+
};
|
|
43
|
+
export const TwoColumn21: Story = {
|
|
44
|
+
args: { columnClass: 'ns-col-lg-2-1' },
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const ThreeColumn211: Story = {
|
|
48
|
+
args: { columnClass: 'ns-col-lg-2-1-1' },
|
|
49
|
+
};
|
|
50
|
+
export const ThreeColumn121: Story = {
|
|
51
|
+
args: { columnClass: 'ns-col-lg-1-2-1' },
|
|
52
|
+
};
|
|
53
|
+
export const ThreeColumn111Responsive: Story = {
|
|
54
|
+
args: { columnClass: 'ns-col-lg-1-1-1' },
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const FourColumn1111Responsive: Story = {
|
|
58
|
+
args: { columnClass: 'ns-col-lg-1-1-1-1' },
|
|
59
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { StoryObj, Meta } from '@storybook/react';
|
|
2
|
+
import { withCenterDecorator } from '../../../stories/decorators/withCenterDecorator';
|
|
3
|
+
import { NsGridColumns } from '..';
|
|
4
|
+
import { DivArray } from './NDivs.story';
|
|
5
|
+
import { childrenMapping, selectDivOptions } from './common';
|
|
6
|
+
|
|
7
|
+
type ComponentType = typeof NsGridColumns;
|
|
8
|
+
type Story = StoryObj<ComponentType>;
|
|
9
|
+
type MetaStory = Meta<ComponentType>;
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
title: 'Components/Column/NsGridColumns',
|
|
13
|
+
component: NsGridColumns,
|
|
14
|
+
decorators: [withCenterDecorator],
|
|
15
|
+
argTypes: {
|
|
16
|
+
columnClass: {
|
|
17
|
+
control: 'text',
|
|
18
|
+
defaultValue: 'ns-col-lg-1-1-1 ns-col-md-1-1 ns-col-sm-1',
|
|
19
|
+
},
|
|
20
|
+
gap: {
|
|
21
|
+
control: 'number',
|
|
22
|
+
defaultValue: 16,
|
|
23
|
+
},
|
|
24
|
+
children: {
|
|
25
|
+
control: {
|
|
26
|
+
type: 'select',
|
|
27
|
+
options: selectDivOptions,
|
|
28
|
+
},
|
|
29
|
+
defaultValue: <DivArray elementsCount={8} />,
|
|
30
|
+
mapping: childrenMapping,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
args: {
|
|
34
|
+
columnClass: 'ns-col-lg-1-1-1',
|
|
35
|
+
children: <DivArray elementsCount={12} />,
|
|
36
|
+
},
|
|
37
|
+
} as MetaStory;
|
|
38
|
+
|
|
39
|
+
export const SingleColumnControl: Story = {};
|
|
40
|
+
export const TwoColumn11: Story = {
|
|
41
|
+
args: { columnClass: 'ns-col-lg-1-1' },
|
|
42
|
+
};
|
|
43
|
+
export const TwoColumn21: Story = {
|
|
44
|
+
args: { columnClass: 'ns-col-lg-2-1' },
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const ThreeColumn211: Story = {
|
|
48
|
+
args: { columnClass: 'ns-col-lg-2-1-1' },
|
|
49
|
+
};
|
|
50
|
+
export const ThreeColumn121: Story = {
|
|
51
|
+
args: { columnClass: 'ns-col-lg-1-2-1' },
|
|
52
|
+
};
|
|
53
|
+
export const ThreeColumn111Responsive: Story = {
|
|
54
|
+
args: { columnClass: 'ns-col-lg-1-1-1' },
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const FourColumn1111Responsive: Story = {
|
|
58
|
+
args: { columnClass: 'ns-col-lg-1-1-1-1' },
|
|
59
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DivArray } from './NDivs.story';
|
|
2
|
+
|
|
3
|
+
/* an array from 1 to n */
|
|
4
|
+
export const selectDivOptions = Array(16)
|
|
5
|
+
.fill(0)
|
|
6
|
+
.map((_, index) => index + 1);
|
|
7
|
+
|
|
8
|
+
/* this component is used only as a utility to show column control in storybook */
|
|
9
|
+
export const childrenMapping = selectDivOptions.reduce((childrenMappingObject, elementCount) => {
|
|
10
|
+
return {
|
|
11
|
+
...childrenMappingObject,
|
|
12
|
+
[elementCount]: <DivArray elementsCount={elementCount} />,
|
|
13
|
+
};
|
|
14
|
+
}, {});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Box } from '@mui/material';
|
|
2
|
+
import { styled } from '@nuskin/foundation-theme';
|
|
3
|
+
import { sizeObjectType } from '../types';
|
|
4
|
+
import { commonStyles, getPercentArray } from './common';
|
|
5
|
+
|
|
6
|
+
const options = {
|
|
7
|
+
shouldForwardProp: (propKey: string) => propKey !== 'sizes | gap',
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
type StyledFlexProps = {
|
|
11
|
+
sizes: sizeObjectType;
|
|
12
|
+
gap?: number;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/* main wrapper for column control using css flex */
|
|
16
|
+
export const StyledFlex = styled(
|
|
17
|
+
Box as any,
|
|
18
|
+
options
|
|
19
|
+
)<StyledFlexProps>(({ sizes, gap }: StyledFlexProps) => {
|
|
20
|
+
const gridGap = gap ? `${gap}px` : '2rem';
|
|
21
|
+
const fraction = getPercentArray(sizes.fractions);
|
|
22
|
+
const flexResponsive = { flexGrow: 1, flexShrink: 1 };
|
|
23
|
+
const style: any = {
|
|
24
|
+
gap: gridGap,
|
|
25
|
+
...commonStyles,
|
|
26
|
+
display: 'flex',
|
|
27
|
+
paddingInline: '20px',
|
|
28
|
+
flexWrap: 'wrap',
|
|
29
|
+
justifyContent: 'center',
|
|
30
|
+
' > *': {
|
|
31
|
+
display: 'flex',
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
fraction.forEach((f, i) => {
|
|
35
|
+
style[`> :nth-of-type(${fraction.length}n+${i + 1})`] = {
|
|
36
|
+
flexBasis: `calc(${fraction[i]} - ${gridGap})`,
|
|
37
|
+
...flexResponsive,
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
return style;
|
|
41
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Box } from '@mui/material';
|
|
2
|
+
import { styled } from '@nuskin/foundation-theme';
|
|
3
|
+
import { sizeObjectType } from '../types';
|
|
4
|
+
import { commonStyles, getPercentArray } from './common';
|
|
5
|
+
|
|
6
|
+
type StyledGridProps = {
|
|
7
|
+
sizes: sizeObjectType;
|
|
8
|
+
gap?: number;
|
|
9
|
+
};
|
|
10
|
+
const options = {
|
|
11
|
+
shouldForwardProp: (propKey: string) => propKey !== 'sizes | gap',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/* main wrapper for column control using css grid */
|
|
15
|
+
export const StyledGrid = styled(
|
|
16
|
+
Box as any,
|
|
17
|
+
options
|
|
18
|
+
)<StyledGridProps>(({ sizes, gap }: StyledGridProps) => {
|
|
19
|
+
const gridGap = gap ?? '2rem';
|
|
20
|
+
return {
|
|
21
|
+
gap: gridGap,
|
|
22
|
+
...commonStyles,
|
|
23
|
+
display: 'grid',
|
|
24
|
+
/* here we are creating gridTemplateColumns as calc(40% - 20px) calc(40% - 20px), */
|
|
25
|
+
gridTemplateColumns: getPercentArray(sizes.fractions)
|
|
26
|
+
?.map((fractionPercent) => `calc(${fractionPercent} - 20px)`)
|
|
27
|
+
.join(''),
|
|
28
|
+
justifyContent: 'center',
|
|
29
|
+
'.span-2': {
|
|
30
|
+
gridColumn: 'span 2',
|
|
31
|
+
},
|
|
32
|
+
} as any;
|
|
33
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const mobileBreakPoint = '600px';
|
|
2
|
+
// TODO: we need to add a prop in the to allow full width of page instead of 1200px
|
|
3
|
+
export const commonStyles = {
|
|
4
|
+
maxWidth: '1200px',
|
|
5
|
+
margin: '32px auto',
|
|
6
|
+
[`@media (max-width: ${mobileBreakPoint})`]: {
|
|
7
|
+
display: 'flex',
|
|
8
|
+
flexDirection: 'column',
|
|
9
|
+
flexWrap: 'wrap',
|
|
10
|
+
margin: '2rem 1rem',
|
|
11
|
+
'> * ': {
|
|
12
|
+
flex: '1 1 0 !important',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
/*
|
|
17
|
+
we have kept extra margin by taking 80% instead of 100%, because margins and padding,
|
|
18
|
+
and gaps also take up space, so we should be left with appropriate space
|
|
19
|
+
example:
|
|
20
|
+
['1','1'] => ['40%','40%']
|
|
21
|
+
['1','2'] => ['27%','53%']
|
|
22
|
+
*/
|
|
23
|
+
export function getPercentArray(fractionArray?: string[] | number[]) {
|
|
24
|
+
let numbers = fractionArray?.map((numberString) => +numberString)?.filter((num) => 0 < num && num < 10) ?? [];
|
|
25
|
+
const sum = numbers.reduce((currentSum, currentNumber) => currentSum + currentNumber, 0);
|
|
26
|
+
return numbers.map((currentNumber) => ((currentNumber / sum) * 80).toFixed(2) + '%');
|
|
27
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ValueOf } from 'next/dist/shared/lib/constants';
|
|
2
|
-
import { NsColumnControlProps, sizeObjectType } from './types';
|
|
2
|
+
import { NsColumnControlProps, sizeObjectType } from './types.d';
|
|
3
3
|
|
|
4
4
|
export const columnClasses: NsColumnControlProps['columnClass'][] = [
|
|
5
5
|
'ns-col-lg-2-1',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render, fireEvent, screen, waitFor } from '
|
|
2
|
+
import { render, fireEvent, screen, waitFor } from '@/test-utils/index';
|
|
3
3
|
import NsDropdown from './NsDropdown';
|
|
4
4
|
import NsDropdownOption from './NsDropdownOption';
|
|
5
5
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import { DropdownContainer, DropdownButton, DropdownList, DropdownHead } from './NsDropdown.styled';
|
|
3
3
|
import { NsIcon } from '../icon';
|
|
4
|
-
import { DropdownProps } from './types';
|
|
4
|
+
import { DropdownProps } from './types.d';
|
|
5
5
|
|
|
6
6
|
const NsDropdown: React.FC<DropdownProps> = ({
|
|
7
7
|
selectedValue,
|