@lunit/oui 1.0.1-alpha.13 → 1.0.1-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/dist/index.js +0 -1
  2. package/dist/types/index.d.ts +0 -1
  3. package/package.json +7 -20
  4. package/src/assets/ic-bell-noti-outlined-20px.tsx +21 -0
  5. package/src/assets/ic-close-large-outlined-20px.tsx +17 -0
  6. package/src/assets/ic-close-small-outlined-20px.tsx +17 -0
  7. package/src/assets/ic-download-pdf-outlined-20px.tsx +18 -0
  8. package/src/assets/ic-ellipse-outlined-20px.tsx +17 -0
  9. package/src/assets/ic-filter-noti-outlined-20px.tsx +21 -0
  10. package/src/assets/ic-hide-large-outlined-20px.tsx +13 -0
  11. package/src/assets/ic-hide-small-outlined-20px.tsx +17 -0
  12. package/src/assets/ic-information-large-outlined-20px.tsx +17 -0
  13. package/src/assets/ic-information-small-outlined-20px.tsx +17 -0
  14. package/src/assets/ic-manufacturer-outlined-20px.tsx +19 -0
  15. package/src/assets/ic-rectangle-outlined-20px.tsx +17 -0
  16. package/src/assets/ic-refresh-left-outlined-20px.tsx +17 -0
  17. package/src/assets/ic-refresh-right-outlined-20px.tsx +13 -0
  18. package/src/assets/ic-show-large-outlined-20px.tsx +17 -0
  19. package/src/assets/ic-show-small-outlined-20px.tsx +17 -0
  20. package/src/assets/ic_bell_noti=outlined_20px.svg +5 -0
  21. package/src/assets/ic_close_large=outlined_20px.svg +4 -0
  22. package/src/assets/ic_close_small=outlined_20px.svg +4 -0
  23. package/src/assets/ic_download_pdf=outlined_20px.svg +7 -0
  24. package/src/assets/ic_ellipse=outlined_20px.svg +4 -0
  25. package/src/assets/ic_filter_noti=outlined_20px.svg +5 -0
  26. package/src/assets/ic_hide_large=outlined_20px.svg +4 -0
  27. package/src/assets/ic_hide_small=outlined_20px.svg +4 -0
  28. package/src/assets/ic_information_large=outlined_20px.svg +4 -0
  29. package/src/assets/ic_information_small=outlined_20px.svg +4 -0
  30. package/src/assets/ic_manufacturer=outlined_20px.svg +3 -0
  31. package/src/assets/ic_rectangle=outlined_20px.svg +4 -0
  32. package/src/assets/ic_refresh_left=outlined_20px.svg +4 -0
  33. package/src/assets/ic_refresh_right=outlined_20px.svg +4 -0
  34. package/src/assets/ic_show_large=outlined_20px.svg +4 -0
  35. package/src/assets/ic_show_small=outlined_20px.svg +4 -0
  36. package/src/assets/index.ts +16 -0
  37. package/src/components/Alert/Alert.styled.ts +44 -0
  38. package/src/components/Alert/Alert.tsx +39 -0
  39. package/src/components/Alert/Alert.types.ts +5 -0
  40. package/src/components/Alert/Alert.utils.tsx +43 -0
  41. package/src/components/Alert/index.ts +5 -0
  42. package/src/components/BaseTextField/BaseTextField.styled.ts +110 -0
  43. package/src/components/BaseTextField/BaseTextField.types.ts +25 -0
  44. package/src/components/BaseTextField/BaseTextField.utils.ts +10 -0
  45. package/src/components/Button/BaseButton.tsx +19 -0
  46. package/src/components/Button/Button.tsx +117 -0
  47. package/src/components/Button/Button.types.ts +36 -0
  48. package/src/components/Button/Button.utils.ts +13 -0
  49. package/src/components/Button/index.ts +6 -0
  50. package/src/components/Button/styleds/BaseButton.styled.ts +57 -0
  51. package/src/components/Button/styleds/ContainedButton.styled.ts +123 -0
  52. package/src/components/Button/styleds/GhostButton.styled.ts +139 -0
  53. package/src/components/Button/styleds/IconButton.styled.ts +25 -0
  54. package/src/components/Button/styleds/OutlinedButton.styled.ts +144 -0
  55. package/src/components/Card/Card.styled.tsx +18 -0
  56. package/src/components/Card/Card.tsx +18 -0
  57. package/src/components/Card/Card.types.ts +10 -0
  58. package/src/components/Card/index.ts +5 -0
  59. package/src/components/Checkbox/Checkbox.styled.tsx +27 -0
  60. package/src/components/Checkbox/Checkbox.tsx +64 -0
  61. package/src/components/Checkbox/Checkbox.types.ts +16 -0
  62. package/src/components/Checkbox/Checkbox.utils.tsx +42 -0
  63. package/src/components/Checkbox/index.ts +5 -0
  64. package/src/components/Chip/Chip.styled.ts +120 -0
  65. package/src/components/Chip/Chip.tsx +33 -0
  66. package/src/components/Chip/Chip.types.ts +18 -0
  67. package/src/components/Chip/Chip.utils.tsx +50 -0
  68. package/src/components/Chip/index.ts +4 -0
  69. package/src/components/DataTable/DataTable.styled.ts +66 -0
  70. package/src/components/DataTable/DataTable.tsx +29 -0
  71. package/src/components/DataTable/index.ts +1 -0
  72. package/src/components/DatePicker/DatePicker.styled.ts +19 -0
  73. package/src/components/DatePicker/DatePicker.tsx +194 -0
  74. package/src/components/DatePicker/DatePicker.types.ts +8 -0
  75. package/src/components/DatePicker/index.ts +4 -0
  76. package/src/components/Dialog/Dialog.styled.ts +87 -0
  77. package/src/components/Dialog/Dialog.tsx +111 -0
  78. package/src/components/Dialog/Dialog.types.ts +19 -0
  79. package/src/components/Dialog/index.ts +5 -0
  80. package/src/components/Divider/Divider.styled.ts +24 -0
  81. package/src/components/Divider/Divider.tsx +13 -0
  82. package/src/components/Divider/Divider.types.ts +7 -0
  83. package/src/components/Divider/index.ts +5 -0
  84. package/src/components/Dropdown/Dropdown.styled.tsx +127 -0
  85. package/src/components/Dropdown/Dropdown.tsx +116 -0
  86. package/src/components/Dropdown/Dropdown.types.ts +31 -0
  87. package/src/components/Dropdown/Dropdown.utils.ts +13 -0
  88. package/src/components/Dropdown/DropdownItem.styled.tsx +66 -0
  89. package/src/components/Dropdown/DropdownItem.tsx +45 -0
  90. package/src/components/Dropdown/DropdownItem.types.ts +14 -0
  91. package/src/components/Dropdown/DropdownItem.utils.ts +14 -0
  92. package/src/components/Dropdown/DropdownSubtitle.styled.ts +13 -0
  93. package/src/components/Dropdown/DropdownSubtitle.tsx +9 -0
  94. package/src/components/Dropdown/DropdownSubtitle.types.ts +6 -0
  95. package/src/components/Dropdown/IconDropdown.styled.tsx +82 -0
  96. package/src/components/Dropdown/IconDropdown.tsx +56 -0
  97. package/src/components/Dropdown/IconDropdown.types.ts +22 -0
  98. package/src/components/Dropdown/index.ts +22 -0
  99. package/src/components/FileDnDZone/FileDnDZone.styled.ts +43 -0
  100. package/src/components/FileDnDZone/FileDnDZone.tsx +81 -0
  101. package/src/components/FileDnDZone/FileDnDZone.types.ts +14 -0
  102. package/src/components/FileDnDZone/FileDnDZone.utils.ts +3 -0
  103. package/src/components/FileDnDZone/index.ts +5 -0
  104. package/src/components/List/List.styled.ts +31 -0
  105. package/src/components/List/List.tsx +71 -0
  106. package/src/components/List/List.types.ts +24 -0
  107. package/src/components/List/List.utils.ts +14 -0
  108. package/src/components/List/ListItem.styled.tsx +61 -0
  109. package/src/components/List/ListItem.tsx +66 -0
  110. package/src/components/List/ListItem.types.ts +40 -0
  111. package/src/components/List/ListItemCaption.styled.tsx +7 -0
  112. package/src/components/List/ListItemCaption.tsx +18 -0
  113. package/src/components/List/ListItemCaption.types.ts +2 -0
  114. package/src/components/List/index.ts +8 -0
  115. package/src/components/LoadingIndicator/LoadingIndicator.styled.tsx +40 -0
  116. package/src/components/LoadingIndicator/LoadingIndicator.tsx +44 -0
  117. package/src/components/LoadingIndicator/LoadingIndicator.types.ts +7 -0
  118. package/src/components/LoadingIndicator/assets/DnaLoadingAnimation.json +769 -0
  119. package/src/components/LoadingIndicator/assets/DotLoadingAnimation.json +426 -0
  120. package/src/components/LoadingIndicator/index.ts +5 -0
  121. package/src/components/Menu/Menu.styled.tsx +42 -0
  122. package/src/components/Menu/Menu.tsx +28 -0
  123. package/src/components/Menu/Menu.types.ts +18 -0
  124. package/src/components/Menu/MenuItem.styled.ts +62 -0
  125. package/src/components/Menu/MenuItem.tsx +45 -0
  126. package/src/components/Menu/MenuItem.types.ts +14 -0
  127. package/src/components/Menu/index.ts +5 -0
  128. package/src/components/MuiCssBaseline.ts +78 -0
  129. package/src/components/MuiInputBase.ts +25 -0
  130. package/src/components/MuiOutlinedInput.ts +57 -0
  131. package/src/components/MuiTextField.ts +17 -0
  132. package/src/components/Pagination/Pagination.styled.tsx +71 -0
  133. package/src/components/Pagination/Pagination.tsx +182 -0
  134. package/src/components/Pagination/Pagination.types.ts +39 -0
  135. package/src/components/Pagination/index.ts +2 -0
  136. package/src/components/ProductLabel/ProductLabel.styled.ts +61 -0
  137. package/src/components/ProductLabel/ProductLabel.tsx +57 -0
  138. package/src/components/ProductLabel/ProductLabel.types.ts +10 -0
  139. package/src/components/ProductLabel/index.ts +5 -0
  140. package/src/components/Progress/CircularProgress.styled.ts +10 -0
  141. package/src/components/Progress/CircularProgress.tsx +15 -0
  142. package/src/components/Progress/CircularProgress.types.ts +6 -0
  143. package/src/components/Progress/LinearProgress.styled.ts +15 -0
  144. package/src/components/Progress/LinearProgress.tsx +16 -0
  145. package/src/components/Progress/LinearProgress.types.ts +7 -0
  146. package/src/components/Progress/index.ts +4 -0
  147. package/src/components/Radio/Radio.styled.ts +35 -0
  148. package/src/components/Radio/Radio.tsx +60 -0
  149. package/src/components/Radio/Radio.types.ts +15 -0
  150. package/src/components/Radio/RadioGroup.styled.ts +6 -0
  151. package/src/components/Radio/RadioGroup.tsx +23 -0
  152. package/src/components/Radio/RadioGroup.types.ts +10 -0
  153. package/src/components/Radio/index.ts +7 -0
  154. package/src/components/Stepper/Stepper.styled.ts +38 -0
  155. package/src/components/Stepper/Stepper.tsx +24 -0
  156. package/src/components/Stepper/Stepper.types.ts +13 -0
  157. package/src/components/Stepper/index.ts +5 -0
  158. package/src/components/TabbedPanel/TabbedPanel.styled.ts +129 -0
  159. package/src/components/TabbedPanel/TabbedPanel.tsx +70 -0
  160. package/src/components/TabbedPanel/TabbedPanel.types.ts +36 -0
  161. package/src/components/TabbedPanel/TabbedPanel.utils.ts +21 -0
  162. package/src/components/TabbedPanel/index.ts +5 -0
  163. package/src/components/TextField/TextArea.styled.tsx +36 -0
  164. package/src/components/TextField/TextArea.tsx +35 -0
  165. package/src/components/TextField/TextArea.types.ts +28 -0
  166. package/src/components/TextField/TextInput.styled.tsx +115 -0
  167. package/src/components/TextField/TextInput.tsx +27 -0
  168. package/src/components/TextField/TextInput.types.ts +46 -0
  169. package/src/components/TextField/TextInput.utils.ts +7 -0
  170. package/src/components/TextField/components/Buttons.tsx +26 -0
  171. package/src/components/TextField/components/NormalTextInput.tsx +95 -0
  172. package/src/components/TextField/components/PasswordInput.tsx +92 -0
  173. package/src/components/TextField/index.ts +7 -0
  174. package/src/components/Tooltip/Tooltip.styled.tsx +36 -0
  175. package/src/components/Tooltip/Tooltip.tsx +58 -0
  176. package/src/components/Tooltip/Tooltip.types.ts +24 -0
  177. package/src/components/Tooltip/Tooltip.utils.ts +46 -0
  178. package/src/components/Tooltip/index.ts +5 -0
  179. package/src/components/UploadManager/UploadManager.styled.ts +49 -0
  180. package/src/components/UploadManager/UploadManager.tsx +271 -0
  181. package/src/components/UploadManager/UploadManager.types.ts +16 -0
  182. package/src/components/UploadManager/index.ts +5 -0
  183. package/src/components/index.ts +23 -0
  184. package/src/foundations/index.ts +4 -0
  185. package/src/foundations/palette.ts +418 -0
  186. package/src/foundations/spacing.ts +5 -0
  187. package/src/foundations/styles.ts +9 -0
  188. package/src/foundations/typography.ts +492 -0
  189. package/src/icons/BellNoti/index.tsx +28 -0
  190. package/src/icons/CloseLarge/index.tsx +28 -0
  191. package/src/icons/CloseSmall/index.tsx +28 -0
  192. package/src/icons/DownloadPdf/index.tsx +28 -0
  193. package/src/icons/Ellipse/index.tsx +28 -0
  194. package/src/icons/FilterNoti/index.tsx +28 -0
  195. package/src/icons/HideLarge/index.tsx +28 -0
  196. package/src/icons/HideSmall/index.tsx +28 -0
  197. package/src/icons/InformationLarge/index.tsx +28 -0
  198. package/src/icons/InformationSmall/index.tsx +28 -0
  199. package/src/icons/Manufacturer/index.tsx +28 -0
  200. package/src/icons/Rectangle/index.tsx +28 -0
  201. package/src/icons/RefreshLeft/index.tsx +28 -0
  202. package/src/icons/RefreshRight/index.tsx +28 -0
  203. package/src/icons/ShowLarge/index.tsx +28 -0
  204. package/src/icons/ShowSmall/index.tsx +28 -0
  205. package/src/icons/index.ts +180 -0
  206. package/src/index.ts +4 -0
  207. package/src/react-app-env.d.ts +71 -0
  208. package/src/reportWebVitals.ts +15 -0
  209. package/src/setupTests.ts +5 -0
  210. package/src/systems/drawer.ts +27 -0
  211. package/src/systems/index.ts +7 -0
  212. package/src/theme.ts +22 -0
