@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.
Files changed (117) hide show
  1. package/package.json +1 -1
  2. package/src/common/alert/NsAlert.spec.tsx +17 -16
  3. package/src/common/alert/NsAlert.styled.ts +20 -20
  4. package/src/common/alert/NsAlert.tsx +21 -40
  5. package/src/common/alert/index.ts +2 -2
  6. package/src/common/auth-dropdown/NsAuthDropdown.spec.tsx +1 -1
  7. package/src/common/auth-dropdown/NsAuthDropdown.tsx +1 -1
  8. package/src/common/auth-dropdown/index.ts +1 -1
  9. package/src/common/autocomplete/NsAutocomplete.spec.tsx +5 -5
  10. package/src/common/autocomplete/NsAutocomplete.stories.tsx +1 -1
  11. package/src/common/autocomplete/NsAutocomplete.tsx +1 -1
  12. package/src/common/autocomplete/index.ts +2 -1
  13. package/src/common/banner/NsBanner.spec.tsx +1 -1
  14. package/src/common/banner/NsBanner.styled.tsx +1 -1
  15. package/src/common/banner/NsBanner.tsx +1 -1
  16. package/src/common/banner/index.ts +1 -1
  17. package/src/common/brand-components/NsBrandComponent.tsx +1 -1
  18. package/src/common/brand-components/index.ts +1 -1
  19. package/src/common/breadcrumb/NsBreadcrumb.spec.tsx +1 -1
  20. package/src/common/breadcrumb/NsBreadcrumb.tsx +1 -1
  21. package/src/common/breadcrumb/index.ts +1 -1
  22. package/src/common/button/NsButton.spec.tsx +1 -1
  23. package/src/common/button/NsButton.styled.tsx +10 -13
  24. package/src/common/button/NsButton.tsx +1 -1
  25. package/src/common/button/index.ts +1 -1
  26. package/src/common/card/NsFfgCard.tsx +1 -1
  27. package/src/common/carousal/NsScrollingCarousal.tsx +37 -0
  28. package/src/common/carousal/index.ts +3 -0
  29. package/src/common/carousal/stories/NSCarousal.stories.tsx +1 -1
  30. package/src/common/carousal/stories/NsScrollingCarousal.stories.tsx +52 -0
  31. package/src/common/carousal/tests/NsCarousal.spec.tsx +2 -2
  32. package/src/common/carousal/tests/NsScrollingCarousal.spec.tsx +61 -0
  33. package/src/common/carousal/types.d.ts +21 -0
  34. package/src/common/cart-icon/NsCartIcon.spec.tsx +1 -1
  35. package/src/common/cart-icon/NsCartIcon.tsx +1 -1
  36. package/src/common/cart-icon/index.ts +1 -1
  37. package/src/common/checkbox/NsCheckbox.spec.tsx +2 -2
  38. package/src/common/checkbox/NsCheckbox.tsx +1 -1
  39. package/src/common/checkbox/index.ts +1 -1
  40. package/src/common/checkbox/types.d.ts +1 -7
  41. package/src/common/column-control/NsColumnControl.tsx +1 -1
  42. package/src/common/column-control/NsFlexColumns.tsx +27 -0
  43. package/src/common/column-control/NsGridColumns.tsx +27 -0
  44. package/src/common/column-control/index.ts +3 -1
  45. package/src/common/column-control/{NsColumnControl.spec.tsx → specs/NsColumnControl.spec.tsx} +3 -3
  46. package/src/common/column-control/specs/NsFlexColumns.spec.tsx +24 -0
  47. package/src/common/column-control/specs/NsGridColumns.spec.tsx +24 -0
  48. package/src/common/column-control/{NDivs.story.tsx → stories/NDivs.story.tsx} +1 -1
  49. package/src/common/column-control/{NsColumnControl.stories.tsx → stories/NsColumnControl.stories.tsx} +4 -14
  50. package/src/common/column-control/stories/NsFlexColumns.stories.tsx +59 -0
  51. package/src/common/column-control/stories/NsGridColumns.stories.tsx +59 -0
  52. package/src/common/column-control/stories/common.tsx +14 -0
  53. package/src/common/column-control/styled/StyledFlex.tsx +41 -0
  54. package/src/common/column-control/styled/StyledGrid.tsx +33 -0
  55. package/src/common/column-control/styled/common.ts +27 -0
  56. package/src/common/column-control/utils.ts +1 -1
  57. package/src/common/dropdown/NsDropdown.spec.tsx +1 -1
  58. package/src/common/dropdown/NsDropdown.tsx +1 -1
  59. package/src/common/dropdown/NsDropdownOption.tsx +1 -1
  60. package/src/common/dropdown/index.ts +1 -1
  61. package/src/common/flag/NsFlag.spec.tsx +1 -1
  62. package/src/common/flag/NsFlag.styled.tsx +3 -5
  63. package/src/common/flag/NsFlag.tsx +1 -1
  64. package/src/common/flag/index.ts +1 -1
  65. package/src/common/flag/types.d.ts +0 -2
  66. package/src/common/icon/NsIcon.spec.tsx +1 -1
  67. package/src/common/icon/NsIcon.styled.tsx +1 -1
  68. package/src/common/icon/NsIcon.tsx +1 -1
  69. package/src/common/icon/NsIconVariants.ts +8 -4
  70. package/src/common/icon/icons/AlertErrorIcon.tsx +15 -6
  71. package/src/common/icon/icons/HamburgerIcon.tsx +29 -0
  72. package/src/common/icon/icons/UserIcon.tsx +30 -0
  73. package/src/common/icon/icons/WarningIcon.tsx +14 -5
  74. package/src/common/icon/index.ts +1 -1
  75. package/src/common/image/NsImage.spec.tsx +1 -1
  76. package/src/common/image/NsImage.tsx +1 -1
  77. package/src/common/image/NsNextImage.spec.tsx +1 -1
  78. package/src/common/image/NsNextImage.tsx +1 -1
  79. package/src/common/image/index.ts +1 -1
  80. package/src/common/index.ts +7 -10
  81. package/src/common/input/InputWrapper.tsx +1 -1
  82. package/src/common/input/NsInputField.tsx +1 -1
  83. package/src/common/input/getAdornmentProps.tsx +1 -1
  84. package/src/common/input/index.ts +1 -1
  85. package/src/common/label/NsLabel.tsx +1 -1
  86. package/src/common/label/index.ts +1 -1
  87. package/src/common/link/NsLink.spec.tsx +1 -1
  88. package/src/common/link/NsLink.tsx +1 -1
  89. package/src/common/link/index.ts +1 -1
  90. package/src/common/nav-product-card/NsNavProductCard.spec.tsx +1 -1
  91. package/src/common/nav-product-card/NsNavProductCard.tsx +1 -1
  92. package/src/common/nav-product-card/index.ts +1 -1
  93. package/src/common/nav-tab/NsNavTab.spec.tsx +2 -2
  94. package/src/common/nav-tab/NsNavTab.tsx +1 -1
  95. package/src/common/nav-tab/index.ts +1 -1
  96. package/src/common/search-bar/NsSeachBar.spec.tsx +1 -1
  97. package/src/common/table/NsTable.spec.tsx +146 -0
  98. package/src/common/table/NsTable.stories.tsx +123 -0
  99. package/src/common/table/NsTable.styled.ts +33 -0
  100. package/src/common/table/NsTable.tsx +161 -0
  101. package/src/common/table/NsTableHeader.tsx +48 -0
  102. package/src/common/table/NsTablePagination.tsx +20 -0
  103. package/src/common/table/helper.ts +33 -0
  104. package/src/common/table/index.ts +2 -0
  105. package/src/common/table/types.d.ts +44 -0
  106. package/src/common/text-strip/NsTextStrip.spec.tsx +30 -0
  107. package/src/common/text-strip/NsTextStrip.stories.tsx +32 -0
  108. package/src/common/text-strip/NsTextStrip.tsx +41 -0
  109. package/src/common/text-strip/index.ts +2 -0
  110. package/src/common/text-strip/types.d.ts +14 -0
  111. package/src/common/typography/NsTypography.tsx +1 -1
  112. package/src/common/typography/Typography.styled.tsx +1 -1
  113. package/src/common/typography/index.ts +1 -1
  114. package/src/common/videos/NsVideo.tsx +1 -1
  115. package/src/common/videos/index.ts +1 -1
  116. /package/src/common/autocomplete/{types.ts → types.d.ts} +0 -0
  117. /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,2 @@
