@nuskin/foundation-ui-components 1.0.0-develop.1 → 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.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,123 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import NsTable from './NsTable';
|
|
3
|
+
import { withCenterDecorator } from '../../stories/decorators/withCenterDecorator';
|
|
4
|
+
|
|
5
|
+
type ComponentType = typeof NsTable;
|
|
6
|
+
type Story = StoryObj<ComponentType>;
|
|
7
|
+
type MetaStory = Meta<ComponentType>;
|
|
8
|
+
const headers = [
|
|
9
|
+
{
|
|
10
|
+
label: 'Dessert (100g serving)',
|
|
11
|
+
id: 'name',
|
|
12
|
+
numeric: false
|
|
13
|
+
},
|
|
14
|
+
{ label: 'Calories', id: 'calories' , numeric: true},
|
|
15
|
+
{ label: 'Fat (g)', id: 'fat', numeric: true },
|
|
16
|
+
{ label: 'Carbs (g)', id: 'carbs', numeric: true },
|
|
17
|
+
{ label: 'Protein (g)', id: 'protein', numeric: true },
|
|
18
|
+
{ label: 'Iron (%)', id: 'iron', numeric: false },
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
const items = [
|
|
22
|
+
{
|
|
23
|
+
name: 'Frozen Yogurt',
|
|
24
|
+
calories: 159,
|
|
25
|
+
fat: 6.0,
|
|
26
|
+
carbs: 24,
|
|
27
|
+
protein: 4.0,
|
|
28
|
+
iron: '1%',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: 'Ice cream sandwich',
|
|
32
|
+
calories: 237,
|
|
33
|
+
fat: 9.0,
|
|
34
|
+
carbs: 37,
|
|
35
|
+
protein: 4.3,
|
|
36
|
+
iron: '1%',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'Eclair',
|
|
40
|
+
calories: 262,
|
|
41
|
+
fat: 16.0,
|
|
42
|
+
carbs: 23,
|
|
43
|
+
protein: 6.0,
|
|
44
|
+
iron: '7%',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'Cupcake',
|
|
48
|
+
calories: 305,
|
|
49
|
+
fat: 3.7,
|
|
50
|
+
carbs: 67,
|
|
51
|
+
protein: 4.3,
|
|
52
|
+
iron: '8%',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'Gingerbread',
|
|
56
|
+
calories: 356,
|
|
57
|
+
fat: 16.0,
|
|
58
|
+
carbs: 49,
|
|
59
|
+
protein: 3.9,
|
|
60
|
+
iron: '16%',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'Jelly bean',
|
|
64
|
+
calories: 375,
|
|
65
|
+
fat: 0.0,
|
|
66
|
+
carbs: 94,
|
|
67
|
+
protein: 0.0,
|
|
68
|
+
iron: '0%',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'Lollipop',
|
|
72
|
+
calories: 392,
|
|
73
|
+
fat: 0.2,
|
|
74
|
+
carbs: 98,
|
|
75
|
+
protein: 0,
|
|
76
|
+
iron: '2%',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'Honeycomb',
|
|
80
|
+
calories: 408,
|
|
81
|
+
fat: 3.2,
|
|
82
|
+
carbs: 87,
|
|
83
|
+
protein: 6.5,
|
|
84
|
+
iron: '45%',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: 'Donut',
|
|
88
|
+
calories: 452,
|
|
89
|
+
fat: 25.0,
|
|
90
|
+
carbs: 51,
|
|
91
|
+
protein: 4.9,
|
|
92
|
+
iron: '22%',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: 'KitKat',
|
|
96
|
+
calories: 518,
|
|
97
|
+
fat: 26.0,
|
|
98
|
+
carbs: 65,
|
|
99
|
+
protein: 7,
|
|
100
|
+
iron: '6%',
|
|
101
|
+
},
|
|
102
|
+
];
|
|
103
|
+
|
|
104
|
+
export default {
|
|
105
|
+
title: 'Components/NsTable',
|
|
106
|
+
component: NsTable,
|
|
107
|
+
decorators: [withCenterDecorator],
|
|
108
|
+
argTypes: {
|
|
109
|
+
rows: {
|
|
110
|
+
control: 'select',
|
|
111
|
+
options: [5, 10, 25]
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
args: {
|
|
115
|
+
headers: headers,
|
|
116
|
+
items: items,
|
|
117
|
+
rows: 5,
|
|
118
|
+
itemKey: 'name',
|
|
119
|
+
rowsPerPageOptions: [5, 10, 25]
|
|
120
|
+
}
|
|
121
|
+
} as MetaStory;
|
|
122
|
+
|
|
123
|
+
export const NasTable: Story = {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { styled } from '@nuskin/foundation-theme';
|
|
2
|
+
import { getAppColor } from '@nuskin/foundation-theme/src/utils/color-utils';
|
|
3
|
+
import {
|
|
4
|
+
Table,
|
|
5
|
+
TableContainer,
|
|
6
|
+
TableSortLabel,
|
|
7
|
+
TableRow
|
|
8
|
+
} from '@mui/material';
|
|
9
|
+
|
|
10
|
+
export const StyledTableContainer= styled(TableContainer)`
|
|
11
|
+
background-color: ${({ theme }) => getAppColor(theme, 'primary', 'white')};
|
|
12
|
+
`;
|
|
13
|
+
|
|
14
|
+
export const StyledTable = styled(Table)`
|
|
15
|
+
size: medium;
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
export const StyledTableSortLabel = styled(TableSortLabel)`
|
|
19
|
+
font-size: 12px;
|
|
20
|
+
text-transform: uppercase;
|
|
21
|
+
font-weight: 700;
|
|
22
|
+
line-height: 16px;
|
|
23
|
+
letter-spacing: 0.05em;
|
|
24
|
+
color: ${({ theme }) => getAppColor(theme, 'primary', 'black')};
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
export const StyledPageComponent = styled.div`
|
|
28
|
+
background-color: ${({ theme }) => getAppColor(theme, 'primary', 'white')};
|
|
29
|
+
`;
|
|
30
|
+
|
|
31
|
+
export const StyledEmptyRow = styled(TableRow)<{emptyRows: number}>`
|
|
32
|
+
height: ${({ emptyRows }) => 53 * emptyRows}px;
|
|
33
|
+
`;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import { TableBody, TableRow, TableCell } from '@mui/material';
|
|
3
|
+
import { StyledTable, StyledTableContainer, StyledEmptyRow } from './NsTable.styled';
|
|
4
|
+
import type { NsTableProps, Item, OrderType } from './types.d';
|
|
5
|
+
import { stableSort, getComparator } from './helper';
|
|
6
|
+
import NsTableHeader from './NsTableHeader';
|
|
7
|
+
import NsCheckBox from '../checkbox/NsCheckbox';
|
|
8
|
+
import NsTablePagination from './NsTablePagination';
|
|
9
|
+
|
|
10
|
+
export default function NsTable({
|
|
11
|
+
headers = [],
|
|
12
|
+
items = [],
|
|
13
|
+
rows,
|
|
14
|
+
isShowSelector = true,
|
|
15
|
+
isPagination = false,
|
|
16
|
+
rowsPerPageOptions,
|
|
17
|
+
itemKey,
|
|
18
|
+
}: NsTableProps) {
|
|
19
|
+
const [order, setOrder] = useState<OrderType>('asc');
|
|
20
|
+
const [orderBy, setOrderBy] = useState<keyof Item>(itemKey);
|
|
21
|
+
const [selected, setSelected] = useState<readonly (string | number)[]>([]);
|
|
22
|
+
const [page, setPage] = useState(0);
|
|
23
|
+
const [rowsPerPage, setRowsPerPage] = useState(rows);
|
|
24
|
+
const [itemKeyList, setItemKeyList] = useState<string[]>([]);
|
|
25
|
+
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (items.length) setItemKeyList(Object.keys(items[0]));
|
|
28
|
+
}, [items]);
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
setRowsPerPage(rows);
|
|
32
|
+
setPage(0);
|
|
33
|
+
}, [rows]);
|
|
34
|
+
|
|
35
|
+
const handleRequestSort = (event: React.MouseEvent<unknown>, property: keyof Item) => {
|
|
36
|
+
const isAsc = orderBy === property && order === 'asc';
|
|
37
|
+
setOrder(isAsc ? 'desc' : 'asc');
|
|
38
|
+
setOrderBy(property);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const handleSelectAllClick = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
42
|
+
if (event.target.checked) {
|
|
43
|
+
const newSelected = items.map((n) => n[itemKey as string]);
|
|
44
|
+
setSelected(newSelected);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
setSelected([]);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const handleClick = (event: React.MouseEvent<unknown>, name: string | number) => {
|
|
51
|
+
const selectedIndex = selected.indexOf(name);
|
|
52
|
+
let newSelected: readonly (string | number)[] = [];
|
|
53
|
+
|
|
54
|
+
if (selectedIndex === -1) {
|
|
55
|
+
newSelected = newSelected.concat(selected, name);
|
|
56
|
+
} else if (selectedIndex === 0) {
|
|
57
|
+
newSelected = newSelected.concat(selected.slice(1));
|
|
58
|
+
} else if (selectedIndex === selected.length - 1) {
|
|
59
|
+
newSelected = newSelected.concat(selected.slice(0, -1));
|
|
60
|
+
} else if (selectedIndex > 0) {
|
|
61
|
+
newSelected = newSelected.concat(selected.slice(0, selectedIndex), selected.slice(selectedIndex + 1));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
setSelected(newSelected);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const handleChangePage = (event: unknown, newPage: number) => {
|
|
68
|
+
setPage(newPage);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const handleChangeRowsPerPage = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
72
|
+
setRowsPerPage(parseInt(event.target.value, 10));
|
|
73
|
+
setPage(0);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const isSelected = (name: string | number) => selected.indexOf(name) !== -1;
|
|
77
|
+
|
|
78
|
+
const emptyRows = page > 0 ? Math.max(0, (1 + page) * rowsPerPage - items.length) : 0;
|
|
79
|
+
|
|
80
|
+
const visibleRows = React.useMemo(
|
|
81
|
+
() =>
|
|
82
|
+
stableSort(items, getComparator(order, orderBy)).slice(
|
|
83
|
+
page * rowsPerPage,
|
|
84
|
+
page * rowsPerPage + rowsPerPage
|
|
85
|
+
),
|
|
86
|
+
[order, orderBy, page, rowsPerPage, items]
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<div>
|
|
91
|
+
<StyledTableContainer>
|
|
92
|
+
<StyledTable>
|
|
93
|
+
<NsTableHeader
|
|
94
|
+
headCells={headers}
|
|
95
|
+
numSelected={selected.length}
|
|
96
|
+
order={order}
|
|
97
|
+
orderBy={orderBy as string}
|
|
98
|
+
onSelectAllClick={handleSelectAllClick}
|
|
99
|
+
onRequestSort={handleRequestSort}
|
|
100
|
+
rowCount={items.length}
|
|
101
|
+
isShowSelector={isShowSelector}
|
|
102
|
+
/>
|
|
103
|
+
<TableBody>
|
|
104
|
+
{visibleRows.map((row, index) => {
|
|
105
|
+
const isItemSelected = isSelected(row[itemKey]);
|
|
106
|
+
const labelId = `table-checkbox-${index}`;
|
|
107
|
+
const tableRowTestId = `table-row-${index}`;
|
|
108
|
+
return (
|
|
109
|
+
<TableRow
|
|
110
|
+
hover
|
|
111
|
+
onClick={(event) => handleClick(event, row[itemKey])}
|
|
112
|
+
role="checkbox"
|
|
113
|
+
aria-checked={isItemSelected}
|
|
114
|
+
tabIndex={-1}
|
|
115
|
+
key={row[itemKey]}
|
|
116
|
+
selected={isItemSelected}
|
|
117
|
+
sx={{ cursor: 'pointer' }}
|
|
118
|
+
data-testid={tableRowTestId}
|
|
119
|
+
>
|
|
120
|
+
{isShowSelector ? (
|
|
121
|
+
<TableCell padding="checkbox">
|
|
122
|
+
<NsCheckBox
|
|
123
|
+
checked={isItemSelected}
|
|
124
|
+
testid={labelId}
|
|
125
|
+
name={labelId}
|
|
126
|
+
label=""
|
|
127
|
+
className="ml-0 !important"
|
|
128
|
+
/>
|
|
129
|
+
</TableCell>
|
|
130
|
+
) : null}
|
|
131
|
+
{itemKeyList.map((id, index) => {
|
|
132
|
+
return (
|
|
133
|
+
<TableCell align="left" key={index}>
|
|
134
|
+
{row[id]}
|
|
135
|
+
</TableCell>
|
|
136
|
+
);
|
|
137
|
+
})}
|
|
138
|
+
</TableRow>
|
|
139
|
+
);
|
|
140
|
+
})}
|
|
141
|
+
{emptyRows > 0 ? (
|
|
142
|
+
<StyledEmptyRow emptyRows={emptyRows}>
|
|
143
|
+
<TableCell colSpan={itemKeyList.length} />
|
|
144
|
+
</StyledEmptyRow>
|
|
145
|
+
) : null}
|
|
146
|
+
</TableBody>
|
|
147
|
+
</StyledTable>
|
|
148
|
+
</StyledTableContainer>
|
|
149
|
+
{isPagination ? (
|
|
150
|
+
<NsTablePagination
|
|
151
|
+
rowsPerPageOptions={rowsPerPageOptions}
|
|
152
|
+
count={items.length}
|
|
153
|
+
rowsPerPage={rowsPerPage}
|
|
154
|
+
page={page}
|
|
155
|
+
onPageChange={handleChangePage}
|
|
156
|
+
onRowsPerPageChange={handleChangeRowsPerPage}
|
|
157
|
+
/>
|
|
158
|
+
) : null}
|
|
159
|
+
</div>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { NsTableHeaderProps, Item } from './types.d';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { TableHead, TableRow, Box, TableCell } from '@mui/material';
|
|
4
|
+
import { StyledTableSortLabel } from './NsTable.styled';
|
|
5
|
+
import { visuallyHidden } from '@mui/utils';
|
|
6
|
+
import NsCheckBox from '../checkbox/NsCheckbox';
|
|
7
|
+
|
|
8
|
+
export default function NsTableHeader(props: NsTableHeaderProps) {
|
|
9
|
+
const { order, orderBy, numSelected, rowCount, headCells, isShowSelector, onRequestSort, onSelectAllClick } = props;
|
|
10
|
+
const createSortHandler = (property: keyof Item) => (event: React.MouseEvent<unknown>) => {
|
|
11
|
+
onRequestSort(event, property);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<TableHead>
|
|
16
|
+
<TableRow>
|
|
17
|
+
{isShowSelector ? (
|
|
18
|
+
<TableCell padding="checkbox">
|
|
19
|
+
<NsCheckBox
|
|
20
|
+
checked={rowCount > 0 && numSelected > 0}
|
|
21
|
+
onChange={onSelectAllClick}
|
|
22
|
+
testid="header-checkbox"
|
|
23
|
+
name="header-checkbox"
|
|
24
|
+
label=""
|
|
25
|
+
className="ml-0 !important"
|
|
26
|
+
/>
|
|
27
|
+
</TableCell>
|
|
28
|
+
) : null}
|
|
29
|
+
{headCells.map((headCell) => (
|
|
30
|
+
<TableCell key={headCell.id} sortDirection={orderBy == headCell.id ? order : false}>
|
|
31
|
+
<StyledTableSortLabel
|
|
32
|
+
active={orderBy == headCell.id}
|
|
33
|
+
direction={orderBy == headCell.id ? order : 'asc'}
|
|
34
|
+
onClick={createSortHandler(headCell.id)}
|
|
35
|
+
>
|
|
36
|
+
{headCell.label}
|
|
37
|
+
{orderBy === headCell.id ? (
|
|
38
|
+
<Box component="span" sx={visuallyHidden}>
|
|
39
|
+
{order === 'desc' ? 'sorted descending' : 'sorted ascending'}
|
|
40
|
+
</Box>
|
|
41
|
+
) : null}
|
|
42
|
+
</StyledTableSortLabel>
|
|
43
|
+
</TableCell>
|
|
44
|
+
))}
|
|
45
|
+
</TableRow>
|
|
46
|
+
</TableHead>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { NsTablePaginationProps } from './types.d';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { StyledPageComponent } from './NsTable.styled';
|
|
4
|
+
import { TablePagination } from '@mui/material';
|
|
5
|
+
|
|
6
|
+
export default function NsTablePagination(props: NsTablePaginationProps) {
|
|
7
|
+
const { rowsPerPageOptions, count, rowsPerPage, page, onPageChange, onRowsPerPageChange } = props;
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<TablePagination
|
|
11
|
+
rowsPerPageOptions={rowsPerPageOptions}
|
|
12
|
+
component={StyledPageComponent}
|
|
13
|
+
count={count}
|
|
14
|
+
rowsPerPage={rowsPerPage}
|
|
15
|
+
page={page}
|
|
16
|
+
onPageChange={onPageChange}
|
|
17
|
+
onRowsPerPageChange={onRowsPerPageChange}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
import type { OrderType } from './types.d';
|
|
3
|
+
|
|
4
|
+
export function descendingComparator<T>(a: T, b: T, orderBy: keyof T) {
|
|
5
|
+
if (b[orderBy] < a[orderBy]) {
|
|
6
|
+
return -1;
|
|
7
|
+
}
|
|
8
|
+
if (b[orderBy] > a[orderBy]) {
|
|
9
|
+
return 1;
|
|
10
|
+
}
|
|
11
|
+
return 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function getComparator<Key extends keyof any>(
|
|
15
|
+
order: OrderType,
|
|
16
|
+
orderBy: Key
|
|
17
|
+
): (a: { [key in Key]: number | string }, b: { [key in Key]: number | string }) => number {
|
|
18
|
+
return order === 'desc'
|
|
19
|
+
? (a, b) => descendingComparator(a, b, orderBy)
|
|
20
|
+
: (a, b) => -descendingComparator(a, b, orderBy);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function stableSort<T>(array: readonly T[], comparator: (a: T, b: T) => number) {
|
|
24
|
+
const stabilizedThis = array.map((el, index) => [el, index] as [T, number]);
|
|
25
|
+
stabilizedThis.sort((a, b) => {
|
|
26
|
+
const order = comparator(a[0], b[0]);
|
|
27
|
+
if (order !== 0) {
|
|
28
|
+
return order;
|
|
29
|
+
}
|
|
30
|
+
return a[1] - b[1];
|
|
31
|
+
});
|
|
32
|
+
return stabilizedThis.map((el) => el[0]);
|
|
33
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
import { React } from 'React'
|
|
3
|
+
|
|
4
|
+
export interface Header {
|
|
5
|
+
label: string;
|
|
6
|
+
id: string | number;
|
|
7
|
+
numeric: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface Item {
|
|
11
|
+
[key: string]: string | number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface NsTableProps {
|
|
15
|
+
headers: Header[];
|
|
16
|
+
items: Item[];
|
|
17
|
+
rows: number;
|
|
18
|
+
itemKey: string;
|
|
19
|
+
isShowSelector: boolean;
|
|
20
|
+
rowsPerPageOptions: number[];
|
|
21
|
+
isPagination?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type OrderType = 'asc' | 'desc';
|
|
25
|
+
|
|
26
|
+
export interface NsTableHeaderProps {
|
|
27
|
+
numSelected: number;
|
|
28
|
+
onRequestSort: (event: React.MouseEvent<unknown>, property: keyof Item) => void;
|
|
29
|
+
onSelectAllClick: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
30
|
+
order: OrderType;
|
|
31
|
+
orderBy: string;
|
|
32
|
+
rowCount: number;
|
|
33
|
+
headCells: readonly Header[];
|
|
34
|
+
isShowSelector: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface NsTablePaginationProps {
|
|
38
|
+
rowsPerPageOptions: number[],
|
|
39
|
+
count: number;
|
|
40
|
+
rowsPerPage: number;
|
|
41
|
+
page: number,
|
|
42
|
+
onPageChange: (unknown, number) => void;
|
|
43
|
+
onRowsPerPageChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
44
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import { NsTextStrip } from '@/common/';
|
|
4
|
+
|
|
5
|
+
describe('NsTextStrip component', () => {
|
|
6
|
+
it('renders text description and link', () => {
|
|
7
|
+
const text = 'Free Delivery';
|
|
8
|
+
const description = 'Download the app to access everything Nike';
|
|
9
|
+
const link = { href: 'https://www.nike.com/in/help/a/shipping-delivery-gs', title: 'View Details' };
|
|
10
|
+
render(<NsTextStrip link={link} description={description} text={text} />);
|
|
11
|
+
const element = screen.getByText(text);
|
|
12
|
+
expect(element).toBeInTheDocument();
|
|
13
|
+
const descElement = screen.getByText(description);
|
|
14
|
+
expect(descElement).toBeInTheDocument();
|
|
15
|
+
const anchorElement = screen.getByText(link.title);
|
|
16
|
+
expect(anchorElement.tagName).toBe('A');
|
|
17
|
+
expect(anchorElement).toHaveAttribute('href', link.href);
|
|
18
|
+
});
|
|
19
|
+
it('does not have anchor when link is undefined', () => {
|
|
20
|
+
const text = 'Free Delivery';
|
|
21
|
+
const description = 'Download the app to access everything Nike';
|
|
22
|
+
let link = { title: 'hi' };
|
|
23
|
+
render(<NsTextStrip link={link} description={description} text={text} />);
|
|
24
|
+
const element = screen.getByText(text);
|
|
25
|
+
expect(element).toBeInTheDocument();
|
|
26
|
+
const descElement = screen.getByText(description);
|
|
27
|
+
expect(descElement).toBeInTheDocument();
|
|
28
|
+
expect(() => screen.getByText(link.title)).toThrow();
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NsTextStrip.stories.tsx
|
|
3
|
+
* @description NsTextStrip component.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { StoryObj, Meta } from '@storybook/react';
|
|
7
|
+
import { NsTextStrip } from '@/common/';
|
|
8
|
+
import { withCenterDecorator } from '../../stories/decorators/withCenterDecorator';
|
|
9
|
+
|
|
10
|
+
type ComponentType = typeof NsTextStrip;
|
|
11
|
+
type Story = StoryObj<ComponentType>;
|
|
12
|
+
type MetaStory = Meta<ComponentType>;
|
|
13
|
+
|
|
14
|
+
export default {
|
|
15
|
+
title: 'Components/NsTextStrip',
|
|
16
|
+
component: NsTextStrip,
|
|
17
|
+
decorators: [withCenterDecorator],
|
|
18
|
+
argTypes: {
|
|
19
|
+
children: {
|
|
20
|
+
control: 'text', // use the text control to edit children prop
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
args: {
|
|
24
|
+
text: 'Free Delivery',
|
|
25
|
+
description: 'Download the app to access everything Nike',
|
|
26
|
+
link: { href: 'https://www.nike.com/in/help/a/shipping-delivery-gs', title: 'View Details' },
|
|
27
|
+
alignment: 'center',
|
|
28
|
+
justify: 'center',
|
|
29
|
+
},
|
|
30
|
+
} as MetaStory;
|
|
31
|
+
|
|
32
|
+
export const DefaultTextStrip: Story = {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NsTextStrip.tsx
|
|
3
|
+
* @description NsTextStrip component for scrolling text CTA
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
|
|
8
|
+
import { NsTextStripProps } from './types.d';
|
|
9
|
+
import { NsTypography } from '../typography';
|
|
10
|
+
import { NsLink } from '../link';
|
|
11
|
+
import { styled, ColorUtils, FoundationTheme } from '@nuskin/foundation-theme';
|
|
12
|
+
const { getPaletteColor, getAppColor } = ColorUtils;
|
|
13
|
+
const getIsLight = (theme: FoundationTheme.Theme) => {
|
|
14
|
+
const { palette = { primary: { main: '', contrastText: '' } } } = theme;
|
|
15
|
+
return palette.primary.main === getAppColor(theme, 'primary', 'black');
|
|
16
|
+
};
|
|
17
|
+
const StyledHeader = styled.header`
|
|
18
|
+
background: ${({ theme }) => (getIsLight(theme) ? '#f5f5f5' : getPaletteColor(theme, 'primary', 'contrastText'))};
|
|
19
|
+
padding: 10px;
|
|
20
|
+
a {
|
|
21
|
+
text-decoration: underline;
|
|
22
|
+
font-weight: 600;
|
|
23
|
+
}
|
|
24
|
+
`;
|
|
25
|
+
const NsTextStrip = (props: NsTextStripProps) => {
|
|
26
|
+
const { alignment = 'center', text, description, link, className = '' } = props;
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<StyledHeader className={`${className} justify-${alignment}`}>
|
|
30
|
+
<NsTypography variant="h5" weight="bold">
|
|
31
|
+
{text}
|
|
32
|
+
</NsTypography>
|
|
33
|
+
<NsTypography variant="p-xs">
|
|
34
|
+
{description}
|
|
35
|
+
{link?.href ? <NsLink href={link.href}>{link.title}</NsLink> : ''}
|
|
36
|
+
</NsTypography>
|
|
37
|
+
</StyledHeader>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default NsTextStrip;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AdditionalProps } from '../common.types';
|
|
2
|
+
|
|
3
|
+
export type AlignmentType = 'start' | 'center' | 'end';
|
|
4
|
+
|
|
5
|
+
export type NsTextStripProps = {
|
|
6
|
+
alignment?: AlignmentType;
|
|
7
|
+
className?: string;
|
|
8
|
+
link?: {
|
|
9
|
+
href?: string;
|
|
10
|
+
title?: string;
|
|
11
|
+
};
|
|
12
|
+
text?: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
} & AdditionalProps;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import { PropsWithChildren } from 'react';
|
|
8
8
|
|
|
9
|
-
import { NsVideoProps } from './types';
|
|
9
|
+
import { NsVideoProps } from './types.d';
|
|
10
10
|
|
|
11
11
|
const NsVideo = (props: PropsWithChildren<NsVideoProps>) => {
|
|
12
12
|
const { src, title, width, height, allowFullScreen } = props;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { default as NsVideo } from './NsVideo';
|
|
2
|
-
export type { NsVideoProps } from './types';
|
|
2
|
+
export type { NsVideoProps } from './types.d';
|
|
File without changes
|
|
File without changes
|