@nuskin/foundation-ui-components 1.2.0 → 1.4.0

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 (55) hide show
  1. package/package.json +5 -5
  2. package/src/common/auth-dropdown/NsAuthDropdown.tsx +13 -9
  3. package/src/common/button/NsButton.stories.tsx +3 -2
  4. package/src/common/button/NsButton.tsx +27 -2
  5. package/src/common/button/types.d.ts +21 -17
  6. package/src/common/cart-icon/NsCartIcon.spec.tsx +3 -2
  7. package/src/common/cart-icon/NsCartIcon.stories.tsx +1 -1
  8. package/src/common/cart-icon/NsCartIcon.styled.tsx +14 -0
  9. package/src/common/cart-icon/NsCartIcon.tsx +1 -1
  10. package/src/common/cart-icon/types.d.ts +2 -2
  11. package/src/common/dropdown/NsDropdown.tsx +15 -11
  12. package/src/common/email-simple/NsEmailSimple.tsx +1 -1
  13. package/src/common/flag/NsFlag.spec.tsx +14 -2
  14. package/src/common/flag/NsFlag.styled.tsx +2 -5
  15. package/src/common/hooks/useOnClickOutside.tsx +14 -14
  16. package/src/common/icon/NsIcon.spec.tsx +21 -6
  17. package/src/common/icon/NsIcon.stories.tsx +2 -1
  18. package/src/common/icon/NsIcon.styled.tsx +13 -10
  19. package/src/common/icon/NsIcon.tsx +9 -6
  20. package/src/common/icon/NsIconVariants.ts +2 -0
  21. package/src/common/icon/icons/AlertErrorIcon.tsx +2 -1
  22. package/src/common/icon/icons/ArrowLeft.tsx +2 -2
  23. package/src/common/icon/icons/ArrowRight.tsx +2 -2
  24. package/src/common/icon/icons/CartBadge.tsx +2 -2
  25. package/src/common/icon/icons/Check.tsx +25 -0
  26. package/src/common/icon/icons/CloseIcon.tsx +1 -1
  27. package/src/common/icon/icons/ErrorIcon.tsx +3 -2
  28. package/src/common/icon/icons/SearchIcon.tsx +3 -2
  29. package/src/common/icon/icons/SuccessIcon.tsx +7 -1
  30. package/src/common/icon/icons/TrashIcon.tsx +2 -1
  31. package/src/common/icon/icons/UserIcon.tsx +8 -1
  32. package/src/common/icon/icons/UserOutline.tsx +4 -1
  33. package/src/common/icon/icons/WarningIcon.tsx +3 -2
  34. package/src/common/icon/types.d.ts +3 -2
  35. package/src/common/index.ts +8 -4
  36. package/src/common/progress/NsProgress.spec.tsx +2 -2
  37. package/src/common/progress/NsProgress.stories.tsx +10 -5
  38. package/src/common/progress/NsProgress.styled.tsx +30 -12
  39. package/src/common/progress/NsProgress.tsx +18 -16
  40. package/src/common/progress/types.d.ts +2 -2
  41. package/src/common/radiogroup/NsRadioGroup.spec.tsx +2 -2
  42. package/src/common/radiogroup/NsRadioGroup.stories.tsx +2 -2
  43. package/src/common/radiogroup/NsRadioGroup.tsx +5 -3
  44. package/src/common/radiogroup/types.d.ts +11 -12
  45. package/src/common/select/NsSelect.styled.tsx +38 -71
  46. package/src/common/select/NsSelect.tsx +86 -91
  47. package/src/common/select/NsSelectOption.tsx +10 -14
  48. package/src/common/select/specs/NsSelect.spec.tsx +183 -0
  49. package/src/common/select/specs/NsSelectOption.spec.tsx +32 -0
  50. package/src/common/select/stories/NsSelect.stories.tsx +25 -80
  51. package/src/common/select/stories/countries.ts +53 -0
  52. package/src/common/select/types.d.ts +21 -8
  53. package/src/common/table/NsTable.stories.tsx +1 -0
  54. package/src/common/cart-icon/NsCartIcon.styled.ts +0 -14
  55. package/src/common/select/NsSelect.spec.tsx +0 -274
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "@nuskin/foundation-ui-components",
3
- "version": "1.2.0",
3
+ "version": "1.4.0",
4
4
  "description": "It is a foundation library written in react, that provides common components to all UI pages",
