@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,82 @@
1
+ type ContainedParams = {
2
+ backgroundColor: string;
3
+ textColor: string;
4
+ hovered: string;
5
+ pressed: string;
6
+ focused: string;
7
+ };
8
+
9
+ export function generateContainedStyle({
10
+ backgroundColor,
11
+ textColor,
12
+ hovered,
13
+ pressed,
14
+ focused,
15
+ }: ContainedParams): string {
16
+ return `
17
+ background-color: ${backgroundColor};
18
+ color: ${textColor} !important;
19
+ &:hover {
20
+ background-color: ${hovered};
21
+ }
22
+ &:active {
23
+ background-color: ${pressed};
24
+ }
25
+ &:focus {
26
+ background-color: ${focused};
27
+ }
28
+ `;
29
+ }
30
+ type OutlinedParams = {
31
+ borderColor: string;
32
+ hovered: string;
33
+ pressed: string;
34
+ activeColor: string;
35
+ };
36
+ export function generateOutlinedStyle({ borderColor, hovered, pressed, activeColor }: OutlinedParams) {
37
+ return `
38
+ border-color: ${borderColor};
39
+ color: ${borderColor};
40
+ &:hover {
41
+ border-color: ${hovered};
42
+ color: ${borderColor};
43
+ }
44
+ &:active {
45
+ border-color: ${pressed};
46
+ color: ${activeColor};
47
+ }
48
+ `;
49
+ }
50
+
51
+ type TextParams = {
52
+ underlineColor: string;
53
+ hovered: string;
54
+ pressed: string;
55
+ };
56
+
57
+ export function generateTextStyles({ underlineColor, hovered, pressed }: TextParams): string {
58
+ return `
59
+ text-decoration: underline 1px !important;
60
+ text-underline-offset: 4px;
61
+ padding: 0;
62
+ min-width: auto;
63
+ background-color: transparent !important;
64
+ text-decoration-color: ${underlineColor};
65
+ color: ${underlineColor};
66
+ &:hover {
67
+ color: ${hovered};
68
+ text-decoration-color: ${hovered};
69
+ }
70
+ &:active {
71
+ color: ${underlineColor};
72
+ text-decoration-color: ${pressed};
73
+ }
74
+ `;
75
+ }
76
+
77
+ export function generateIconOnlyStyles() {
78
+ return `
79
+ padding: 10px;
80
+ min-width: unset;
81
+ `;
82
+ }
@@ -1,2 +1,2 @@
1
1
  export { default as NsButton } from './NsButton';
2
- export type { NsButtonProps } from './types';
2
+ export type { NsButtonProps } from './types.d';
@@ -14,6 +14,9 @@ export type NsButtonProps = Pick<
14
14
  | 'onFocus'
15
15
  | 'aria-label'
16
16
  | 'className'
17
+ | 'startIcon'
18
+ | 'endIcon'
17
19
  > & {
18
20
  iconOnly?: boolean;
21
+ darkModeEnabled?: boolean;
19
22
  };
@@ -1,16 +1,22 @@
1
1
  import { NsNextImage, NsLink } from '../';
2
2
  import { NsFfgStyled } from './styled/NsFfgStyled';
3
- import { NsFfgCardProps } from './types';
3
+ import { NsFfgCardProps } from './types.d';
4
4
 