1
+ export { default as NsTable } from './NsTable';
2
+ export type { NsTableProps } from './types.d';
@@ -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}&nbsp;
35
+ {link?.href ? <NsLink href={link.href}>{link.title}</NsLink> : ''}
36
+ </NsTypography>
37
+ </StyledHeader>
38
+ );
39
+ };
40
+
41
+ export default NsTextStrip;
@@ -0,0 +1,2 @@
1
+ export { default as NsTextStrip } from './NsTextStrip';
2
+ export type { NsTextStripProps } from './types.d';
@@ -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;
@@ -1,5 +1,5 @@
1
1
  import React, { PropsWithChildren } from 'react';
2
- import { NsTypographyProps } from './types';
2
+ import { NsTypographyProps } from './types.d';
3
3
  import { StyledTypography } from './Typography.styled';
4
4
 
5
5
  const NsTypography = ({
@@ -1,5 +1,5 @@
1
1
  import { styled, ColorUtils } from '@nuskin/foundation-theme';
2
- import { NsTypographyProps } from './types';
2
+ import { NsTypographyProps } from './types.d';
3
3
 
4
4
  const { getPaletteColor } = ColorUtils;
5
5
 
@@ -1,3 +1,3 @@
1
1
  export { default as NsTypography } from './NsTypography';
2
- export type { NsTypographyProps, Variants } from './types';
2
+ export type { NsTypographyProps, Variants } from './types.d';
3
3
  export { default as GlobalFontInter } from './GlobalFontInter';
@@ -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';