5
- "private": false,
6
5
  "main": "src/common/index.ts",
7
6
  "repository": {
8
7
  "type": "git",
@@ -37,7 +36,7 @@
37
36
  "test:pattern": "jest --coverage --testNamePattern accordion/*",
38
37
  "test:watch": "jest --watch",
39
38
  "test:failed": "npx jest --onlyFailures",
40
- "test:coverage": "yarn test --coverage",
39
+ "test:coverage": "jest --coverage",
41
40
  "types:check": "tsc --pretty --noEmit"
42
41
  },
43
42
  "dependencies": {
@@ -47,7 +46,7 @@
47
46
  "@mui/material": "5.4.2",
48
47
  "@mui/utils": "^5.14.1",
49
48
  "@next/font": "13.2.4",
50
- "@nuskin/foundation-theme": "1.0.0-develop.5",
49
+ "@nuskin/foundation-theme": "^1.0.0",
51
50
  "framer-motion": "^10.8.5",
52
51
  "next": "13.2.4",
53
52
  "react": "18.2.0",
@@ -103,5 +102,6 @@
103
102
  "files": [
104
103
  "src/common"
105
104
  ],
106
- "readme": "./README.md"
105
+ "readme": "./README.md",
106
+ "packageManager": "yarn@3.6.3"
107
107
  }