5
- const NsFfgCard = ({ actionText, actionLink, text, topImageUrl, topImageAlt, additionalProps }: NsFfgCardProps) => {
5
+ const NsFfgCard = ({ cardLink, text, topImageUrl, topImageAlt, additionalProps, cslp, onClick }: NsFfgCardProps) => {
6
6
  return (
7
- <NsFfgStyled data-testid={additionalProps?.testid}>
8
- <div className="top-image">
7
+ <NsFfgStyled
8
+ data-testid={additionalProps?.testid}
9
+ onClick={onClick}
10
+ className={additionalProps?.className ?? ''}
11
+ >
12
+ <header className="top-image">
9
13
  <NsNextImage height={192} width={288} alt={topImageAlt} src={topImageUrl} />
10
- </div>
11
- <div className="body-text">{text}</div>
12
- <NsLink className="action-link" href={actionLink}>
13
- {actionText || 'LEARN MORE'}
14
+ </header>
15
+ <article className="body-text" {...cslp?.card_text}>
16
+ {text}
17
+ </article>
18
+ <NsLink className="action-link" href={cardLink.href} additionalProps={cslp?.action_text}>
19
+ {cardLink.title || 'LEARN MORE'}
14
20
  </NsLink>
15
21
  </NsFfgStyled>
16
22
  );
@@ -0,0 +1,33 @@
1
+ import { render, screen, fireEvent } from '@testing-library/react';
2
+ import NsFfgCard from '../NsFfgCard';
3
+
4
+ describe('NsFfgCard component', () => {
5
+ const props = {
6
+ topImageUrl: 'https://media.nuskin.com/m/6245528b8f76ad32/webimage-brand-ageLOC.png',
7
+ topImageAlt: 'alt-text',
8
+ text: 'card text',
9
+ cardLink: { href: 'https://www.google.com', title: 'Test' },
10
+ onClick: jest.fn(),
11
+ };
12
+ it('1. renders with background image', () => {
13
+ render(<NsFfgCard {...props} additionalProps={{ testid: 'ffg-card' }} />);
14
+ const card = screen.getByTestId('ffg-card');
15
+ expect(card).toHaveStyle(`
16
+ background-color: #fff;
17
+ `);
18
+ });
19
+ it('2. renders with cover size', () => {
20
+ render(<NsFfgCard {...props} additionalProps={{ testid: 'ffg-card-1' }} />);
21
+ const card = screen.getByText(props.cardLink.title);
22
+ expect(card).toBeInTheDocument();
23
+ });
24
+ it('3. calls onclick', () => {
25
+ const handler = jest.fn();
26
+ const { getByTestId } = render(
27
+ <NsFfgCard {...props} onClick={handler} additionalProps={{ testid: 'ffg-card-1' }} />
28
+ );
29
+ const card = getByTestId('ffg-card-1');
30
+ fireEvent.click(card);
31
+ expect(handler).toHaveBeenCalled();
32
+ });
33
+ });
@@ -1,6 +1,6 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
2
  import { NsBgCard } from '../';
3
- import { withCenterDecorator } from '../../../stories/decorators/withCenterDecorator';
3
+ import { withCenterDecorator } from '@/stories/decorators/withCenterDecorator';
4
4
 
5
5
  type ComponentType = typeof NsBgCard;
6
6
  type Story = StoryObj<ComponentType>;
@@ -8,13 +8,11 @@ type MetaStory = Meta<ComponentType>;
8
8
 
9
9
  export default {
10
10
  component: NsBgCard,
11
- title: 'Components/NsCard/NsBgCard',
11
+ title: 'Components/Containers/Card/NsBgCard',
12
12
  argTypes: {},
13
13
  args: {
14
14
  title: 'ageLOC LumiSpa',
15
15
  backgroundImageUrl: 'https://media.nuskin.com/m/3604b5202b0b64c6/webimage-brand-lumispa-optweb.png',
16
- // brandImageUrl:
17
- // 'https://media.nuskin.com/m/2571a0407433a6e8/webimage-brand-lumispa.png',
18
16
  },
19
17
  decorators: [withCenterDecorator],
20
18
  } as MetaStory;
@@ -1,5 +1,5 @@
1
1
  import type { StoryObj, Meta } from '@storybook/react';
2
- import { withCenterDecorator } from '../../../stories/decorators/withCenterDecorator';
2
+ import { withCenterDecorator } from '@/stories/decorators/withCenterDecorator';
3
3
  import { NsBrandProductCard } from '../';
4
4
 
5
5
  type ComponentType = typeof NsBrandProductCard;
@@ -8,7 +8,7 @@ type MetaStory = Meta<ComponentType>;
8
8
 
9
9
  export default {
10
10
  component: NsBrandProductCard,
11
- title: 'Components/NsCard/NsBrandProductCard',
11
+ title: 'Components/Containers/Card/NsBrandProductCard',
12
12
  argTypes: {},
13
13
  decorators: [withCenterDecorator],
14
14
  } as MetaStory;
@@ -1,7 +1,7 @@
1
1
  import type { StoryObj, Meta } from '@storybook/react';
2
2
  import { within, userEvent } from '@storybook/testing-library';
3
3
  import { expect } from '@storybook/jest';
4
- import { withCenterDecorator } from '../../../stories/decorators/withCenterDecorator';
4
+ import { withCenterDecorator } from '@/stories/decorators/withCenterDecorator';
5
5
  import { NsFfgCard } from '../';
6
6
 
7
7
  type ComponentType = typeof NsFfgCard;
@@ -10,31 +10,64 @@ type MetaStory = Meta<ComponentType>;
10
10
 
11
11
  export default {
12
12
  component: NsFfgCard,
13
- title: 'Components/NsCard/NsFfgCard',
14
- argTypes: {},
13
+ title: 'Components/Containers/Card/NsFfgCard',
14
+ argTypes: {
15
+ onClick: {
16
+ action: 'clicked',
17
+ },
18
+ },
15
19
  decorators: [withCenterDecorator],
16
20
  } as MetaStory;
17
21
 
22
+ const text = `Every child deserves a chance to shine. Through our Nu Skin Force for Good Foundation,
23
+ we’re empowering children around the world with hope for a brighter future.`;
24
+ const host = 'https://images.contentstack.io/v3/assets';
25
+
18
26
  export const Default: Story = {
19
27
  args: {
20
- actionText: 'LEARN MORE',
21
- actionLink: 'https://www.forceforgood.org/',
22
- text: 'Every child deserves a chance to shine. Through our Nu Skin Force for Good Foundation, we’re empowering children around the world with hope for a brighter future.',
23
- topImageUrl:
24
- 'https://images.contentstack.io/v3/assets/blt594f30e2dc643eae/blt34cdb300dc9b93ff/645ccaa7520ba1a1af13a08a/nsffg-foundation.webp',
28
+ cardLink: {
29
+ href: 'https://www.forceforgood.org/',
30
+ title: 'LEARN MORE',
31
+ },
32
+ text,
33
+ topImageUrl: `${host}/blt594f30e2dc643eae/blt34cdb300dc9b93ff/645ccaa7520ba1a1af13a08a/nsffg-foundation.webp`,
34
+ topImageAlt: 'Force for Good Foundation',
35
+ additionalProps: {
36
+ testid: 'ffg-card',
37
+ },
38
+ onClick: () => {
39
+ console.log('onClick called');
40
+ },
41
+ },
42
+ play: async ({ canvasElement }: any) => {
43
+ const canvas = within(canvasElement);
44
+ userEvent.hover(canvas.getByTestId('ffg-card'));
45
+ userEvent.hover(canvas.getByRole('link'));
46
+ expect(canvas.getByText(text)).toBeInTheDocument();
47
+ },
48
+ };
49
+ const d = { count: -1 };
50
+ export const OnClick: Story = {
51
+ args: {
52
+ cardLink: {
53
+ href: 'https://www.forceforgood.org/',
54
+ title: 'LEARN MORE',
55
+ },
56
+ text,
57
+ topImageUrl: `${host}/blt594f30e2dc643eae/blt34cdb300dc9b93ff/645ccaa7520ba1a1af13a08a/nsffg-foundation.webp`,
25
58
  topImageAlt: 'Force for Good Foundation',
26
59
  additionalProps: {
27
60
  testid: 'ffg-card',
28
61
  },
62
+ onClick: () => {
63
+ d.count = 1;
64
+ console.log('on click called');
65
+ },
29
66
  },
30
- play: async ({ canvasElement }) => {
67
+ play: async ({ canvasElement }: any) => {
68
+ d.count = 0;
31
69
  const canvas = within(canvasElement);
32
- await userEvent.hover(canvas.getByTestId('ffg-card'));
33
- await userEvent.hover(canvas.getByRole('link'));
34
- await expect(
35
- canvas.getByText(
36
- 'Every child deserves a chance to shine. Through our Nu Skin Force for Good Foundation, we’re empowering children around the world with hope for a brighter future.'
37
- )
38
- ).toBeInTheDocument();
70
+ userEvent.click(canvas.getByTestId('ffg-card'));
71
+ expect(d.count).toEqual(1);
39
72
  },
40
73
  };
@@ -8,14 +8,6 @@ export const brandImages = [
8
8
  'https://media.nuskin.com/m/4bd7ab9b46bd456d/webimage-brand-pharmanex.png',
9
9
  'https://media.nuskin.com/m/501d638a8af80087/webimage-brand-ap24.png',
10
10
  'https://media.nuskin.com/m/f3a91129cbbae32/webimage-brand-nutricentials.png',
11
- 'https://media.nuskin.com/m/63a454ff90d038b4/webimage-brand-epoch.png',
12
- 'https://media.nuskin.com/m/3eb406f465d4b0fe/webimage-brand-sunright.png',
13
- 'https://media.nuskin.com/m/2d3276518912283b/webimage-brand-nu_colour.png',
14
- 'https://media.nuskin.com/m/3855d3836d920639/webimage-brand-nuskin180.png',
15
- 'https://media.nuskin.com/m/6245528b8f76ad32/webimage-brand-ageLOC.png',
16
- 'https://media.nuskin.com/m/2571a0407433a6e8/webimage-brand-lumispa.png',
17
- 'https://media.nuskin.com/m/4bd7ab9b46bd456d/webimage-brand-pharmanex.png',
18
- 'https://media.nuskin.com/m/501d638a8af80087/webimage-brand-ap24.png',
19
11
  ];
20
12
 
21
13
  export const brandBackImages = [
@@ -28,34 +20,18 @@ export const brandBackImages = [
28
20
  'https://media.nuskin.com/m/4a1245a63c595262/webimage-brand-pharmanex-optweb.png',
29
21
  'https://media.nuskin.com/m/14a0fd6ef63e5dbb/webimage-brand-ap_24.png',
30
22
  'https://media.nuskin.com/m/298104036e885b40/webimage-brand-nutricentials.png',
31
- 'https://media.nuskin.com/m/549aa3e5184434d8/webimage-brand-epoch-optweb.png',
32
- 'https://media.nuskin.com/m/14e238d7599e1811/webimage-brand-sunright.png',
33
- 'https://media.nuskin.com/m/2543e79419276727/webimage-brand-nu_colour-optweb.png',
34
- 'https://media.nuskin.com/m/446c7a2aad513f58/webimage-brand-nu_skin_180-optweb.png',
35
- 'https://media.nuskin.com/m/42911c8b05600476/webimage-brand-ageloc-optweb.png',
36
- 'https://media.nuskin.com/m/3604b5202b0b64c6/webimage-brand-lumispa-optweb.png',
37
- 'https://media.nuskin.com/m/4a1245a63c595262/webimage-brand-pharmanex-optweb.png',
38
- 'https://media.nuskin.com/m/14a0fd6ef63e5dbb/webimage-brand-ap_24.png',
39
23
  ];
40
24
 
41
25
  export const brandTitles = [
42
26
  'Epoch',
43
27
  'Sunright',
44
- 'Nu Colour',
28
+ 'Nu Color',
45
29
  '180 System',
46
30
  'ageLOC',
47
31
  'ageLOC LumiSpa',
48
32
  'Pharmanex',
49
33
  'AP 24',
50
34
  'Nutricentials',
51
- 'Epoch',
52
- 'Sunright',
53
- 'Nu Colour',
54
- '180 System',
55
- 'ageLOC',
56
- 'ageLOC LumiSpa',
57
- 'Pharmanex',
58
- 'AP 24',
59
35
  ];
60
36
  export const brandEntries = brandTitles.map((title, index) => {
61
37
  return {
@@ -1,8 +1,6 @@
1
1
  import { Box } from '@mui/material';
2
2
  import { styled } from '@nuskin/foundation-theme';
3
3
 
4
- const options = {};
5
-
6
4
  const Component = () => {
7
5
  return {
8
6
  backgroundClip: 'border-box',
@@ -10,9 +8,10 @@ const Component = () => {
10
8
  border: '1px solid #eff2f7',
11
9
  borderRadius: '1rem',
12
10
  boxShadow: '0 0.75rem 1.5rem rgba(18, 38, 63, .03)',
11
+ cursor: 'pointer',
13
12
  display: 'flex',
14
13
  flexDirection: 'column' as 'column', // https://github.com/cssinjs/jss/issues/1344
15
- marginBottom: '2rem',
14
+ marginBottom: '16px',
16
15
  transition: 'all .2s ease',
17
16
  textAlign: 'center' as 'center',
18
17
  wordWrap: 'break-word' as 'break-word',
@@ -25,12 +24,15 @@ const Component = () => {
25
24
  },
26
25
  },
27
26
  '.body-text': {
28
- padding: '0 1.5rem 3rem',
29
- fontSize: '1rem',
27
+ padding: '0 1.5rem 4rem',
28
+ fontSize: '16px',
30
29
  color: '#8492a6',
31
30
  },
32
31
  '.top-image': {
33
- padding: '1.5rem 3rem',
32
+ padding: '3rem 1.5rem',
33
+ img: {
34
+ maxWidth: '100%',
35
+ },
34
36
  },
35
37
  '.action-link': {
36
38
  color: '#3c4858',
@@ -41,4 +43,4 @@ const Component = () => {
41
43
  },
42
44
  };
43
45
  };
44
- export const NsFfgStyled = styled(Box, options)<{}>(Component);
46
+ export const NsFfgStyled = styled(Box)(Component);
@@ -1,9 +1,12 @@
1
- import { AdditionalProps } from '../common.types';
2
-
1
+ import { AdditionalProps, CslpTag } from '../common.types';
3
2
  export type NsFfgCardProps = AdditionalProps & {
4
3
  topImageUrl: string;
5
4
  topImageAlt: string;
6
5
  text: string;
7
- actionLink: string;
8
- actionText?: string;
6
+ cardLink: { href: string; title: string };
7
+ onClick(): void;
8
+ cslp?: {
9
+ card_text: CslpTag;
10
+ action_text: CslpTag;
11
+ };
9
12
  };
@@ -0,0 +1,61 @@
1
+ import React, { useMemo } from 'react';
2
+ import Slider from 'react-slick';
3
+ import { NsScrollingCarousalProps } from '../';
4
+ import { styled } from '@nuskin/foundation-theme';
5
+
6
+ const options = {
7
+ shouldForwardProp: (prop: string) => prop !== 'dotsBottomPixel',
8
+ };
9
+
10
+ const StyledDiv = styled(
11
+ 'div',
12
+ options
13
+ )<{
14
+ dotsBottomPixel?: number;
15
+ }>(({ dotsBottomPixel }) => {
16
+ return {
17
+ '.slick-dots': {
18
+ zIndex: 9,
19
+ bottom: `${dotsBottomPixel ?? -25}px`,
20
+ opacity: '0.5',
21
+ },
22
+ };
23
+ });
24
+
25
+ const NsScrollingCarousal = ({
26
+ slides,
27
+ scrollSeconds,
28
+ stillSeconds,
29
+ renderSlide,
30
+ settings,
31
+ dotsBottomPixel,
32
+ additionalProps,
33
+ }: NsScrollingCarousalProps) => {
34
+ const defaultSettings = useMemo(() => {
35
+ return {
36
+ ...settings,
37
+ autoplay: true,
38
+ autoplaySpeed: stillSeconds * 1000 || 2000, // autoplaySpeed = delay between scroll in milliseconds
39
+ accessibility: true,
40
+ adaptiveHeight: true,
41
+ arrows: true,
42
+ draggable: true,
43
+ dots: true,
44
+ infinite: true,
45
+ speed: scrollSeconds * 1000 || 500, // speed = animation speed in milliseconds
46
+ slidesToShow: 1,
47
+ slidesToScroll: 1,
48
+ swipeToSlide: true,
49
+ };
50
+ }, [stillSeconds, scrollSeconds, settings]);
51
+ return (
52
+ <StyledDiv
53
+ dotsBottomPixel={dotsBottomPixel}
54
+ data-testid={additionalProps?.testid ?? 'scrolling-carousal-test-id'}
55
+ >
56
+ <Slider {...defaultSettings}>{slides.map(renderSlide)}</Slider>
57
+ </StyledDiv>
58
+ );
59
+ };
60
+
61
+ export default NsScrollingCarousal;
@@ -1,2 +1,5 @@
1
1
  export { default as NsCarousal } from './NsCarousal';
2
+ export { default as NsScrollingCarousal } from './NsScrollingCarousal';
2
3
  export { default as NsDefaultCarousalSettings } from './slickSetting';
4
+
5
+ export type { NsCarousalProps, NsScrollingCarousalProps } from './types.d';
@@ -1,5 +1,5 @@
1
- import { render, screen, fireEvent } from '../../../../test-utils';
2
- import NsCarousal from '../NsCarousal';
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
+ });
@@ -1,5 +1,5 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
- import { NsCarousal } from '../';
2
+ import { NsCarousal } from '@/common/';
3
3
  import { brandEntries } from '../../card/stories/data';
4
4
  import { RenderBrand } from '../RenderBrand';
5
5
  import settings from '../slickSetting';
@@ -9,7 +9,7 @@ type Story = StoryObj<ComponentType>;
9
9
  type MetaStory = Meta<ComponentType>;
10
10
 
11
11
  export default {
12
- title: 'Components/NsCarousal/Brand',
12
+ title: 'Components/Containers/NsCarousal/Brand',
13
13
  component: NsCarousal,
14
14
  argTypes: {},
15
15
  } as MetaStory;
@@ -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/Containers/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 = {};
@@ -0,0 +1,23 @@
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
+ /* value in number, specifying how much the dots should be from bottom of slides container */
22
+ dotsBottomPixel?: number;
23
+ } & AdditionalProps;
@@ -1,5 +1,5 @@
1
1
  import { NsCartIcon } from './';
2
- import { render, screen } from '../../../test-utils';
2
+ import { render, screen } from '@/test-utils/index';
3
3
 
4
4
  const { getByTestId } = screen;
5
5
  describe('NsCartIcon', () => {
@@ -1,5 +1,5 @@
1
1
  import type { StoryObj, Meta } from '@storybook/react';
2
- import { withCenterDecorator } from '../../stories/decorators/withCenterDecorator';
2
+ import { withCenterDecorator } from '@/stories/decorators/withCenterDecorator';
3
3
  import { NsCartIcon } from './';
4
4
 
5
5
  type ComponentType = typeof NsCartIcon;
@@ -7,7 +7,7 @@ type Story = StoryObj<ComponentType>;
7
7
  type MetaStory = Meta<ComponentType>;
8
8
 
9
9
  export default {
10
- title: 'Components/NsCartIcon',
10
+ title: 'Components/Data Display/NsCartIcon',
11
11
  component: NsCartIcon,
12
12
  decorators: [withCenterDecorator],
13
13
  argTypes: {