@nuskin/foundation-ui-components 1.0.0-cft-35.13 → 1.0.0-develop.10

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 (247) hide show
  1. package/package.json +21 -11
  2. package/src/common/accordion/NsAccordion.tsx +69 -0
  3. package/src/common/accordion/NsAccordionHeader.tsx +77 -0
  4. package/src/common/accordion/NsAccordionItem.tsx +59 -0
  5. package/src/common/accordion/NsCollapse.tsx +110 -0
  6. package/src/common/accordion/NsToggleSection.tsx +43 -0
  7. package/src/common/accordion/ToggleSection.styled.tsx +32 -0
  8. package/src/common/accordion/colorMap.ts +117 -0
  9. package/src/common/accordion/enums.ts +8 -0
  10. package/src/common/accordion/index.ts +7 -0
  11. package/src/common/accordion/specs/NsAccordion.spec.tsx +163 -0
  12. package/src/common/accordion/specs/NsAccordionHeader.spec.tsx +130 -0
  13. package/src/common/accordion/specs/NsAccordionItem.spec.tsx +79 -0
  14. package/src/common/accordion/specs/NsCollapse.spec.tsx +129 -0
  15. package/src/common/accordion/specs/NsToggleSection.spec.tsx +74 -0
  16. package/src/common/accordion/stories/NsAccordion.stories.tsx +65 -0
  17. package/src/common/accordion/stories/NsAccordionHeader.stories.tsx +44 -0
  18. package/src/common/accordion/stories/NsAccordionItem.stories.tsx +45 -0
  19. package/src/common/accordion/stories/NsCollapse.stories.tsx +50 -0
  20. package/src/common/accordion/stories/NsToggleSection.stories.tsx +26 -0
  21. package/src/common/accordion/stories/data.tsx +143 -0
  22. package/src/common/accordion/types.d.ts +81 -0
  23. package/src/common/alert/Header.tsx +29 -0
  24. package/src/common/alert/NsAlert.spec.tsx +62 -29
  25. package/src/common/alert/NsAlert.stories.tsx +18 -17
  26. package/src/common/alert/NsAlert.styled.tsx +124 -0
  27. package/src/common/alert/NsAlert.tsx +27 -110
  28. package/src/common/alert/index.ts +2 -2
  29. package/src/common/alert/types.d.ts +23 -23
  30. package/src/common/auth-dropdown/NsAuthDropdown.spec.tsx +24 -6
  31. package/src/common/auth-dropdown/NsAuthDropdown.stories.tsx +2 -2
  32. package/src/common/auth-dropdown/NsAuthDropdown.styled.ts +21 -16
  33. package/src/common/auth-dropdown/NsAuthDropdown.tsx +7 -6
  34. package/src/common/auth-dropdown/index.ts +1 -1
  35. package/src/common/auth-dropdown/types.d.ts +3 -1
  36. package/src/common/autocomplete/NsAutocomplete.spec.tsx +69 -24
  37. package/src/common/autocomplete/NsAutocomplete.stories.tsx +64 -7
  38. package/src/common/autocomplete/NsAutocomplete.styled.tsx +12 -0
  39. package/src/common/autocomplete/NsAutocomplete.tsx +100 -46
  40. package/src/common/autocomplete/index.ts +2 -1
  41. package/src/common/autocomplete/mock/MockData.ts +50 -7
  42. package/src/common/autocomplete/mock/MockUI.tsx +2 -1
  43. package/src/common/autocomplete/{types.ts → types.d.ts} +18 -8
  44. package/src/common/banner/NsBanner.spec.tsx +13 -4
  45. package/src/common/banner/NsBanner.stories.tsx +2 -2
  46. package/src/common/banner/NsBanner.styled.tsx +1 -1
  47. package/src/common/banner/NsBanner.tsx +1 -1
  48. package/src/common/banner/index.ts +1 -1
  49. package/src/common/brand-components/NsBrand.stories.tsx +2 -2
  50. package/src/common/brand-components/NsBrandComponent.tsx +6 -3
  51. package/src/common/brand-components/index.ts +1 -1
  52. package/src/common/breadcrumb/NsBreadcrumb.spec.tsx +8 -9
  53. package/src/common/breadcrumb/NsBreadcrumb.stories.tsx +3 -5
  54. package/src/common/breadcrumb/NsBreadcrumb.tsx +5 -3
  55. package/src/common/breadcrumb/data.ts +10 -0
  56. package/src/common/breadcrumb/index.ts +1 -1
  57. package/src/common/button/NsButton.spec.tsx +66 -51
  58. package/src/common/button/NsButton.stories.tsx +61 -4
  59. package/src/common/button/NsButton.styled.tsx +54 -72
  60. package/src/common/button/NsButton.tsx +9 -3
  61. package/src/common/button/helper.ts +82 -0
  62. package/src/common/button/index.ts +1 -1
  63. package/src/common/button/types.d.ts +3 -0
  64. package/src/common/card/NsFfgCard.tsx +14 -8
  65. package/src/common/card/specs/NsFfgCard.spec.tsx +33 -0
  66. package/src/common/card/stories/NsBgCard.stories.tsx +2 -4
  67. package/src/common/card/stories/NsBrandProductCard.stories.tsx +2 -2
  68. package/src/common/card/stories/NsFfgCard.stories.tsx +49 -16
  69. package/src/common/card/stories/{data.js → data.ts} +1 -25
  70. package/src/common/card/styled/NsFfgStyled.tsx +9 -7
  71. package/src/common/card/types.d.ts +7 -4
  72. package/src/common/carousal/NsScrollingCarousal.tsx +61 -0
  73. package/src/common/carousal/index.ts +3 -0
  74. package/src/common/carousal/{tests → specs}/NsCarousal.spec.tsx +2 -2
  75. package/src/common/carousal/specs/NsScrollingCarousal.spec.tsx +61 -0
  76. package/src/common/carousal/stories/NSCarousal.stories.tsx +2 -2
  77. package/src/common/carousal/stories/NsScrollingCarousal.stories.tsx +52 -0
  78. package/src/common/carousal/types.d.ts +23 -0
  79. package/src/common/cart-icon/NsCartIcon.spec.tsx +1 -1
  80. package/src/common/cart-icon/NsCartIcon.stories.tsx +2 -2
  81. package/src/common/cart-icon/NsCartIcon.tsx +1 -1
  82. package/src/common/cart-icon/index.ts +1 -1
  83. package/src/common/checkbox/NsCheckbox.spec.tsx +2 -2
  84. package/src/common/checkbox/NsCheckbox.stories.tsx +2 -2
  85. package/src/common/checkbox/NsCheckbox.styled.tsx +15 -16
  86. package/src/common/checkbox/NsCheckbox.tsx +2 -2
  87. package/src/common/checkbox/index.ts +1 -1
  88. package/src/common/checkbox/types.d.ts +1 -7
  89. package/src/common/column-control/NsColumnControl.tsx +1 -1
  90. package/src/common/column-control/NsFlexColumns.tsx +22 -0
  91. package/src/common/column-control/NsGridColumns.tsx +22 -0
  92. package/src/common/column-control/index.ts +3 -1
  93. package/src/common/column-control/{NsColumnControl.spec.tsx → specs/NsColumnControl.spec.tsx} +3 -3
  94. package/src/common/column-control/specs/NsFlexColumns.spec.tsx +24 -0
  95. package/src/common/column-control/specs/NsGridColumns.spec.tsx +24 -0
  96. package/src/common/column-control/stories/DivArray.stories.tsx +18 -0
  97. package/src/common/column-control/stories/DivArray.tsx +63 -0
  98. package/src/common/column-control/{NsColumnControl.stories.tsx → stories/NsColumnControl.stories.tsx} +9 -16
  99. package/src/common/column-control/stories/NsFlexColumns.stories.tsx +63 -0
  100. package/src/common/column-control/stories/NsGridColumns.stories.tsx +63 -0
  101. package/src/common/column-control/stories/common.tsx +14 -0
  102. package/src/common/column-control/styled/StyledFlex.tsx +45 -0
  103. package/src/common/column-control/styled/StyledGrid.tsx +40 -0
  104. package/src/common/column-control/styled/common.ts +27 -0
  105. package/src/common/column-control/types.d.ts +15 -16
  106. package/src/common/column-control/utils.ts +5 -5
  107. package/src/common/common.types.d.ts +21 -0
  108. package/src/common/dropdown/NsDropdown.spec.tsx +1 -1
  109. package/src/common/dropdown/NsDropdown.styled.tsx +23 -18
  110. package/src/common/dropdown/NsDropdown.tsx +1 -1
  111. package/src/common/dropdown/NsDropdownOption.tsx +1 -1
  112. package/src/common/dropdown/index.ts +1 -1
  113. package/src/common/dropdown/stories/NsDropdown.stories.tsx +2 -2
  114. package/src/common/dropdown/stories/NsDropdownCountry.stories.tsx +2 -2
  115. package/src/common/dropdown/types.d.ts +3 -1
  116. package/src/common/email-simple/NsEmailSimple.spec.tsx +145 -0
  117. package/src/common/email-simple/NsEmailSimple.stories.tsx +61 -0
  118. package/src/common/email-simple/NsEmailSimple.tsx +71 -0
  119. package/src/common/email-simple/index.ts +2 -0
  120. package/src/common/email-simple/types.d.ts +14 -0
  121. package/src/common/flag/NsFlag.spec.tsx +5 -25
  122. package/src/common/flag/NsFlag.stories.tsx +2 -2
  123. package/src/common/flag/NsFlag.styled.tsx +7 -9
  124. package/src/common/flag/NsFlag.tsx +1 -3
  125. package/src/common/flag/index.ts +1 -1
  126. package/src/common/flag/types.d.ts +0 -2
  127. package/src/common/hooks/index.ts +2 -0
  128. package/src/common/hooks/specs/useWindowSize.spec.tsx +19 -0
  129. package/src/common/hooks/useAccordionMap.tsx +39 -0
  130. package/src/common/hooks/useWindowSize.tsx +30 -0
  131. package/src/common/icon/NsIcon.spec.tsx +1 -1
  132. package/src/common/icon/NsIcon.stories.tsx +2 -2
  133. package/src/common/icon/NsIcon.styled.tsx +1 -1
  134. package/src/common/icon/NsIcon.tsx +1 -1
  135. package/src/common/icon/NsIconVariants.ts +9 -4
  136. package/src/common/icon/icons/AlertErrorIcon.tsx +15 -6
  137. package/src/common/icon/icons/HamburgerIcon.tsx +29 -0
  138. package/src/common/icon/icons/UserIcon.tsx +30 -0
  139. package/src/common/icon/icons/WarningIcon.tsx +14 -5
  140. package/src/common/icon/index.ts +1 -1
  141. package/src/common/icon/types.d.ts +1 -0
  142. package/src/common/image/NsImage.spec.tsx +57 -7
  143. package/src/common/image/NsImage.stories.tsx +2 -2
  144. package/src/common/image/NsImage.tsx +24 -12
  145. package/src/common/image/NsNextImage.spec.tsx +1 -1
  146. package/src/common/image/NsNextImage.stories.tsx +2 -2
  147. package/src/common/image/NsNextImage.tsx +1 -1
  148. package/src/common/image/index.ts +1 -1
  149. package/src/common/image/types.d.ts +1 -0
  150. package/src/common/index.ts +14 -10
  151. package/src/common/input/InputFieldWrapper.tsx +4 -4
  152. package/src/common/input/InputWrapper.tsx +12 -7
  153. package/src/common/input/NsInputField.stories.tsx +13 -10
  154. package/src/common/input/NsInputField.tsx +13 -6
  155. package/src/common/input/getAdornmentProps.tsx +5 -1
  156. package/src/common/input/index.ts +1 -1
  157. package/src/common/input/types.d.ts +18 -1
  158. package/src/common/label/NsLabel.stories.tsx +6 -1
  159. package/src/common/label/NsLabel.tsx +21 -20
  160. package/src/common/label/index.ts +1 -1
  161. package/src/common/label/types.d.ts +2 -1
  162. package/src/common/link/NsLink.spec.tsx +1 -1
  163. package/src/common/link/NsLink.stories.tsx +2 -2
  164. package/src/common/link/NsLink.tsx +1 -1
  165. package/src/common/link/index.ts +1 -1
  166. package/src/common/modal/NsModal.spec.tsx +46 -0
  167. package/src/common/modal/NsModal.styled.tsx +28 -0
  168. package/src/common/modal/NsModal.tsx +37 -0
  169. package/src/common/modal/helper-component/NsModalContentBox.tsx +32 -0
  170. package/src/common/modal/helper-component/NsModalDefault.tsx +25 -0
  171. package/src/common/modal/helper-component/NsModalStatus.tsx +15 -0
  172. package/src/common/modal/helper-component/NsModalStatusIcon.tsx +14 -0
  173. package/src/common/modal/helper-component/NsModalTitle.tsx +26 -0
  174. package/src/common/modal/index.ts +2 -0
  175. package/src/common/modal/model/NsModalVariantMap.tsx +24 -0
  176. package/src/common/modal/stories/NsModal.stories.tsx +86 -0
  177. package/src/common/modal/stories/mock.tsx +46 -0
  178. package/src/common/modal/types.ts +56 -0
  179. package/src/common/nav-product-card/NsNavProductCard.spec.tsx +1 -1
  180. package/src/common/nav-product-card/NsNavProductCard.stories.tsx +2 -2
  181. package/src/common/nav-product-card/NsNavProductCard.tsx +1 -1
  182. package/src/common/nav-product-card/index.ts +1 -1
  183. package/src/common/nav-tab/NsNavTab.spec.tsx +2 -7
  184. package/src/common/nav-tab/NsNavTab.stories.tsx +2 -2
  185. package/src/common/nav-tab/NsNavTab.styled.tsx +7 -4
  186. package/src/common/nav-tab/NsNavTab.tsx +1 -1
  187. package/src/common/nav-tab/index.ts +1 -1
  188. package/src/common/nav-tab/types.d.ts +2 -2
  189. package/src/common/radiogroup/NsRadioGroup.spec.tsx +63 -0
  190. package/src/common/radiogroup/NsRadioGroup.stories.tsx +84 -0
  191. package/src/common/radiogroup/NsRadioGroup.styled.tsx +52 -0
  192. package/src/common/radiogroup/NsRadioGroup.tsx +62 -0
  193. package/src/common/radiogroup/index.ts +2 -0
  194. package/src/common/radiogroup/types.d.ts +20 -0
  195. package/src/common/search-bar/NsSeachBar.spec.tsx +1 -1
  196. package/src/common/search-bar/NsSearchBar.tsx +1 -3
  197. package/src/common/select/NsSelect.spec.tsx +193 -0
  198. package/src/common/select/NsSelect.styled.tsx +104 -0
  199. package/src/common/select/NsSelect.tsx +117 -0
  200. package/src/common/select/NsSelectOption.tsx +30 -0
  201. package/src/common/select/index.ts +3 -0
  202. package/src/common/select/stories/NsSelect.stories.tsx +134 -0
  203. package/src/common/select/types.d.ts +34 -0
  204. package/src/common/spinner/NsSpinner.spec.tsx +21 -0
  205. package/src/common/spinner/NsSpinner.stories.tsx +26 -0
  206. package/src/common/spinner/NsSpinner.styled.tsx +344 -0
  207. package/src/common/spinner/NsSpinner.tsx +14 -0
  208. package/src/common/spinner/icons/Spinner.tsx +161 -0
  209. package/src/common/spinner/index.ts +2 -0
  210. package/src/common/spinner/types.ts +5 -0
  211. package/src/common/table/NsExpandableRow.tsx +68 -0
  212. package/src/common/table/NsTable.spec.tsx +174 -0
  213. package/src/common/table/NsTable.stories.tsx +161 -0
  214. package/src/common/table/NsTable.styled.ts +127 -0
  215. package/src/common/table/NsTable.tsx +133 -0
  216. package/src/common/table/NsTableHeader.tsx +41 -0
  217. package/src/common/table/NsTablePagination.tsx +28 -0
  218. package/src/common/table/helper.ts +33 -0
  219. package/src/common/table/index.ts +2 -0
  220. package/src/common/table/types.d.ts +57 -0
  221. package/src/common/text-strip/NsTextStrip.spec.tsx +30 -0
  222. package/src/common/text-strip/NsTextStrip.stories.tsx +33 -0
  223. package/src/common/text-strip/NsTextStrip.tsx +47 -0
  224. package/src/common/text-strip/index.ts +2 -0
  225. package/src/common/text-strip/types.d.ts +17 -0
  226. package/src/common/typography/NsTypography.stories.tsx +2 -2
  227. package/src/common/typography/NsTypography.tsx +1 -1
  228. package/src/common/typography/Typography.styled.tsx +4 -4
  229. package/src/common/typography/index.ts +1 -1
  230. package/src/common/util.ts +1 -0
  231. package/src/common/utility/Show.tsx +13 -0
  232. package/src/common/utility/index.ts +1 -0
  233. package/src/common/validations/regex.ts +3 -0
  234. package/src/common/videos/NsVideo.stories.tsx +2 -2
  235. package/src/common/videos/NsVideo.tsx +1 -1
  236. package/src/common/videos/index.ts +1 -1
  237. package/src/common/videos/types.d.ts +1 -1
  238. package/src/common/alert/NsAlert.styled.ts +0 -124
  239. package/src/common/card/tests/NsFfgCard.spec.tsx +0 -23
  240. package/src/common/column-control/NDivs.story.tsx +0 -35
  241. package/src/common/common.types.ts +0 -10
  242. /package/src/common/brand-components/{NsBrandContanier.styled.tsx → NsBrandContainer.styled.tsx} +0 -0
  243. /package/src/common/card/{tests → specs}/BrandLogo.spec.tsx +0 -0
  244. /package/src/common/card/{tests → specs}/NsBgCard.spec.tsx +0 -0
  245. /package/src/common/card/{tests → specs}/NsBrandProductCard.spec.tsx +0 -0
  246. /package/src/common/carousal/{tests → specs}/Chevron.spec.tsx +0 -0
  247. /package/src/common/carousal/{tests → specs}/RenderBrand.spec.tsx +0 -0