@@ -0,0 +1,43 @@
1
+ import React from 'react';
2
+ import { AlertColor } from '@mui/material';
3
+ import { Success, Error, Information } from '../../icons';
4
+ import theme from '../../theme';
5
+
6
+ export const getIcons = (severity: AlertColor | undefined) => {
7
+ switch (severity) {
8
+ case 'info':
9
+ return <Information />;
10
+ case 'success':
11
+ return <Success />;
12
+ case 'error':
13
+ return <Error />;
14
+ default:
15
+ return <Error />;
16
+ }
17
+ };
18
+
19
+ export const getBackgroundColor = (severity: AlertColor | undefined) => {
20
+ switch (severity) {
21
+ case 'info':
22
+ return theme.palette.alert.InfoBG;
23
+ case 'success':
24
+ return theme.palette.alert.SuccessBG;
25
+ case 'error':
26
+ return theme.palette.alert.ErrorBG;
27
+ default:
28
+ return theme.palette.alert.WarningBG;
29
+ }
30
+ };
31
+
32
+ export const getAccentColor = (severity: AlertColor | undefined) => {
33
+ switch (severity) {
34
+ case 'info':
35
+ return theme.palette.blue[25];
36
+ case 'success':
37
+ return theme.palette.lunitTeal[40];
38
+ case 'error':
39
+ return theme.palette.red[5];
40
+ default:
41
+ return theme.palette.yellow[20];
42
+ }
43
+ };
@@ -0,0 +1,5 @@
1
+ import Alert from './Alert';
2
+ import type { AlertProps } from './Alert.types';
3
+
4
+ export { Alert };
5
+ export type { AlertProps };
@@ -0,0 +1,110 @@
1
+ // This file facilitates style sharing between text input and text area
2
+ import { Box, Theme, Typography } from '@mui/material';
3
+ import { styled } from '@mui/material/styles';
4
+ import type { BaseTextFieldContainerProps, HelperMsgProps } from './BaseTextField.types';
5
+ import { formatCSSSize } from './BaseTextField.utils';
6
+
7
+ const baseTextFieldStyle = (theme: Theme) => {
8
+ return {
9
+ backgroundColor: theme.palette.neutralGrey[75],
10
+ borderRadius: '8px',
11
+ border: '1px solid',
12
+ borderColor: 'transparent',
13
+ color: theme.palette.neutralGrey[5],
14
+ fontWeight: '400',
15
+ fontSize: '14px',
16
+ fontFamily:
17
+ 'Pretendard,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"',
18
+ lineHeight: '20px',
19
+ padding: '7px 16px',
20
+
21
+ '&::placeholder': {
22
+ color: theme.palette.neutralGrey[45],
23
+ },
24
+ '&:focus': {
25
+ outline: 'none',
26
+ border: '1px solid',
27
+ borderColor: theme.palette.lunitTeal[10],
28
+ },
29
+ '&:hover': {
30
+ borderColor: theme.palette.neutralGrey[45],
31
+ },
32
+ '&:disabled': {
33
+ opacity: '0.8',
34
+ pointerEvents: 'none',
35
+ },
36
+ '&:read-only': {
37
+ border: `1px solid ${theme.palette.neutralGrey[70]}`,
38
+ backgroundColor: 'transparent',
39
+ color: theme.palette.neutralGrey[45],
40
+ pointerEvents: 'none',
41
+ },
42
+ };
43
+ };
44
+
45
+ const baseTextFieldErrorStyle = (theme: Theme) => {
46
+ return {
47
+ borderColor: theme.palette.red[5],
48
+ };
49
+ };
50
+
51
+ const baseTextFieldMsgStyle = (theme: Theme) => {
52
+ return {
53
+ width: '312px',
54
+ maxWidth: '312px',
55
+ minHeight: '20px',
56
+ color: theme.palette.neutralGrey[45],
57
+ padding: '4px',
58
+ };
59
+ };
60
+
61
+ const baseTextFieldMsgErrorStyle = (theme: Theme) => {
62
+ return {
63
+ color: theme.palette.red[5],
64
+ };
65
+ };
66
+
67
+ const BaseTextFieldBox = styled(Box, {
68
+ shouldForwardProp: (prop) => prop !== 'width',
69
+ })<BaseTextFieldContainerProps>(({ width }) => {
70
+ return {
71
+ width: formatCSSSize(width),
72
+ minWidth: formatCSSSize(width) ? 'unset' : '208px',
73
+ };
74
+ });
75
+
76
+ const BaseTextFieldContainer = styled(Box, {
77
+ shouldForwardProp: (prop) => !['width'].includes(prop.toString()),
78
+ })<BaseTextFieldContainerProps>(({ width }) => {
79
+ return {
80
+ position: 'relative',
81
+ display: 'flex',
82
+ flexDirection: 'column',
83
+ width: formatCSSSize(width),
84
+ minWidth: formatCSSSize(width) ? 'unset' : '208px',
85
+ };
86
+ });
87
+
88
+ const InputMsg = styled(Typography, {
89
+ shouldForwardProp: (prop) => prop !== 'error',
90
+ })<HelperMsgProps>(({ theme, error }) => {
91
+ let resultStyle = baseTextFieldMsgStyle(theme);
92
+
93
+ if (error) {
94
+ resultStyle = {
95
+ ...resultStyle,
96
+ ...baseTextFieldMsgErrorStyle(theme),
97
+ };
98
+ }
99
+
100
+ return resultStyle;
101
+ });
102
+
103
+ const styles = {
104
+ baseTextFieldStyle,
105
+ baseTextFieldErrorStyle,
106
+ baseTextFieldMsgStyle,
107
+ baseTextFieldMsgErrorStyle,
108
+ };
109
+
110
+ export { styles, BaseTextFieldContainer, BaseTextFieldBox, InputMsg };
@@ -0,0 +1,25 @@
1
+ // Props for all text fields
2
+
3
+ import type { BoxProps } from '@mui/material';
4
+
5
+ // It redefines certain intrinsic properties because of MUI interference
6
+ interface BaseTextFieldContainerProps {
7
+ width?: string | number;
8
+ }
9
+
10
+ interface RootTextFieldProps extends BaseTextFieldContainerProps {
11
+ disabled?: boolean;
12
+ readOnly?: boolean;
13
+ value?: string;
14
+ defaultValue?: string;
15
+ error?: boolean;
16
+ BoxProps?: BoxProps;
17
+ }
18
+
19
+ // Props for helper message specifically
20
+ interface HelperMsgProps {
21
+ error?: boolean;
22
+ helperMsg?: string;
23
+ }
24
+
25
+ export { RootTextFieldProps, BaseTextFieldContainerProps, HelperMsgProps };
@@ -0,0 +1,10 @@
1
+ function formatCSSSize(sizeVal: string | number | undefined) {
2
+ if (typeof sizeVal === 'undefined') {
3
+ return undefined;
4
+ }
5
+ if (typeof sizeVal === 'number') return `${sizeVal}px`;
6
+
7
+ return sizeVal;
8
+ }
9
+
10
+ export { formatCSSSize };
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import type { BaseButtonProps } from './Button.types';
3
+ import { BaseContainedButton } from './styleds/ContainedButton.styled';
4
+ import { BaseGhostButton } from './styleds/GhostButton.styled';
5
+ import { BaseOutlinedButton } from './styleds/OutlinedButton.styled';
6
+
7
+ const BaseButton = ({ variant, ...otherProps }: BaseButtonProps) => {
8
+ if (variant === 'ghost') {
9
+ return <BaseGhostButton {...otherProps} />;
10
+ }
11
+
12
+ if (variant === 'outlined') {
13
+ return <BaseOutlinedButton {...otherProps} />;
14
+ }
15
+
16
+ return <BaseContainedButton {...otherProps} />;
17
+ };
18
+
19
+ export default BaseButton;
@@ -0,0 +1,117 @@
1
+ import React from 'react';
2
+ import { Box } from '@mui/system';
3
+ import BaseButton from './BaseButton';
4
+ import { CircularProgress } from '../Progress';
5
+ import theme from '../../theme';
6
+
7
+ import { isIconButton } from './Button.utils';
8
+ import type { ButtonProps } from './Button.types';
9
+
10
+ function Button(props: ButtonProps) {
11
+ if (isIconButton(props)) {
12
+ const {
13
+ icon,
14
+ loading,
15
+ onClick,
16
+ disableRipple = true,
17
+ focusOutline = false,
18
+ ...otherProps
19
+ } = props;
20
+
21
+ return (
22
+ <BaseButton
23
+ {...otherProps}
24
+ isIconOnly
25
+ disableRipple={disableRipple}
26
+ focusOutline={focusOutline}
27
+ onClick={
28
+ loading
29
+ ? (e) => {
30
+ e.preventDefault();
31
+ }
32
+ : onClick
33
+ }
34
+ >
35
+ {loading ? (
36
+ <CircularProgress
37
+ circleColor={theme.palette.neutralGrey[0]}
38
+ size={20}
39
+ sx={{
40
+ display: 'flex',
41
+ justifyContent: 'center',
42
+ alignItems: 'center',
43
+ }}
44
+ />
45
+ ) : (
46
+ icon
47
+ )}
48
+ </BaseButton>
49
+ );
50
+ }
51
+
52
+ const {
53
+ icon,
54
+ label,
55
+ size,
56
+ focusOutline = false,
57
+ disableRipple = true,
58
+ loading,
59
+ onClick,
60
+ ...otherProps
61
+ } = props;
62
+ return (
63
+ <BaseButton
64
+ isIconOnly={false}
65
+ variant={otherProps.variant ?? 'contained'}
66
+ disableRipple={disableRipple}
67
+ size={size}
68
+ color={otherProps.color}
69
+ focusOutline={focusOutline}
70
+ onClick={
71
+ loading
72
+ ? (e) => {
73
+ e.preventDefault();
74
+ }
75
+ : onClick
76
+ }
77
+ sx={
78
+ loading
79
+ ? {
80
+ '&:not(.loadingCircle)': {
81
+ color: 'transparent',
82
+ },
83
+ }
84
+ : {}
85
+ }
86
+ {...otherProps}
87
+ >
88
+ <>
89
+ {icon}
90
+ {label}
91
+
92
+ {loading && (
93
+ <Box
94
+ className="loadingCircle"
95
+ sx={{
96
+ position: 'absolute',
97
+ top: '50%',
98
+ left: '50%',
99
+ transform: 'translate3d(-50%, -50%, 0)',
100
+ }}
101
+ >
102
+ <CircularProgress
103
+ circleColor={theme.palette.neutralGrey[0]}
104
+ size={20}
105
+ sx={{
106
+ display: 'flex',
107
+ justifyContent: 'center',
108
+ alignItems: 'center',
109
+ }}
110
+ />
111
+ </Box>
112
+ )}
113
+ </>
114
+ </BaseButton>
115
+ );
116
+ }
117
+ export default Button;
@@ -0,0 +1,36 @@
1
+ import type { ButtonProps as MuiButtonProps } from '@mui/material';
2
+
3
+ type ButtonVariant = 'contained' | 'ghost' | 'outlined';
4
+ type ButtonColor = 'primary' | 'secondary' | 'error';
5
+ type ButtonSize = 'small' | 'medium' | 'large';
6
+
7
+ interface BaseButtonProps extends Omit<MuiButtonProps, 'variant' | 'color'> {
8
+ variant?: ButtonVariant;
9
+ color?: ButtonColor;
10
+ size?: ButtonSize;
11
+ disabled?: boolean;
12
+ focusOutline?: boolean;
13
+ isIconOnly: boolean;
14
+ loading?: boolean;
15
+ label?: string;
16
+ }
17
+
18
+ interface IconButtonProps extends Omit<BaseButtonProps, 'isIconOnly'> {
19
+ icon: React.ReactNode;
20
+ }
21
+
22
+ interface NormalButtonProps extends Omit<BaseButtonProps, 'isIconOnly'> {
23
+ label: string;
24
+ icon?: React.ReactNode;
25
+ }
26
+
27
+ type ButtonProps = IconButtonProps | NormalButtonProps;
28
+
29
+ export type {
30
+ ButtonVariant,
31
+ ButtonColor,
32
+ BaseButtonProps,
33
+ IconButtonProps,
34
+ NormalButtonProps,
35
+ ButtonProps,
36
+ };
@@ -0,0 +1,13 @@
1
+ import type { ButtonProps, IconButtonProps, NormalButtonProps } from './Button.types';
2
+
3
+ /**
4
+ * @param props
5
+ * @returns boolean
6
+ * @description checks for presence of `label` prop to assert between Icon and Normal Button
7
+ */
8
+ function isIconButton(props: ButtonProps): props is IconButtonProps {
9
+ const p = props as NormalButtonProps;
10
+ return !p.label;
11
+ }
12
+
13
+ export { isIconButton };
@@ -0,0 +1,6 @@
1
+ import Button from './Button';
2
+ import BaseButton from './BaseButton';
3
+ import type { BaseButtonProps, ButtonProps } from './Button.types';
4
+
5
+ export { Button, BaseButton };
6
+ export type { ButtonProps, BaseButtonProps };
@@ -0,0 +1,57 @@
1
+ import { Theme } from '@mui/material';
2
+ import { typography } from '../../../foundations';
3
+
4
+ const baseButtonStyle = (theme: Theme, focusOutline: boolean | undefined) => {
5
+ const mainColor = theme.palette.lunitTeal[40];
6
+
7
+ return {
8
+ alignItems: 'center',
9
+ display: 'flex',
10
+ gap: '4px',
11
+ borderRadius: '8px',
12
+ border: '1px solid transparent',
13
+ textTransform: 'none' as const,
14
+ minWidth: '36px',
15
+ width: 'max-content',
16
+ height: '36px',
17
+ padding: '8px 12px',
18
+ ...typography.body4,
19
+ backgroundColor: mainColor,
20
+ color: theme.palette.neutralGrey[97],
21
+ '&:hover': {
22
+ backgroundColor: mainColor,
23
+ opacity: 0.8,
24
+ },
25
+ '&:disabled': {
26
+ color: theme.palette.neutralGrey[97],
27
+ backgroundColor: mainColor,
28
+ opacity: 0.4,
29
+ },
30
+ '&:focus': {
31
+ border: focusOutline ? `1px solid ${theme.palette.lunitTeal[10]}` : '1px solid transparent',
32
+ outline: 'none' as const,
33
+ },
34
+ '&:focus-visible': {
35
+ border: focusOutline ? `1px solid ${theme.palette.lunitTeal[10]}` : '1px solid transparent',
36
+ outline: 'none' as const,
37
+ },
38
+ };
39
+ };
40
+
41
+ const baseSmallStyle = {
42
+ height: '28px',
43
+ minWidth: '28px',
44
+ padding: '4px 8px',
45
+ };
46
+
47
+ const baseLargeStyle = {
48
+ fontWeight: 600,
49
+ fontSize: '16px',
50
+ lineHeight: '22px',
51
+ // textTransform: 'capitalize', // This causes a type error in BaseOutlinedButton :S
52
+ height: '44px',
53
+ minWidth: '44px',
54
+ padding: '12px',
55
+ };
56
+
57
+ export { baseButtonStyle, baseSmallStyle, baseLargeStyle };
@@ -0,0 +1,123 @@
1
+ import { ButtonBase, styled } from '@mui/material';
2
+ import type { Theme } from '@mui/material';
3
+ import { baseButtonStyle, baseLargeStyle, baseSmallStyle } from './BaseButton.styled';
4
+ import { baseLargeIconStyle, baseMediumIconStyle, baseSmallIconStyle } from './IconButton.styled';
5
+ import type { BaseButtonProps } from '../Button.types';
6
+
7
+ const containedPrimaryStyle = (theme: Theme, focusOutline: boolean | undefined) => {
8
+ return baseButtonStyle(theme, focusOutline);
9
+ };
10
+
11
+ const containedSecondaryStyle = (theme: Theme, focusOutline: boolean | undefined) => {
12
+ const mainColor = theme.palette.lunitTeal[40];
13
+
14
+ return {
15
+ backgroundColor: theme.palette.neutralGrey[85],
16
+ color: mainColor,
17
+ '&:hover': {
18
+ color: mainColor,
19
+ backgroundColor: theme.palette.neutralGrey[75],
20
+ opacity: 1,
21
+ },
22
+ '&:disabled': {
23
+ color: mainColor,
24
+ backgroundColor: theme.palette.neutralGrey[85],
25
+ opacity: 0.4,
26
+ },
27
+ '&:focus': {
28
+ outline: 'none' as const,
29
+ border: focusOutline ? `1px solid ${mainColor}` : '1px solid transparent',
30
+ },
31
+ '&:focus-visible': {
32
+ outline: 'none' as const,
33
+ border: focusOutline ? `1px solid ${mainColor}` : '1px solid transparent',
34
+ },
35
+ };
36
+ };
37
+
38
+ const containedErrorStyle = (theme: Theme, focusOutline: boolean | undefined) => {
39
+ const mainColor = theme.palette.red[5];
40
+
41
+ return {
42
+ backgroundColor: mainColor,
43
+ color: theme.palette.neutralGrey[0],
44
+ '&:hover': {
45
+ backgroundColor: mainColor,
46
+ opacity: 0.8,
47
+ },
48
+ '&:disabled': {
49
+ color: theme.palette.neutralGrey[0],
50
+ backgroundColor: mainColor,
51
+ opacity: 0.4,
52
+ },
53
+ '&:focus': {
54
+ outline: 'none' as const,
55
+ border: focusOutline ? `1px solid ${mainColor}` : '1px solid transparent',
56
+ },
57
+ '&:focus-visible': {
58
+ outline: 'none' as const,
59
+ border: focusOutline ? `1px solid ${mainColor}` : '1px solid transparent',
60
+ },
61
+ };
62
+ };
63
+
64
+ const BaseContainedButton = styled(ButtonBase, {
65
+ shouldForwardProp: (prop) =>
66
+ !['color', 'variant', 'size', 'focusOutline', 'isIconOnly'].includes(prop.toString()),
67
+ })<BaseButtonProps>(({ theme, color, size, focusOutline, isIconOnly }) => {
68
+ let resultStyle = containedPrimaryStyle(theme, focusOutline);
69
+
70
+ // Apply icon sizing if icon only
71
+ if (isIconOnly) {
72
+ if (size === 'small') {
73
+ resultStyle = {
74
+ ...resultStyle,
75
+ ...baseSmallIconStyle,
76
+ };
77
+ } else if (size === 'large') {
78
+ resultStyle = {
79
+ ...resultStyle,
80
+ ...baseLargeIconStyle,
81
+ };
82
+ } else {
83
+ resultStyle = {
84
+ ...resultStyle,
85
+ ...baseMediumIconStyle,
86
+ };
87
+ }
88
+ } else {
89
+ // Apply label or icon-label
90
+ if (size === 'small') {
91
+ resultStyle = {
92
+ ...resultStyle,
93
+ ...baseSmallStyle,
94
+ };
95
+ }
96
+
97
+ if (size === 'large') {
98
+ resultStyle = {
99
+ ...resultStyle,
100
+ ...baseLargeStyle,
101
+ };
102
+ }
103
+ }
104
+
105
+ // Apply color
106
+ if (color === 'error') {
107
+ resultStyle = {
108
+ ...resultStyle,
109
+ ...containedErrorStyle(theme, focusOutline),
110
+ };
111
+ }
112
+
113
+ if (color === 'secondary') {
114
+ resultStyle = {
115
+ ...resultStyle,
116
+ ...containedSecondaryStyle(theme, focusOutline),
117
+ };
118
+ }
119
+
120
+ return resultStyle;
121
+ });
122
+
123
+ export { containedPrimaryStyle, containedSecondaryStyle, containedErrorStyle, BaseContainedButton };