@@ -25,27 +25,31 @@ const NsAuthDropdown = ({
25
25
  darkModeEnabled = true,
26
26
  }: NsAuthDropdownProps) => {
27
27
  const [isOpen, setIsOpen] = useState(false);
28
- const dropdowneRef = useRef<HTMLDivElement | null>(null);
28
+ const dropdownRef = useRef<HTMLDivElement | null>(null);
29
29
 
30
- const handleToggle = () => {
30
+ const handleToggle = useCallback(() => {
31
31
  setIsOpen(!isOpen);
32
- };
32
+ }, [isOpen]);
33
33
 
34
- useOnClickOutside(dropdowneRef, handleToggle);
34
+ const handleClose = useCallback(() => {
35
+ setIsOpen(false);
36
+ },[]);
35
37
 
36
- const closeDropdown = useCallback(() => {
38
+ useOnClickOutside(dropdownRef?.current, handleClose);
39
+
40
+ const handleOnMouseLeave = useCallback(() => {
37
41
  if (closeOnMouseLeave) {
38
- setIsOpen(false);
42
+ handleClose();
39
43
  }
40
- }, [closeOnMouseLeave]);
44
+ }, [closeOnMouseLeave, handleClose]);
41
45
 
42
46
  return (
43
- <AuthDropdownContainer ref={dropdowneRef}>
47
+ <AuthDropdownContainer ref={dropdownRef}>
44
48
  <AuthHead data-testid="auth-head" onClick={handleToggle} darkModeEnabled={darkModeEnabled}>
45
49
  <Button>{titleText}</Button>
46
50
  <NsIcon testId="chevron-icon" name={isOpen ? 'arrowUp' : 'arrowDown'} color="primary" />
47
51
  {isOpen ? (
48
- <div onMouseLeave={closeDropdown} className="auth-wrapper">
52
+ <div onMouseLeave={handleOnMouseLeave} className="auth-wrapper">
49
53
  <Triangle />
50
54
  <AuthDropdown>
51
55
  <SignInButton href={signInRedirectLink} data-testid="sign-in-btn">
@@ -6,7 +6,6 @@ import { withCenterDecorator } from '@/stories/decorators/withCenterDecorator';
6
6
  import { within } from '@storybook/testing-library';
7
7
  import { expect } from '@storybook/jest';
8
8
  import { nuskinTheme } from '@nuskin/foundation-theme';
9
-
10
9
  const { palette } = nuskinTheme;
11
10
 
12
11
  type ComponentType = typeof NsButton;
@@ -40,7 +39,9 @@ export default {
40
39
  },
41
40
  } as MetaStory;
42
41
 
43
- export const button: Story = {};
42
+ export const button: Story = {
43
+ args: {},
44
+ };
44
45
 
45
46
  export const IconOnlyButton: Story = {
46
47
  render: (args: any) => (
@@ -4,13 +4,38 @@ import { useTheme } from '@mui/material/styles';
4
4
  import StyledButton from './NsButton.styled';
5
5
 
6
6
  import { NsButtonProps } from './types.d';
7
+ import { NsIcon } from '../icon';
7
8
 
8
9
  const NsButton = ({ children, darkModeEnabled = true, ...props }: PropsWithChildren<NsButtonProps>) => {
9
- const { color } = props;
10
+ const { color, startIconName, endIconName, variant } = props;
10
11
  const { palette } = useTheme();
11
12
  const btnColor = color && palette?.[color] ? color : 'primary';
13
+ let iconColor = btnColor;
14
+ if (variant === 'contained') {
15
+ if (btnColor === 'secondary') {
16
+ iconColor = 'primary';
17
+ } else {
18
+ iconColor = 'secondary';
19
+ }
20
+ }
21
+ let startIcon = props.startIcon;
22
+ if (!startIcon && startIconName) {
23
+ startIcon = <NsIcon name={startIconName} color={iconColor} size={props.size} />;
24
+ }
25
+ let endIcon = props.endIcon;
26
+ if (!endIcon && endIconName) {
27
+ endIcon = <NsIcon name={endIconName} color={iconColor} size={props.size} />;
28
+ }
29
+
12
30
  return (
13
- <StyledButton {...props} color={btnColor} disableRipple darkModeEnabled={darkModeEnabled}>
31
+ <StyledButton
32
+ {...props}
33
+ startIcon={startIcon}
34
+ endIcon={endIcon}
35
+ color={btnColor}
36
+ disableRipple
37
+ darkModeEnabled={darkModeEnabled}
38
+ >
14
39
  {children}
15
40
  </StyledButton>
16
41
  );
@@ -1,22 +1,26 @@
1
1
  import { ButtonProps as MUIButtonProps } from '@mui/material';
2
+ import { NsIconProps } from '../icon';
2
3
 
3
4
  export type NsButtonProps = Pick<
4
- MUIButtonProps,
5
- | 'size'
6
- | 'variant'
7
- | 'disabled'
8
- | 'fullWidth'
9
- | 'color'
10
- | 'type'
11
- | 'onBlur'
12
- | 'onClick'
13
- | 'onChange'
14
- | 'onFocus'
15
- | 'aria-label'
16
- | 'className'
17
- | 'startIcon'
18
- | 'endIcon'
5
+ MUIButtonProps,
6
+ | 'aria-label'
7
+ | 'className'
8
+ | 'color'
9
+ | 'disabled'
10
+ | 'endIcon'
11
+ | 'fullWidth'
12
+ | 'href'
13
+ | 'onBlur'
14
+ | 'onClick'
15
+ | 'onChange'
16
+ | 'onFocus'
17
+ | 'size'
18
+ | 'startIcon'
19
+ | 'type'
20
+ | 'variant'
19
21
  > & {
20
- iconOnly?: boolean;
21
- darkModeEnabled?: boolean;
22
+ iconOnly?: boolean;
23
+ darkModeEnabled?: boolean;
24
+ startIconName?: NsIconProps['name'];
25
+ endIconName?: NsIconProps['name'];
22
26
  };
@@ -1,10 +1,11 @@
1
- import { NsCartIcon } from './';
2
1
  import { render, screen } from '@/test-utils/index';
3
2
 
3
+ import { NsCartIcon } from './';
4
+
4
5
  const { getByTestId } = screen;
5
6
  describe('NsCartIcon', () => {
6
7
  it('1. renders Cart icon when item count is 0', () => {
7
- render(<NsCartIcon itemCount={0} color="primary" size="large" />);
8
+ render(<NsCartIcon />);
8
9
  const cartIcon = getByTestId('cart-badge-icon');
9
10
  expect(cartIcon).toBeInTheDocument();
10
11
  });
@@ -19,7 +19,7 @@ export default {
19
19
  },
20
20
  },
21
21
  args: {
22
- itemCount: 5,
22
+ itemCount: 0,
23
23
  color: 'primary',
24
24
  size: 'large',
25
25
  },
@@ -0,0 +1,14 @@
1
+ import { Badge, Theme } from '@mui/material';
2
+ import { ColorUtils, styled, FoundationTheme } from '@nuskin/foundation-theme';
3
+
4
+ type ItemCountParams = {
5
+ theme?: Theme;
6
+ bgcolor: FoundationTheme.PaletteColors;
7
+ };
8
+ const { paletteColor } = ColorUtils;
9
+ export const StyledBadge = styled(Badge)<ItemCountParams>`
10
+ & .MuiBadge-badge {
11
+ background-color: ${({ bgcolor, theme }) => paletteColor(bgcolor)({ theme })};
12
+ color: ${({ bgcolor, theme }) => paletteColor(bgcolor, 'contrastText')({ theme })};
13
+ }
14
+ `;
@@ -4,7 +4,7 @@ import { NsCartIconProps } from './types.d';
4
4
 
5
5
  const NsCartIcon = ({ itemCount = 0, size = 'large', color = 'primary', maxItemCount = 999 }: NsCartIconProps) => {
6
6
  return (
7
- <StyledBadge badgeContent={itemCount} max={maxItemCount} bgcolor={color}>
7
+ <StyledBadge badgeContent={itemCount} max={maxItemCount} bgcolor={color} showZero>
8
8
  <NsIcon testId="cart-badge-icon" name="cart" size={size} color={color} />
9
9
  </StyledBadge>
10
10
  );
@@ -1,8 +1,8 @@
1
1
  import { FoundationTheme } from '@nuskin/foundation-theme';
2
2
 
3
3
  export type NsCartIconProps = {
4
- itemCount: number;
4
+ itemCount?: number;
5
5
  size?: 'small' | 'medium' | 'large' | 'xLarge';
6
6
  color?: FoundationTheme.PaletteColors;
7
- maxItemCount?:number;
7
+ maxItemCount?: number;
8
8
  };
@@ -1,4 +1,4 @@
1
- import React, { useRef, useState } from 'react';
1
+ import React, { useCallback, useRef, useState } from 'react';
2
2
 
3
3
  import { DropdownContainer, DropdownButton, DropdownList, DropdownHead } from './NsDropdown.styled';
4
4
  import { NsIcon } from '../icon';
@@ -19,20 +19,24 @@ const NsDropdown: React.FC<DropdownProps> = ({
19
19
  }) => {
20
20
  const [isOpen, setIsOpen] = useState(false);
21
21
  const [value, setValue] = useState(selectedValue || '');
22
- const dropdowneRef = useRef<HTMLDivElement | null>(null);
22
+ const dropdownRef = useRef<HTMLDivElement | null>(null);
23
23
 
24
- const handleToggle = () => {
24
+ const handleToggle = useCallback(() => {
25
25
  if (disabled) return;
26
- setIsOpen(!isOpen);
27
- };
26
+ setIsOpen((x) => !x);
27
+ }, [disabled]);
28
+
29
+ const handleClose = useCallback(() => {
30
+ setIsOpen(false);
31
+ }, []);
28
32
 
29
- useOnClickOutside(dropdowneRef, handleToggle);
33
+ useOnClickOutside(dropdownRef?.current, handleClose);
30
34
 
31
- const closeDropdown = () => {
35
+ const handleOnMouseLeave = useCallback(() => {
32
36
  if (closeOnMouseLeave) {
33
- setIsOpen(false);
37
+ handleClose();
34
38
  }
35
- };
39
+ }, [closeOnMouseLeave, handleClose]);
36
40
 
37
41
  const handleSelect = (input: string) => {
38
42
  onSelect(input);
@@ -41,7 +45,7 @@ const NsDropdown: React.FC<DropdownProps> = ({
41
45
  };
42
46
 
43
47
  return (
44
- <DropdownContainer disabled={disabled} ref={dropdowneRef}>
48
+ <DropdownContainer disabled={disabled} ref={dropdownRef}>
45
49
  <DropdownHead data-testid="dropdown-head" disabled={disabled} type={type} onClick={handleToggle}>
46
50
  <DropdownButton>{selectedLabel || placeholder}</DropdownButton>
47
51
  <NsIcon testId="chevron-icon" name={isOpen ? 'arrowUp' : 'arrowDown'} color="primary" />
@@ -49,7 +53,7 @@ const NsDropdown: React.FC<DropdownProps> = ({
49
53
  {isOpen ? (
50
54
  <DropdownList
51
55
  data-testid="dropdown-list"
52
- onMouseLeave={closeDropdown}
56
+ onMouseLeave={handleOnMouseLeave}
53
57
  borderColor={dropdownBorderColor}
54
58
  >
55
59
  {React.Children.map(children, (child) => {
@@ -43,7 +43,7 @@ const NsEmailSimple = (props: NsEmailSimpleProps) => {
43
43
  errorMessageValue = '';
44
44
  }
45
45
  } catch (error) {
46
- console.log('API error', error);
46
+ console.error('API error', error);
47
47
  }
48
48
  } else {
49
49
  //TODO What happens when user does not pass valid checkEmail function
@@ -1,10 +1,10 @@
1
+ import { render } from '@/test-utils/index';
1
2
  import React from 'react';
2
3
 
3
- import { render } from '@/test-utils/index';
4
4
  import { NsFlag } from '../';
5
5
 
6
6
  describe('FlagComponent', () => {
7
- it('renders a div element with background color and text', () => {
7
+ it('1. renders a div element with background color and text', () => {
8
8
  const text = 'NU SKIN';
9
9
  const { getByText } = render(<NsFlag message="NU SKIN" color="accentColorA" />);
10
10
  const divElement = getByText(text);
@@ -12,4 +12,16 @@ describe('FlagComponent', () => {
12
12
  expect(divElement).toBeInTheDocument();
13
13
  expect(divElement).toHaveTextContent(text);
14
14
  });
15
+ it('2. should render a flag with default size, color, and testId when only message prop is provided', () => {
16
+ const props = {
17
+ message: 'Test Message',
18
+ };
19
+ const { getByTestId } = render(<NsFlag {...props} />);
20
+ const flag = getByTestId('ns-flag-component');
21
+ expect(flag).toBeInTheDocument();
22
+ expect(flag).toHaveStyle('height: 20px');
23
+ expect(flag).toHaveStyle('color: #ffffff');
24
+ expect(flag).toHaveStyle('background: #f56767');
25
+ expect(flag).toHaveTextContent(props.message);
26
+ });
15
27
  });
@@ -27,7 +27,7 @@ const FlagHeightMap = {
27
27
  };
28
28
 
29
29
  const getFlagHeight = ({ $size }: { $size: NsFlagSize }) => {
30
- return FlagHeightMap[$size] || FlagHeightMap['small' as NsFlagSize];
30
+ return FlagHeightMap[$size];
31
31
  };
32
32
 
33
33
  const makeFlagSize = ({ $size }: { $size: NsFlagSize }) => {
@@ -36,10 +36,7 @@ const makeFlagSize = ({ $size }: { $size: NsFlagSize }) => {
36
36
  };
37
37
 
38
38
  const makeFlagBorder = ({ $size, $bgColor = 'accentColorA', theme }: NsFlagThemeParams) => {
39
- if (theme) {
40
- return `${makeFlagSize({ $size })}px solid ${paletteColor($bgColor)({ theme })}`;
41
- }
42
- return '';
39
+ return `${makeFlagSize({ $size })}px solid ${paletteColor($bgColor)({ theme })}`;
43
40
  };
44
41
 
45
42
  export const StyledFlag = styled('span')<NsFlagThemeParams>`
@@ -1,25 +1,25 @@
1
- import { RefObject, useEffect } from 'react';
1
+ import { useEffect } from 'react';
2
2
 
3
3
  export type Handler = () => void;
4
4
 
5
- export function useOnClickOutside<T extends HTMLElement = HTMLElement>(
6
- ref: RefObject<T>,
7
- handler: Handler,
5
+ export function useOnClickOutside(
6
+ element: HTMLDivElement | null,
7
+ handler: Handler = () => {},
8
8
  mouseEvent: 'click' | 'mousedown' | 'mouseup' = 'click'
9
9
  ): void {
10
- const handleEventListener = (event: MouseEvent) => {
11
- const el = ref?.current;
12
- if (!el || el.contains(event.target as Node)) {
13
- return;
14
- }
15
- handler();
16
- };
17
10
  useEffect(() => {
11
+ const eventListener = (event: MouseEvent) => {
12
+ // Do nothing if clicking ref's element or descendent elements
13
+ if (!element || element.contains(event.target as Node)) {
14
+ return;
15
+ }
16
+ handler?.();
17
+ };
18
18
  if (document) {
19
- document.addEventListener(mouseEvent, handleEventListener);
19
+ document.addEventListener(mouseEvent, eventListener);
20
20
  return () => {
21
- document.removeEventListener(mouseEvent, handleEventListener);
21
+ document.removeEventListener(mouseEvent, eventListener);
22
22
  };
23
23
  }
24
- }, []);
24
+ }, [mouseEvent, handler, element]);
25
25
  }
@@ -1,31 +1,33 @@
1
- import React from 'react';
2
1
  import { render, screen } from '@/test-utils/index';
2
+ import { fireEvent } from '@storybook/testing-library';
3
+ import React from 'react';
4
+
3
5
  import { NsIcon, NsIconNameType, NsIconVariants } from './';
4
6
 
5
7
  describe('NsIcon Component', () => {
6
- it('renders cartBadge icon with custom size and color', () => {
7
- const { getByTestId } = render(<NsIcon name="cart" size="medium" color="secondary" />);
8
+ it('1. renders cartBadge icon with custom size and color', () => {
9
+ const { getByTestId } = render(<NsIcon name="cart" size={'medium'} color="secondary" />);
8
10
  const icon = getByTestId('icon');
9
11
  const svgIcon = icon.querySelector('svg');
10
12
  // expect(svgIcon).toHaveClass('MuiSvgIcon-colorSecondary');
11
13
  expect(svgIcon).toHaveClass('MuiSvgIcon-fontSizeMedium');
12
14
  });
13
15
 
14
- it('renders with testId', () => {
16
+ it('2. renders with testId', () => {
15
17
  Object.keys(NsIconVariants).forEach((iconName) => {
16
18
  render(<NsIcon name={iconName as NsIconNameType} />);
17
19
  const icon = screen.getByTestId(iconName);
18
20
  expect(icon).toBeInTheDocument();
19
21
  });
20
22
  });
21
- it('renders with custom testId', () => {
23
+ it('3. renders with custom testId', () => {
22
24
  const { getByTestId } = render(<NsIcon name="cart" testId="custom-icon" />);
23
25
  const icon = getByTestId('custom-icon');
24
26
  expect(icon).toBeInTheDocument();
25
27
  expect(icon.innerHTML).toContain('svg');
26
28
  });
27
29
 
28
- it('throws an error if invalid icon name is provided', () => {
30
+ it('4. throws an error if invalid icon name is provided', () => {
29
31
  const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
30
32
  // @ts-ignore
31
33
  const { queryByTestId } = render(<NsIcon name="invalidIcon" />);
@@ -33,4 +35,17 @@ describe('NsIcon Component', () => {
33
35
  expect(consoleErrorSpy).not.toHaveBeenCalled();
34
36
  consoleErrorSpy.mockRestore();
35
37
  });
38
+ it('5. renders default color of alertErrorIcon', () => {
39
+ const { getByTestId } = render(<NsIcon name="alertError" size={'medium'} />);
40
+ const icon = getByTestId('alertError');
41
+ expect(icon).toBeInTheDocument();
42
+ });
43
+ it('6. calls onClick event handler', () => {
44
+ const onClick = jest.fn();
45
+ const { getByTestId } = render(<NsIcon name="alertError" size="medium" onClick={onClick} />);
46
+ const icon = getByTestId('alertError');
47
+ expect(icon).toBeInTheDocument();
48
+ fireEvent.click(icon);
49
+ expect(onClick).toHaveBeenCalled();
50
+ });
36
51
  });
@@ -1,3 +1,4 @@
1
+ import { PaletteColors } from '@nuskin/foundation-theme';
1
2
  import type { StoryObj, Meta } from '@storybook/react';
2
3
  import { withCenterDecorator } from '@/stories/decorators/withCenterDecorator';
3
4
  import { NsIcon, NsIconVariants } from './';
@@ -18,7 +19,7 @@ export default {
18
19
  },
19
20
  color: {
20
21
  control: 'select',
21
- options: ['primary', 'secondary', 'success', 'error', 'warning', 'info'],
22
+ options: PaletteColors,
22
23
  },
23
24
  colorOverride: {
24
25
  control: 'color',
@@ -1,19 +1,22 @@
1
1
  import { styled } from '@nuskin/foundation-theme';
2
2
  import { NsIconSizeType } from './types.d';
3
3
 
4
- const iconSize = {
4
+ export const iconSize: Record<NsIconSizeType, string> = {
5
5
  small: '16px',
6
6
  medium: '20px',
7
7
  large: '24px',
8
8
  xLarge: '30px',
9
9
  };
10
+ type IconWrapperType = { size: NsIconSizeType };
10
11
 
11
- export const IconContainer = styled.div<{ size: NsIconSizeType }>`
12
- display: flex;
13
- place-content: center;
14
- place-items: center;
15
- svg {
16
- width: ${({ size }) => iconSize[size]};
17
- height: ${({ size }) => iconSize[size]};
18
- }
19
- `;
12
+ export const IconWrapper = styled('div')<IconWrapperType>(({ size }) => {
13
+ return {
14
+ display: 'flex',
15
+ placeContent: 'center',
16
+ placeItems: 'center',
17
+ svg: {
18
+ width: iconSize[size],
19
+ height: iconSize[size],
20
+ },
21
+ };
22
+ });
@@ -1,19 +1,22 @@
1
1
  import { useTheme } from '@mui/material';
2
2
  import { ColorUtils } from '@nuskin/foundation-theme';
3
- import { IconContainer } from './NsIcon.styled';
3
+
4
+ import { IconWrapper } from './NsIcon.styled';
4
5
  import IconVariants from './NsIconVariants';
5
- import { NsIconProps } from './types.d';
6
+ import { NsIconNameType, NsIconProps } from './types.d';
6
7
 
7
8
  const { paletteColor } = ColorUtils;
9
+
8
10
  const NsIcon = ({
9
11
  name,
10
- size = 'large',
12
+ size,
11
13
  color = 'primary',
12
14
  testId = 'icon',
13
15
  className,
14
16
  colorOverride,
17
+ onClick = () => {},
15
18
  }: NsIconProps) => {
16
- const Icon = IconVariants[name];
19
+ const Icon = IconVariants[name as NsIconNameType];
17
20
  const theme = useTheme();
18
21
  const iconColor = paletteColor(color)({ theme });
19
22
  if (!Icon) {
@@ -21,9 +24,9 @@ const NsIcon = ({
21
24
  }
22
25
 
23
26
  return (
24
- <IconContainer data-testid={testId} size={size} className={className}>
27
+ <IconWrapper data-testid={testId} size={size || 'large'} className={className} onClick={onClick}>
25
28
  <Icon color={colorOverride ? colorOverride : (iconColor as any)} />
26
- </IconContainer>
29
+ </IconWrapper>
27
30
  );
28
31
  };
29
32
 
@@ -20,6 +20,7 @@ import CloseIcon from './icons/CloseIcon';
20
20
  import UserIcon from './icons/UserIcon';
21
21
  import HamburgerIcon from './icons/HamburgerIcon';
22
22
  import UserOutline from './icons/UserOutline';
23
+ import Check from './icons/Check';
23
24
 
24
25
  const IconVariants = {
25
26
  arrowDown: ArrowDown,
@@ -30,6 +31,7 @@ const IconVariants = {
30
31
  cart: Cart,
31
32
  cartBadge: CartBadge,
32
33
  close: CloseIcon,
34
+ check: Check,
33
35
  checkShield: CheckShield,
34
36
  checkVerified: CheckVerified,
35
37
  error: ErrorIcon,
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable max-len */
2
2
  import SvgIcon, { SvgIconProps } from '@mui/material/SvgIcon';
3
+
3
4
  /**
4
5
  *
5
6
  * @param props { fill: color to be filled for icon, color: color of the tick icon}
@@ -24,7 +25,7 @@ const AlertErrorIcon = (props: SvgIconProps) => {
24
25
  15.5143276 0.328282319,15.6093523 0.505163987,15.6123832 L17.5120236,15.6123832 C17.6889052,15.6093523 17.8513135,15.5143276 17.940195,15.3618609 C18.0290766,
25
26
  15.2093943 18.0314841,15.0216954 17.9465423,14.8670135 Z"
26
27
  id="Shape"
27
- fill={props.color || '#B2140A'}
28
+ fill={props.color}
28
29
  fillRule="nonzero"
29
30
  ></path>
30
31
  <path
@@ -1,4 +1,4 @@
1
- import { SvgIconProps, SvgIcon } from '@mui/material';
1
+ import { SvgIcon, SvgIconProps } from '@mui/material';
2
2
 
3
3
  const ArrowLeft = (props: SvgIconProps) => {
4
4
  return (
@@ -19,7 +19,7 @@ const ArrowLeft = (props: SvgIconProps) => {
19
19
  strokeLinecap="round"
20
20
  strokeLinejoin="round"
21
21
  >
22
- <g transform="translate(-196, -226)" stroke={props.color || '#000'}>
22
+ <g transform="translate(-196, -226)" stroke={props.color}>
23
23
  <polyline
24
24
  // eslint-disable-next-line max-len
25
25
  transform="translate(209.000000, 237.500000) scale(-1.2, 1.2) rotate(90.000000) translate(-209.000000, -237.500000)"
@@ -1,4 +1,4 @@
1
- import { SvgIconProps, SvgIcon } from '@mui/material';
1
+ import { SvgIcon, SvgIconProps } from '@mui/material';
2
2
 
3
3
  export const ArrowRight = (props: SvgIconProps) => {
4
4
  return (
@@ -19,7 +19,7 @@ export const ArrowRight = (props: SvgIconProps) => {
19
19
  strokeLinecap="round"
20
20
  strokeLinejoin="round"
21
21
  >
22
- <g transform="translate(-196, -226)" stroke={props.color || '#000'}>
22
+ <g transform="translate(-196, -226)" stroke={props.color}>
23
23
  <polyline
24
24
  // eslint-disable-next-line max-len
25
25
  transform="translate(209.000000, 237.500000) scale(-1.2, 1.2) rotate(-90.000000) translate(-209.000000, -237.500000)"
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable max-len */
2
2
 
3
- import { SvgIconProps, SvgIcon } from '@mui/material';
3
+ import { SvgIcon, SvgIconProps } from '@mui/material';
4
4
 
5
5
  const CartBadge = (props: SvgIconProps) => {
6
6
  return (
@@ -20,7 +20,7 @@ const CartBadge = (props: SvgIconProps) => {
20
20
  width="30px"
21
21
  height="30px"
22
22
  >
23
- <g id="Group" transform="translate(0.000000, 0.500000)" stroke={props.color || 'currentColor'}>
23
+ <g id="Group" transform="translate(0.000000, 0.500000)" stroke={props.color}>
24
24
  <circle id="Oval" cx="11" cy="21.5" r="1.5"></circle>
25
25
  <circle id="Oval" cx="23" cy="21.5" r="1.5"></circle>
26
26
  <polyline