@@ -0,0 +1,174 @@
1
+ import React from 'react';
2
+ import { render, fireEvent, screen } from '@/test-utils/index';
3
+ import NsTable from './NsTable';
4
+ import { Item } from './types';
5
+ import { NsIcon } from '../icon';
6
+
7
+ const expandableContent = (selectedItem: Item, index: number) => {
8
+ return (
9
+ <div key={index}>
10
+ <p>
11
+ Data: {selectedItem.name} , {selectedItem.calories}
12
+ </p>
13
+ <p>
14
+ Index: {index}
15
+ </p>
16
+ <p>
17
+ Expandable: True
18
+ </p>
19
+ </div>
20
+ )
21
+ }
22
+
23
+ const actionClick = (row: Item) => {
24
+ const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
25
+ event.stopPropagation();
26
+ console.log(row)
27
+ }
28
+
29
+ return (
30
+ <button onClick={handleClick}>
31
+ <NsIcon
32
+ name='cart'
33
+ size='medium'
34
+ />
35
+ </button>
36
+ )
37
+ }
38
+
39
+ describe('NsTable', () => {
40
+ const headers = [
41
+ { id: 'name', label: 'Name', numeric: false, sortable: true },
42
+ { id: 'age', label: 'Age', numeric: true, sortable: true },
43
+ ];
44
+
45
+ const items = [
46
+ { name: 'John', age: 26 },
47
+ { name: 'Jane', age: 32 },
48
+ { name: 'Maria', age: 28 },
49
+ { name: 'Kevin', age: 31 },
50
+ { name: 'Suzan', age: 25 },
51
+ { name: 'Dan', age: 30 },
52
+ { name: 'Micheal', age: 39 },
53
+ { name: 'Sandy', age: 39 },
54
+ ];
55
+
56
+ const rows = 5;
57
+ const rowsPerPageOptions = [5, 10, 15];
58
+ const itemKey = 'name';
59
+
60
+ it('renders table with correct data', () => {
61
+ render(
62
+ <NsTable
63
+ headers={headers}
64
+ items={items}
65
+ rows={rows}
66
+ rowsPerPageOptions={rowsPerPageOptions}
67
+ itemKey={itemKey}
68
+ isExpandableAll={true}
69
+ loading={true}
70
+ showActions={false}
71
+ showExpandedContent={false}
72
+ expandableContent={expandableContent}
73
+ actionClick={actionClick}
74
+ />
75
+ );
76
+
77
+ expect(screen.getByText('Name')).toBeInTheDocument();
78
+ expect(screen.getByText('Age')).toBeInTheDocument();
79
+ expect(screen.getByText('Kevin')).toBeInTheDocument();
80
+ expect(screen.getByText('Maria')).toBeInTheDocument();
81
+ expect(screen.getByText('28')).toBeInTheDocument();
82
+ expect(screen.getByText('31')).toBeInTheDocument();
83
+ });
84
+
85
+ it('expandable true click', () => {
86
+ render(
87
+ <NsTable
88
+ headers={headers}
89
+ items={items}
90
+ rows={rows}
91
+ rowsPerPageOptions={rowsPerPageOptions}
92
+ itemKey={itemKey}
93
+ isExpandableAll={true}
94
+ expandableContent={expandableContent}
95
+ actionClick={actionClick}
96
+ />
97
+ );
98
+
99
+
100
+ expect(screen.getByTestId('table-row-0')).toBeInTheDocument();
101
+
102
+ const button = screen.getByTestId('table-row-0');
103
+
104
+ fireEvent.click(button);
105
+ expect(screen.getByText('Expandable: True')).toBeInTheDocument();
106
+ fireEvent.click(button);
107
+ });
108
+
109
+ it('expandable false click', () => {
110
+ render(
111
+ <NsTable
112
+ headers={headers}
113
+ items={items}
114
+ rows={rows}
115
+ rowsPerPageOptions={rowsPerPageOptions}
116
+ itemKey={itemKey}
117
+ isExpandableAll={false}
118
+ expandableContent={expandableContent}
119
+ actionClick={actionClick}
120
+ />
121
+ );
122
+
123
+ expect(screen.getByTestId('table-row-0')).toBeInTheDocument();
124
+
125
+ const button = screen.getByTestId('table-row-0');
126
+
127
+ fireEvent.click(button);
128
+ expect(screen.getByText('Expandable: True')).toBeInTheDocument();
129
+ fireEvent.click(button);
130
+ });
131
+
132
+ it('pagination next button click event', async () => {
133
+ render(
134
+ <NsTable
135
+ headers={headers}
136
+ items={items}
137
+ rows={rows}
138
+ rowsPerPageOptions={rowsPerPageOptions}
139
+ itemKey={itemKey}
140
+ isExpandableAll={true}
141
+ expandableContent={expandableContent}
142
+ actionClick={actionClick}
143
+ />
144
+ );
145
+
146
+ expect(screen.getByTestId('NavigateNextIcon')).toBeInTheDocument();
147
+
148
+ const button = screen.getByTestId('NavigateNextIcon');
149
+ fireEvent.click(button);
150
+ expect(screen.getByText('Sandy')).toBeInTheDocument();
151
+ });
152
+
153
+ it('sort rows via age', () => {
154
+ render(
155
+ <NsTable
156
+ headers={headers}
157
+ items={items}
158
+ rows={rows}
159
+ rowsPerPageOptions={rowsPerPageOptions}
160
+ itemKey={itemKey}
161
+ isExpandableAll={true}
162
+ expandableContent={expandableContent}
163
+ actionClick={actionClick}
164
+ />
165
+ );
166
+
167
+ expect(screen.getByText('Age')).toBeInTheDocument();
168
+ const button = screen.getByText('Age');
169
+ fireEvent.click(button);
170
+
171
+ expect(screen.getByText('John')).toBeInTheDocument();
172
+ fireEvent.click(button);
173
+ });
174
+ });
@@ -0,0 +1,161 @@
1
+ import React from 'react'
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import NsTable from './NsTable';
4
+ import { withCenterDecorator } from '../../stories/decorators/withCenterDecorator';
5
+ import { Item } from './types';
6
+ import { NsIcon } from '../icon';
7
+
8
+ type ComponentType = typeof NsTable;
9
+ type Story = StoryObj<ComponentType>;
10
+ type MetaStory = Meta<ComponentType>;
11
+ const headers = [
12
+ {
13
+ label: 'Dessert (100g serving)',
14
+ id: 'name',
15
+ numeric: false,
16
+ sortable: false
17
+ },
18
+ { label: 'Calories', id: 'calories' , numeric: true, sortable: true},
19
+ { label: 'Fat (g)', id: 'fat', numeric: true, sortable: true },
20
+ { label: 'Carbs (g)', id: 'carbs', numeric: true, sortable: true },
21
+ { label: 'Protein (g)', id: 'protein', numeric: true, sortable: true },
22
+ { label: 'Iron (%)', id: 'iron', numeric: false, sortable: true },
23
+ ];
24
+
25
+ const items = [
26
+ {
27
+ name: 'Frozen Yogurt',
28
+ calories: 159,
29
+ fat: 6.0,
30
+ carbs: 24,
31
+ protein: 4.0,
32
+ iron: '1%',
33
+ },
34
+ {
35
+ name: 'Ice cream sandwich',
36
+ calories: 237,
37
+ fat: 9.0,
38
+ carbs: 37,
39
+ protein: 4.3,
40
+ iron: '1%',
41
+ },
42
+ {
43
+ name: 'Eclair',
44
+ calories: 262,
45
+ fat: 16.0,
46
+ carbs: 23,
47
+ protein: 6.0,
48
+ iron: '7%',
49
+ },
50
+ {
51
+ name: 'Cupcake',
52
+ calories: 305,
53
+ fat: 3.7,
54
+ carbs: 67,
55
+ protein: 4.3,
56
+ iron: '8%',
57
+ },
58
+ {
59
+ name: 'Gingerbread',
60
+ calories: 356,
61
+ fat: 16.0,
62
+ carbs: 49,
63
+ protein: 3.9,
64
+ iron: '16%',
65
+ },
66
+ {
67
+ name: 'Jelly bean',
68
+ calories: 375,
69
+ fat: 0.0,
70
+ carbs: 94,
71
+ protein: 0.0,
72
+ iron: '0%',
73
+ },
74
+ {
75
+ name: 'Lollipop',
76
+ calories: 392,
77
+ fat: 0.2,
78
+ carbs: 98,
79
+ protein: 0,
80
+ iron: '2%',
81
+ },
82
+ {
83
+ name: 'Honeycomb',
84
+ calories: 408,
85
+ fat: 3.2,
86
+ carbs: 87,
87
+ protein: 6.5,
88
+ iron: '45%',
89
+ },
90
+ {
91
+ name: 'Donut',
92
+ calories: 452,
93
+ fat: 25.0,
94
+ carbs: 51,
95
+ protein: 4.9,
96
+ iron: '22%',
97
+ },
98
+ {
99
+ name: 'KitKat',
100
+ calories: 518,
101
+ fat: 26.0,
102
+ carbs: 65,
103
+ protein: 7,
104
+ iron: '6%',
105
+ },
106
+ ];
107
+
108
+ export default {
109
+ title: 'Components/Data Display/NsTable',
110
+ component: NsTable,
111
+ decorators: [withCenterDecorator],
112
+ argTypes: {
113
+ rows: {
114
+ control: 'select',
115
+ options: [5, 10, 25],
116
+ },
117
+ },
118
+ args: {
119
+ headers: headers,
120
+ items: items,
121
+ rows: 5,
122
+ itemKey: 'name',
123
+ rowsPerPageOptions: [5, 10, 25],
124
+ isExpandableAll: true,
125
+ showActions: true,
126
+ showExpandedContent: true,
127
+ loading: false,
128
+ expandableContent: (selectedItem: Item, index: number) => {
129
+ return (
130
+ <div key={index}>
131
+ <p>
132
+ Data: {selectedItem.name} , {selectedItem.calories}
133
+ </p>
134
+ <p>
135
+ Index: {index}
136
+ </p>
137
+ <p>
138
+ Expandable: True
139
+ </p>
140
+ </div>
141
+ )
142
+ },
143
+ actionClick: (row: Item) => {
144
+ const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
145
+ event.stopPropagation();
146
+ console.log(row)
147
+ }
148
+
149
+ return (
150
+ <button onClick={handleClick}>
151
+ <NsIcon
152
+ name='cart'
153
+ size='medium'
154
+ />
155
+ </button>
156
+ )
157
+ }
158
+ }
159
+ } as MetaStory;
160
+
161
+ export const NasTable: Story = {};
@@ -0,0 +1,127 @@
1
+ // TODO: const ariel = #f8e9f8;
2
+
3
+ import { styled, ColorUtils } from '@nuskin/foundation-theme';
4
+
5
+ import {
6
+ Table,
7
+ TableContainer,
8
+ TableSortLabel,
9
+ TableRow,
10
+ TableCell
11
+ } from '@mui/material';
12
+ import Pagination from '@mui/material/Pagination';
13
+ import LinearProgress from '@mui/material/LinearProgress';
14
+
15
+ const { color } = ColorUtils;
16
+
17
+ export const StyledTableContainer= styled(TableContainer)`
18
+ background-color: ${color('primary', 'white')};
19
+ `;
20
+
21
+ export const StyledTable = styled(Table)`
22
+ size: medium;
23
+ `;
24
+
25
+ export const StyledTableSortLabel = styled(TableSortLabel)`
26
+ font-size: 12px;
27
+ text-transform: uppercase;
28
+ font-weight: 600;
29
+ line-height: 16px;
30
+ letter-spacing: 0.05em;
31
+ color: rgba(0, 0, 0, 0.54);
32
+ &:hover {
33
+ color: ${color('primary', 'black')};
34
+ }
35
+ `;
36
+
37
+ export const StyledTableLabel = styled.span`
38
+ font-size: 12px;
39
+ text-transform: uppercase;
40
+ font-weight: 700;
41
+ line-height: 16px;
42
+ letter-spacing: 0.05em;
43
+ color: rgba(0, 0, 0, 0.54);
44
+ &:hover {
45
+ cursor: default;
46
+ }
47
+ `;
48
+
49
+ export const StyledPageComponent = styled.div`
50
+ background-color: ${color('primary', 'white')};
51
+ `;
52
+
53
+ export const StyledEmptyRow = styled(TableRow)<{emptyRows: number}>`
54
+ height: ${({ emptyRows }) => 48 * emptyRows}px;
55
+ `;
56
+
57
+ // [Todo-Arun] - Move f8e9f8 to custom color palette
58
+ export const StyledTableRow = styled(TableRow)`
59
+ &:hover {
60
+ background-color: #f8e9f8 !important;
61
+ }
62
+ `;
63
+
64
+ export const StyledTableLastCell = styled(TableCell)`
65
+ display: flex;
66
+ height: 49px;
67
+ align-items: center;
68
+ padding: 0 24px;
69
+ margin-bottom: -0.5px;
70
+
71
+ .action {
72
+ margin-left: auto;
73
+ }
74
+ `;
75
+
76
+ export const StyledOriginalTableCell = styled(TableCell)`
77
+ height: 48px;
78
+ padding: 0 24px;
79
+ `;
80
+
81
+ export const StyledPagination = styled(Pagination)`
82
+ .MuiPagination-ul {
83
+ display: flex;
84
+ justify-content: flex-end;
85
+ background-color: ${color('primary', 'white')};
86
+ }
87
+ & .MuiPaginationItem-previousNext {
88
+ margin: 0.3rem 10px;
89
+ width: 2rem;
90
+ height: 2rem;
91
+ border-radius: 4px;
92
+ }
93
+ & .MuiPaginationItem-page {
94
+ border-radius: 0px;
95
+ width: auto;
96
+ min-width: 34px;
97
+ padding: 0 5px;
98
+ font-size: 16px;
99
+ line-height: 17px;
100
+ border-color: ${color('primary', 'black')};
101
+ }
102
+ & .MuiPaginationItem-root.Mui-selected {
103
+ background-color: ${color('primary', 'black')};
104
+ color: ${color('primary', 'white')};
105
+ }
106
+ `;
107
+
108
+ export const StyledExpandCell= styled(TableCell)`
109
+ padding-bottom: 0;
110
+ padding-top: 0;
111
+ &.remove {
112
+ border: 0;
113
+ }
114
+ `;
115
+
116
+ export const StyledProgressCell = styled(TableCell)`
117
+ padding: 0;
118
+ border: 0;
119
+ `;
120
+
121
+ export const StyledLinearProgress = styled(LinearProgress)`
122
+ && {
123
+ width: 100%;
124
+ height: 7px;
125
+ border-radius: 4px;
126
+ }
127
+ `;
@@ -0,0 +1,133 @@
1
+ import React, { useState, useEffect } from 'react';
2
+ import { TableBody, TableCell, TableRow } from '@mui/material';
3
+ import {
4
+ StyledTable,
5
+ StyledTableContainer,
6
+ StyledEmptyRow,
7
+ StyledProgressCell,
8
+ StyledLinearProgress,
9
+ } from './NsTable.styled';
10
+ import type { NsTableProps, Item, OrderType } from './types';
11
+ import { stableSort, getComparator } from './helper';
12
+ import NsTableHeader from './NsTableHeader';
13
+ import NsTablePagination from './NsTablePagination';
14
+ import ExpandableRow from './NsExpandableRow';
15
+ import Grid from '@mui/material/Grid';
16
+
17
+ export default function NsTable({
18
+ headers = [],
19
+ items = [],
20
+ rows,
21
+ rowsPerPageOptions,
22
+ itemKey,
23
+ expandableContent,
24
+ actionClick,
25
+ showActions = true,
26
+ showExpandedContent = true,
27
+ loading = false,
28
+ isExpandableAll = false,
29
+ }: NsTableProps) {
30
+ const [order, setOrder] = useState<OrderType>('asc');
31
+ const [orderBy, setOrderBy] = useState<keyof Item>(itemKey);
32
+ const [expandMap, setExpandMap] = useState<{ [key: number]: boolean }>({});
33
+ const [page, setPage] = useState(0);
34
+ const [rowsPerPage, setRowsPerPage] = useState(rows);
35
+ const itemKeyList = React.useMemo(() => {
36
+ return items.length ? Object.keys(items[0]) : [];
37
+ }, [items]);
38
+
39
+ useEffect(() => {
40
+ setRowsPerPage(rows);
41
+ setPage(0);
42
+ }, [rows]);
43
+
44
+ const handleRequestSort = (event: React.MouseEvent<unknown>, property: keyof Item) => {
45
+ const isAsc = orderBy === property && order === 'asc';
46
+ setOrder(isAsc ? 'desc' : 'asc');
47
+ setOrderBy(property);
48
+ };
49
+
50
+ const handleClick = (index: number) => {
51
+ if (isExpandableAll) {
52
+ setExpandMap((prevState) => ({ ...prevState, [index]: !prevState[index] }));
53
+ } else {
54
+ setExpandMap({ [index]: !expandMap[index] });
55
+ }
56
+ };
57
+
58
+ const handleChangePage = (newPage: number) => {
59
+ setPage(newPage - 1);
60
+ };
61
+
62
+ const emptyRows = getEmptyRows();
63
+
64
+ const visibleRows = React.useMemo(
65
+ () =>
66
+ stableSort(items, getComparator(order, orderBy)).slice(
67
+ page * rowsPerPage,
68
+ page * rowsPerPage + rowsPerPage
69
+ ),
70
+ [order, orderBy, page, rowsPerPage, items]
71
+ );
72
+
73
+ return (
74
+ <div>
75
+ <StyledTableContainer>
76
+ <StyledTable>
77
+ <NsTableHeader
78
+ headCells={headers}
79
+ order={order}
80
+ orderBy={orderBy as string}
81
+ onRequestSort={handleRequestSort}
82
+ rowCount={items.length}
83
+ />
84
+ <TableBody>
85
+ {loading ? (
86
+ <TableRow>
87
+ <StyledProgressCell colSpan={itemKeyList.length}>
88
+ <Grid container>
89
+ <Grid item xs={12}>
90
+ <StyledLinearProgress />
91
+ </Grid>
92
+ </Grid>
93
+ </StyledProgressCell>
94
+ </TableRow>
95
+ ) : null}
96
+ {visibleRows.map((row, index) => {
97
+ return (
98
+ <ExpandableRow
99
+ key={index}
100
+ expandableContent={expandableContent}
101
+ isExpand={expandMap[index]}
102
+ handleClick={handleClick}
103
+ row={row}
104
+ index={index}
105
+ itemKeyList={itemKeyList}
106
+ actionClick={actionClick}
107
+ showActions={showActions}
108
+ showExpandedContent={showExpandedContent}
109
+ />
110
+ );
111
+ })}
112
+ {emptyRows > 0 ? (
113
+ <StyledEmptyRow emptyRows={emptyRows}>
114
+ <TableCell colSpan={itemKeyList.length} />
115
+ </StyledEmptyRow>
116
+ ) : null}
117
+ </TableBody>
118
+ </StyledTable>
119
+ </StyledTableContainer>
120
+ <NsTablePagination
121
+ rowsPerPageOptions={rowsPerPageOptions}
122
+ count={items.length}
123
+ rowsPerPage={rowsPerPage}
124
+ page={page + 1}
125
+ onPageChange={handleChangePage}
126
+ />
127
+ </div>
128
+ );
129
+
130
+ function getEmptyRows() {
131
+ return page > 0 ? Math.max(0, (1 + page) * rowsPerPage - items.length) : 0;
132
+ }
133
+ }
@@ -0,0 +1,41 @@
1
+ import type { NsTableHeaderProps, Item } from './types';
2
+ import React from 'react';
3
+ import { TableHead, TableRow, Box, TableCell } from '@mui/material';
4
+ import { StyledTableSortLabel, StyledTableLabel } from './NsTable.styled';
5
+ import { visuallyHidden } from '@mui/utils';
6
+
7
+ export default function NsTableHeader(props: NsTableHeaderProps) {
8
+ const { order, orderBy, headCells, onRequestSort } = props;
9
+ const createSortHandler = (property: keyof Item) => (event: React.MouseEvent<unknown>) => {
10
+ onRequestSort(event, property);
11
+ };
12
+
13
+ return (
14
+ <TableHead>
15
+ <TableRow>
16
+ {headCells.map((headCell) =>
17
+ headCell.sortable ? (
18
+ <TableCell key={headCell.id} sortDirection={orderBy === headCell.id ? order : false}>
19
+ <StyledTableSortLabel
20
+ active={orderBy === headCell.id}
21
+ direction={orderBy === headCell.id ? order : 'asc'}
22
+ onClick={createSortHandler(headCell.id)}
23
+ >
24
+ {headCell.label}
25
+ {orderBy === headCell.id ? (
26
+ <Box component="span" sx={visuallyHidden}>
27
+ {order === 'desc' ? 'sorted descending' : 'sorted ascending'}
28
+ </Box>
29
+ ) : null}
30
+ </StyledTableSortLabel>
31
+ </TableCell>
32
+ ) : (
33
+ <TableCell key={headCell.id} sortDirection={false}>
34
+ <StyledTableLabel>{headCell.label}</StyledTableLabel>
35
+ </TableCell>
36
+ )
37
+ )}
38
+ </TableRow>
39
+ </TableHead>
40
+ );
41
+ }
@@ -0,0 +1,28 @@
1
+ import type { NsTablePaginationProps } from './types'
2
+ import React from 'react'
3
+ import { StyledPagination } from './NsTable.styled'
4
+
5
+ export default function NsTablePagination(props: NsTablePaginationProps) {
6
+ const {
7
+ count,
8
+ rowsPerPage,
9
+ page,
10
+ onPageChange,
11
+ } = props;
12
+
13
+ const totalPage = Math.ceil(count / rowsPerPage);
14
+ const handleChange = (event: React.ChangeEvent<unknown>, value: number) => {
15
+ onPageChange(value);
16
+ };
17
+
18
+ return (
19
+ <StyledPagination
20
+ count={totalPage}
21
+ page={page}
22
+ variant="outlined"
23
+ onChange={handleChange}
24
+ shape="rounded"
25
+ color="primary"
26
+ />
27
+ );
28
+ }
@@ -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';