@team-monolith/cds 0.4.0 → 0.4.3

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 (88) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +2 -0
  3. package/package.json +5 -1
  4. package/public/favicon.ico +0 -0
  5. package/public/index.html +0 -43
  6. package/public/logo192.png +0 -0
  7. package/public/logo512.png +0 -0
  8. package/public/manifest.json +0 -25
  9. package/public/robots.txt +0 -3
  10. package/src/App.tsx +0 -7
  11. package/src/cds/CodleDesignSystemProvider.tsx +0 -93
  12. package/src/cds/README.md +0 -23
  13. package/src/cds/components/AlertDialog/AlertDialog.tsx +0 -101
  14. package/src/cds/components/AlertDialog/AlertDialogActions.tsx +0 -34
  15. package/src/cds/components/AlertDialog/AlertDialogContent.tsx +0 -36
  16. package/src/cds/components/AlertDialog/AlertDialogTitle.tsx +0 -63
  17. package/src/cds/components/AlertDialog/index.tsx +0 -4
  18. package/src/cds/components/Banner.tsx +0 -176
  19. package/src/cds/components/Button.tsx +0 -256
  20. package/src/cds/components/CheckboxInput.tsx +0 -270
  21. package/src/cds/components/Input.tsx +0 -171
  22. package/src/cds/components/InputBase.tsx +0 -226
  23. package/src/cds/components/Pagination.tsx +0 -99
  24. package/src/cds/components/PinInput.tsx +0 -322
  25. package/src/cds/components/RadioInput.tsx +0 -226
  26. package/src/cds/components/SquareButton.tsx +0 -229
  27. package/src/cds/components/Switch.tsx +0 -129
  28. package/src/cds/components/Tag.tsx +0 -155
  29. package/src/cds/components/Tooltip.tsx +0 -104
  30. package/src/cds/foundation/color.ts +0 -83
  31. package/src/cds/foundation/shadows.ts +0 -17
  32. package/src/cds/icons/Arrows/index.ts +0 -2
  33. package/src/cds/icons/Media/index.ts +0 -2
  34. package/src/cds/icons/System/index.ts +0 -2
  35. package/src/cds/icons/arrows.tsx +0 -116
  36. package/src/cds/icons/brand.tsx +0 -13
  37. package/src/cds/icons/design.tsx +0 -15
  38. package/src/cds/icons/map.tsx +0 -14
  39. package/src/cds/icons/system.tsx +0 -143
  40. package/src/cds/index.ts +0 -64
  41. package/src/cds/patterns/Card/Card.tsx +0 -294
  42. package/src/cds/patterns/Card/class-icon.svg +0 -28
  43. package/src/cds/patterns/Card/index.tsx +0 -2
  44. package/src/cds/patterns/Card/material-icon.svg +0 -25
  45. package/src/cds/patterns/Card/problem-icon.svg +0 -25
  46. package/src/cds/patterns/Card/thumbnail/sample.png +0 -0
  47. package/src/cds/patterns/Dialog/Dialog.tsx +0 -57
  48. package/src/cds/patterns/Dialog/DialogContent.tsx +0 -28
  49. package/src/cds/patterns/Dialog/DialogNavigation.tsx +0 -29
  50. package/src/cds/patterns/Dialog/DialogNavigationContext.tsx +0 -9
  51. package/src/cds/patterns/Dialog/DialogNavigationItem.tsx +0 -42
  52. package/src/cds/patterns/Dialog/DialogPanel.tsx +0 -40
  53. package/src/cds/patterns/Dialog/DialogPanels.tsx +0 -24
  54. package/src/cds/patterns/Dialog/DialogPanelsContext.tsx +0 -9
  55. package/src/cds/patterns/Dialog/DialogTitle.tsx +0 -55
  56. package/src/cds/patterns/Dialog/index.tsx +0 -7
  57. package/src/cds/patterns/Dropdown/Dropdown.tsx +0 -111
  58. package/src/cds/patterns/Dropdown/DropdownItem.tsx +0 -203
  59. package/src/cds/patterns/Dropdown/DropdownMenu.tsx +0 -176
  60. package/src/cds/patterns/Dropdown/index.tsx +0 -2
  61. package/src/cds/patterns/EmptyState/EmptyState.tsx +0 -91
  62. package/src/cds/patterns/EmptyState/empty-state-icon.svg +0 -36
  63. package/src/cds/patterns/EmptyState/index.tsx +0 -2
  64. package/src/cds/patterns/Navigation/NavigationContext.tsx +0 -9
  65. package/src/cds/patterns/Navigation/NavigationHorizontal.tsx +0 -32
  66. package/src/cds/patterns/Navigation/NavigationItem.tsx +0 -36
  67. package/src/cds/patterns/Navigation/NavigationVertical.tsx +0 -39
  68. package/src/cds/patterns/Navigation/index.tsx +0 -3
  69. package/src/cds/patterns/SegmentedControl/SegmentedControlButton.tsx +0 -55
  70. package/src/cds/patterns/SegmentedControl/SegmentedControlGroup.tsx +0 -81
  71. package/src/cds/patterns/SegmentedControl/SegmentedControlGroupPropsContext.tsx +0 -9
  72. package/src/cds/patterns/SegmentedControl/SegmentedControlSquareButton.tsx +0 -51
  73. package/src/cds/patterns/SegmentedControl/index.ts +0 -3
  74. package/src/cds/patterns/Table/Table.tsx +0 -62
  75. package/src/cds/patterns/Table/TableBody.tsx +0 -30
  76. package/src/cds/patterns/Table/TableCell.tsx +0 -253
  77. package/src/cds/patterns/Table/TableHead.tsx +0 -30
  78. package/src/cds/patterns/Table/TablePropsContext.tsx +0 -9
  79. package/src/cds/patterns/Table/TableRow.tsx +0 -70
  80. package/src/cds/patterns/Table/TableVariantContext.tsx +0 -9
  81. package/src/cds/patterns/Table/index.tsx +0 -15
  82. package/src/cds/utils/hover.tsx +0 -24
  83. package/src/cds/utils/reset.tsx +0 -19
  84. package/src/cds/utils/zIndex.tsx +0 -3
  85. package/src/index.tsx +0 -10
  86. package/tsconfig.json +0 -22
  87. /package/{src/cds → @types}/emotion.d.ts +0 -0
  88. /package/{src/cds → @types}/svg.d.ts +0 -0
@@ -1,9 +0,0 @@
1
- import React from "react";
2
-
3
- export const DialogPanelsContext = React.createContext<{
4
- value: string;
5
- renderStrategy: "hidden" | "unmount";
6
- }>({
7
- value: "",
8
- renderStrategy: "unmount",
9
- });
@@ -1,55 +0,0 @@
1
- /** @jsxImportSource @emotion/react */
2
- import { css, useTheme } from "@emotion/react";
3
- import React from "react";
4
- import SquareButton from "../../components/SquareButton";
5
- import { CloseFillIcon } from "../../icons/system";
6
-
7
- export interface DialogTitleProps {
8
- className?: string;
9
- component?: React.ElementType;
10
-
11
- /**
12
- * 제목의 X 버튼을 누르를 때 호출되는 callback.
13
- * 이 속성이 전달되면 X 버튼을 Title 영역에 그립니다.
14
- */
15
- onClose?: () => void;
16
-
17
- /** Content 내용으로 표기될 값 */
18
- children: React.ReactNode;
19
- }
20
-
21
- export function DialogTitle(props: DialogTitleProps) {
22
- const { className, component: Component = "div", onClose, children } = props;
23
- const theme = useTheme();
24
- return (
25
- <>
26
- <Component
27
- className={className}
28
- css={css`
29
- display: flex;
30
- padding: 0px 16px 0px 24px;
31
- justify-content: space-between;
32
- align-items: center;
33
-
34
- text-align: center;
35
- /* Alt/Paragraph/16px-Eb */
36
- font-size: 16px;
37
- font-family: NanumSquareNeo;
38
- font-weight: 800;
39
- line-height: 24px;
40
- color: ${theme.color.foreground.neutralBase};
41
- `}
42
- >
43
- {children}
44
- {onClose && (
45
- <SquareButton
46
- color="icon"
47
- size="small"
48
- icon={<CloseFillIcon />}
49
- onClick={onClose}
50
- />
51
- )}
52
- </Component>
53
- </>
54
- );
55
- }
@@ -1,7 +0,0 @@
1
- export * from "./Dialog";
2
- export * from "./DialogTitle";
3
- export * from "./DialogContent";
4
- export * from "./DialogNavigation";
5
- export * from "./DialogNavigationItem";
6
- export * from "./DialogPanels";
7
- export * from "./DialogPanel";
@@ -1,111 +0,0 @@
1
- import React, { useRef, useState } from "react";
2
- import Button, { ButtonColor, ButtonSize } from "../../components/Button";
3
- import DropdownMenu, { DropdownMenuProps } from "./DropdownMenu";
4
- import { ArrowDropDownFillIcon } from "../../icons/arrows";
5
-
6
- /* 드롭다운 패턴은 버튼 컴포넌트와 드롭다운 메뉴 컴포넌트를 합쳐서 사용합니다.
7
- 드롭다운 메뉴 컴포넌트는 MUI의 Menu 컴포넌트를 사용하며, 드롭다운 아이템의 리스트 형태로 구성됩니다.
8
-
9
- <DropdownMenu>
10
- 드롭다운 메뉴는 기본값으로 Mui Modal의 성질을 갖고 있어서 클릭 이벤트가 발생하면 메뉴가 열리고,
11
- 생성된 메뉴 외부 영역을 클릭하면 메뉴가 닫힙니다.
12
- 그런데, 중첩된 드롭다운 메뉴를 구현할 때 이러한 성질이 문제가 됩니다.
13
- 이 생성된 메뉴 외부 영역이 상위 드롭다운 메뉴를 가려서 클릭이 되지 않기 때문입니다.
14
- 그래서 중첩된 메뉴(isNestedMenu)의 경우 이 모달의 position을 적절히 이동시켜 상위 메뉴와 상호작용 할 수 있게 만들었습니다.
15
- 또한 메뉴에서 열려있는 서브메뉴가 최대 하나만 존재하게 하기 위해 selectedIndex 상태를 추가했습니다.
16
- handleClick을 통해 아이템이 아닌 다른 곳을 클릭하면 메뉴가 닫히도록 했습니다.
17
-
18
- <DropdownItem>
19
- 드롭다운 아이템의 서브메뉴가 열리는 조건은 복잡합니다.
20
- 1. 서브메뉴가 존재해야 하고,(isSubMenuExist)
21
- 2. 드롭다운 아이템이 클릭되어 내부 상태(isSubMenuOpen)가 true가 되어야 하며,
22
- 3. 서브메뉴 노출이 허용되어 있어야 합니다.(shouldSubMenuOpen)
23
-
24
- 드롭다운 메뉴의 handleClick은 드롭다운 메뉴를 닫는 역할을 하므로,
25
- 드롭다운 아이템의 handleClick은 e.stopPropagation()을 통해 이벤트 전파를 막습니다.
26
- 그리고 드롭다운 아이템을 클릭하면 내부 상태(isSubMenuOpen)를 true로 만들고,
27
- onClick을 통해 전달된 함수를 통해 드롭다운 메뉴의 selectedIndex 상태를 변경합니다.
28
- 이 selectedIndex 상태를 이용해서 서브메뉴 노출 허용여부(shouldSubMenuOpen)를 전달했습니다.
29
- 이를 통해 서브메뉴는 최대 하나만 열리도록 구현했습니다.
30
- */
31
-
32
- export interface DropdownProps {
33
- className?: string;
34
- component?: React.ElementType;
35
-
36
- /** 버튼 비활성화 여부 */
37
- disabled?: boolean;
38
-
39
- /** 버튼 컴포넌트 색상 */
40
- color?: ButtonColor;
41
-
42
- /** 버튼 컴포넌트 크기 */
43
- size?: ButtonSize;
44
-
45
- /** 버튼 컴포넌트 내 좌측에 표기될 아이콘 */
46
- startIcon?: React.ReactNode;
47
-
48
- /** 버튼 컴포넌트 내 우측에 표기될 아이콘 */
49
- endIcon?: React.ReactNode;
50
-
51
- /** 버튼 컴포넌트 내 표기될 문자열 */
52
- label: string;
53
-
54
- /** 버튼 클릭 시 호출될 콜백 함수 */
55
- onClick?: () => void;
56
-
57
- /** 드롭다운 메뉴의 props */
58
- menuProps: DropdownMenuProps;
59
- }
60
-
61
- /**
62
- * [피그마](https://www.figma.com/file/PnQp3tPxiCjgsPZfLUaUL1/Codle-PD-Kit---Patterns?type=design&node-id=203-95329&t=FwczLZ1IVvskUVbT-0)
63
- */
64
- export default function Dropdown(props: DropdownProps) {
65
- const {
66
- className,
67
- component: Component = "div",
68
- disabled,
69
- color = "primary",
70
- size = "medium",
71
- startIcon,
72
- endIcon = <ArrowDropDownFillIcon />,
73
- label,
74
- onClick,
75
- menuProps,
76
- } = props;
77
- const buttonProps = {
78
- disabled,
79
- color,
80
- size,
81
- startIcon,
82
- endIcon,
83
- };
84
- const menuRef = useRef<HTMLButtonElement | null>(null);
85
- const [open, setOpen] = useState(false);
86
-
87
- const handleClick = () => {
88
- onClick?.();
89
- setOpen(true);
90
- };
91
- const handleClose = (e: React.MouseEvent<HTMLElement>) => {
92
- menuProps.onClose?.(e);
93
- setOpen(false);
94
- };
95
- return (
96
- <Component className={className}>
97
- <Button
98
- ref={menuRef}
99
- {...buttonProps}
100
- label={label}
101
- onClick={handleClick}
102
- />
103
- <DropdownMenu
104
- {...menuProps}
105
- open={open}
106
- onClose={handleClose}
107
- anchorEl={menuRef.current}
108
- />
109
- </Component>
110
- );
111
- }
@@ -1,203 +0,0 @@
1
- /** @jsxImportSource @emotion/react */
2
- import { css, Theme } from "@emotion/react";
3
- import * as React from "react";
4
- import styled from "@emotion/styled";
5
- import { MenuItem } from "@mui/material";
6
- import { HOVER } from "../../utils/hover";
7
- import CheckboxInput, {
8
- CheckboxInputProps,
9
- } from "../../components/CheckboxInput";
10
- import { useRef, useState } from "react";
11
- import DropdownMenu, { DropdownMenuProps } from "./DropdownMenu";
12
- import { ArrowRightSLineIcon } from "../../icons/arrows";
13
-
14
- export type DropdownItemType = "default" | "danger";
15
-
16
- export const DROPDOWN_ITEM_WIDTH = 116;
17
-
18
- const TYPE_TO_COLOR = (theme: Theme, type: DropdownItemType): string => {
19
- return {
20
- default: theme.color.foreground.neutralBase,
21
- danger: theme.color.foreground.danger,
22
- }[type];
23
- };
24
-
25
- export interface DropdownItemProps {
26
- className?: string;
27
- component?: React.ElementType;
28
-
29
- /** 드롭다운 아이템의 타입 */
30
- type?: DropdownItemType;
31
- /** 체크박스 노출여부 */
32
- checkbox?: boolean;
33
- /** 체크박스 설정 props. 초기 체크여부 및 체크박스 값 변경시 호출되는 함수 등을 지정합니다. */
34
- checkboxProps?: CheckboxInputProps;
35
- /** 시작 아이콘 설정 */
36
- startIcon?: React.ReactNode;
37
- /** 드롭다운 아이템의 라벨 */
38
- label?: string;
39
- /** 끝 아이콘 설정. subMenuProps가 없으면 노출되지 않습니다. */
40
- endIcon?: React.ReactNode;
41
- /** 비활성화 여부 */
42
- disabled?: boolean;
43
- /** 드롭다운 아이템의 활성화 여부. 서브 메뉴가 노출될 때 true가 됩니다. */
44
- active?: boolean;
45
- /** 드롭다운 아이템 마우스 호버 시 호출될 콜백 함수 */
46
- onMouseEnter?: (e: React.MouseEvent<HTMLElement>) => void;
47
- /** 드롭다운 아이템 마우스 아웃 시 호출될 콜백 함수 */
48
- onMouseLeave?: (e: React.MouseEvent<HTMLElement>) => void;
49
- /** 드롭다운 아이템 클릭 시 호출될 콜백 함수 */
50
- onClick?: (e: React.MouseEvent<HTMLElement>) => void;
51
- /** 드롭다운 아이템의 서브 메뉴가 열려야 하는지 여부 */
52
- shouldSubMenuOpen?: boolean;
53
- /** 아이템이 가지는 드롭다운 메뉴 props. 주어지지 않으면 서브메뉴가 없습니다. */
54
- subMenuProps?: DropdownMenuProps;
55
- /** 드롭다운 아이템의 서브 메뉴가 닫힐 때 실행할 콜백함수 */
56
- onSubMenuClose?: (e: React.MouseEvent<HTMLElement>) => void;
57
- }
58
-
59
- /**
60
- * [피그마](https://www.figma.com/file/PnQp3tPxiCjgsPZfLUaUL1/Codle-PD-Kit---Patterns?type=design&node-id=106-1900&t=FwczLZ1IVvskUVbT-0)
61
- */
62
- const DropdownItem = React.forwardRef<any, DropdownItemProps>(
63
- (props, ref): React.ReactElement => {
64
- const {
65
- className,
66
- component: Component = "div",
67
- type = "default",
68
- checkbox,
69
- checkboxProps = { checked: false },
70
- startIcon,
71
- label,
72
- endIcon = <ArrowRightSLineIcon />,
73
- disabled,
74
- active,
75
- onMouseEnter,
76
- onMouseLeave,
77
- onClick,
78
- shouldSubMenuOpen = false,
79
- subMenuProps = {
80
- itemsProps: [],
81
- },
82
- onSubMenuClose,
83
- ...other
84
- } = props;
85
- const itemRef = useRef<HTMLLIElement | null>(null);
86
- const [isSubMenuOpen, setIsSubMenuOpen] = useState(false);
87
- const handleClick = (e: React.MouseEvent<HTMLElement>) => {
88
- e.stopPropagation();
89
- setIsSubMenuOpen(true);
90
- onClick?.(e);
91
- };
92
- const handleClose = (e: React.MouseEvent<HTMLElement>) => {
93
- setIsSubMenuOpen(false);
94
- onSubMenuClose?.(e);
95
- };
96
- const isSubMenuExist = subMenuProps.itemsProps.length > 0;
97
- const isSubMenuShowed =
98
- isSubMenuExist && isSubMenuOpen && shouldSubMenuOpen;
99
-
100
- return (
101
- <Component
102
- className={className}
103
- ref={ref}
104
- onMouseEnter={onMouseEnter}
105
- onMouseLeave={onMouseLeave}
106
- onClick={handleClick}
107
- {...other}
108
- >
109
- <StyledMenuItem
110
- ref={itemRef}
111
- disabled={disabled}
112
- selected={isSubMenuShowed || active}
113
- >
114
- <LeftWrapper>
115
- {checkbox && (
116
- <StyledCheckboxInput
117
- {...checkboxProps}
118
- onClick={(e) => {
119
- e.stopPropagation();
120
- checkboxProps.onClick?.(e);
121
- }}
122
- />
123
- )}
124
- {startIcon && <IconDiv type={type}>{startIcon}</IconDiv>}
125
- <LabelDiv type={type}>{label}</LabelDiv>
126
- </LeftWrapper>
127
- {isSubMenuExist && <IconDiv type={type}>{endIcon}</IconDiv>}
128
- </StyledMenuItem>
129
- {isSubMenuExist && (
130
- <DropdownMenu
131
- {...subMenuProps}
132
- open={isSubMenuShowed}
133
- anchorEl={itemRef.current}
134
- isNestedMenu={true}
135
- onClose={handleClose}
136
- anchorOrigin={{
137
- vertical: "top",
138
- horizontal: "right",
139
- }}
140
- />
141
- )}
142
- </Component>
143
- );
144
- }
145
- );
146
-
147
- const StyledCheckboxInput = styled(CheckboxInput)`
148
- margin: 4px;
149
- `;
150
-
151
- const IconDiv = styled.div<{ type: DropdownItemType }>(
152
- ({ theme, type }) => css`
153
- width: 14px;
154
- height: 14px;
155
- svg {
156
- width: 14px;
157
- height: 14px;
158
- path {
159
- fill: ${TYPE_TO_COLOR(theme, type)};
160
- }
161
- }
162
- `
163
- );
164
-
165
- const LabelDiv = styled.div<{ type: DropdownItemType }>`
166
- overflow: hidden;
167
- text-overflow: ellipsis;
168
- white-space: nowrap;
169
- font-size: 14px;
170
- color: ${({ theme, type }) => TYPE_TO_COLOR(theme, type)};
171
- `;
172
-
173
- const LeftWrapper = styled.div`
174
- display: flex;
175
- align-items: center;
176
- overflow: hidden;
177
- white-space: nowrap;
178
- gap: 4px;
179
- `;
180
-
181
- const StyledMenuItem = styled(MenuItem)(
182
- ({ theme }) => css`
183
- &.MuiMenuItem-root {
184
- background-color: ${theme.color.background.neutralBase};
185
- width: ${DROPDOWN_ITEM_WIDTH}px;
186
- height: 32px;
187
- border-radius: 6px;
188
- padding: 4px 8px 4px 8px;
189
- display: flex;
190
- align-items: center;
191
- justify-content: space-between;
192
- line-height: 14px;
193
- ${HOVER(css`
194
- background-color: ${theme.color.background.neutralAlt};
195
- `)}
196
- &.Mui-selected {
197
- background-color: ${theme.color.background.neutralAlt};
198
- }
199
- }
200
- `
201
- );
202
-
203
- export default DropdownItem;
@@ -1,176 +0,0 @@
1
- import styled from "@emotion/styled";
2
- import { css } from "@emotion/react";
3
- import { Menu } from "@mui/material";
4
- import React, { useState } from "react";
5
- import shadows from "../../foundation/shadows";
6
- import DropdownItem, {
7
- DROPDOWN_ITEM_WIDTH,
8
- DropdownItemProps,
9
- } from "./DropdownItem";
10
-
11
- interface OriginProps {
12
- vertical: "top" | "center" | "bottom";
13
- horizontal: "left" | "center" | "right";
14
- }
15
-
16
- const ORIGIN_PROPS_TO_MARGIN = (originProps: OriginProps) => {
17
- const { vertical, horizontal } = originProps;
18
- return {
19
- top: {
20
- left: css`
21
- margin-right: 12px;
22
- `,
23
- center: css`
24
- margin-bottom: 8px;
25
- `,
26
- right: css`
27
- margin-left: 12px;
28
- `,
29
- },
30
- center: {
31
- left: css`
32
- margin-right: 12px;
33
- `,
34
- center: css`
35
- margin-bottom: 8px;
36
- `,
37
- right: css`
38
- margin-left: 12px;
39
- `,
40
- },
41
- bottom: {
42
- left: css`
43
- margin-top: 8px;
44
- `,
45
- center: css`
46
- margin-top: 8px;
47
- `,
48
- right: css`
49
- margin-top: 8px;
50
- `,
51
- },
52
- }[vertical][horizontal];
53
- };
54
-
55
- export const DROPDOWN_MENU_WIDTH = 124;
56
- export const DROPDOWN_MENU_MAX_HEIGHT = 160;
57
- export interface DropdownMenuProps {
58
- className?: string;
59
- // component: React.ElementType; // 불필요한 dom 중첩을 막기 위해 사용하지 않습니다.
60
-
61
- /** 드롭다운 메뉴가 열리는지 여부 */
62
- open?: boolean;
63
- /** 드롭다운 메뉴의 위치참조 */
64
- anchorEl?: HTMLElement | null;
65
- /** 드롭다운 메뉴가 닫힐 때 실행될 콜백함수 */
66
- onClose?: (e: React.MouseEvent<HTMLElement>) => void;
67
- /** 현재 드롭다운 메뉴가 중첩 드롭다운인지 여부. 최상위일 경우 false입니다. */
68
- isNestedMenu?: boolean;
69
- /** 드롭다운 메뉴 원점이 anchor의 어디에 위치하는지 조정 */
70
- anchorOrigin?: OriginProps;
71
- /** 드롭다운 메뉴 원점이 메뉴 자신의 어디에 위치하는지 조정 */
72
- transformOrigin?: OriginProps;
73
- /** 드롭다운 메뉴가 가지는 드롭다운 아이템들의 props 배열 */
74
- itemsProps: DropdownItemProps[];
75
- }
76
-
77
- /**
78
- * [피그마](https://www.figma.com/file/PnQp3tPxiCjgsPZfLUaUL1/Codle-PD-Kit---Patterns?type=design&node-id=106-1921&t=FwczLZ1IVvskUVbT-0)
79
- */
80
- const DropdownMenu = React.forwardRef<any, DropdownMenuProps>(
81
- (props, ref): React.ReactElement => {
82
- const {
83
- className,
84
- open = false,
85
- anchorEl,
86
- onClose,
87
- isNestedMenu = false,
88
- anchorOrigin = {
89
- vertical: "bottom",
90
- horizontal: "left",
91
- },
92
- transformOrigin,
93
- itemsProps,
94
- ...other
95
- } = props;
96
-
97
- const [selectedIndex, setSelectedIndex] = useState(-1);
98
-
99
- const handleClick = (e: React.MouseEvent<HTMLElement>) => {
100
- setSelectedIndex(-1);
101
- onClose?.(e);
102
- };
103
-
104
- // https://github.com/mui/material-ui/blob/master/packages/mui-material/src/Popover/Popover.js#L104
105
- // 메뉴를 감싸는 popover의 절대위치를 이동시키기 위해 anchorEl의 위치를 가져옵니다.
106
- const anchorRect = anchorEl?.getBoundingClientRect();
107
-
108
- return (
109
- <StyledMenu
110
- ref={ref}
111
- open={open}
112
- anchorEl={anchorEl}
113
- onClick={handleClick}
114
- onClose={onClose}
115
- className={className}
116
- anchorRect={isNestedMenu ? anchorRect : undefined}
117
- anchorOrigin={anchorOrigin}
118
- transformOrigin={transformOrigin}
119
- hideBackdrop
120
- {...other}
121
- >
122
- {itemsProps?.map((itemProps, index) => (
123
- <DropdownItem
124
- key={index}
125
- {...itemProps}
126
- onClick={(e) => {
127
- itemProps.onClick?.(e);
128
- setSelectedIndex(index);
129
- }}
130
- shouldSubMenuOpen={open && selectedIndex === index}
131
- onSubMenuClose={onClose}
132
- />
133
- ))}
134
- </StyledMenu>
135
- );
136
- }
137
- );
138
-
139
- const StyledMenu = styled(Menu, {
140
- shouldForwardProp: (prop) => prop !== "anchorRect",
141
- })<{
142
- anchorRect?: DOMRect;
143
- anchorOrigin: OriginProps;
144
- }>(
145
- ({ anchorRect, anchorOrigin }) => css`
146
- .MuiPaper-root {
147
- display: block;
148
- ${ORIGIN_PROPS_TO_MARGIN(anchorOrigin)}
149
- width: ${DROPDOWN_MENU_WIDTH}px;
150
- max-height: ${DROPDOWN_MENU_MAX_HEIGHT}px;
151
- box-shadow: ${shadows.shadow04};
152
- .MuiList-root {
153
- display: inline-flex;
154
- flex-direction: column;
155
- padding: 4px;
156
- gap: 2px;
157
- }
158
- ${anchorRect &&
159
- css`
160
- position: absolute;
161
- top: 0px !important;
162
- left: 0px !important;
163
- `}
164
- }
165
- &.MuiModal-root {
166
- ${anchorRect &&
167
- css`
168
- position: absolute;
169
- top: ${anchorRect.top}px;
170
- left: ${anchorRect.left + DROPDOWN_ITEM_WIDTH}px;
171
- `}
172
- }
173
- `
174
- );
175
-
176
- export default DropdownMenu;
@@ -1,2 +0,0 @@
1
- export * from "./Dropdown";
2
- export { default } from "./Dropdown";
@@ -1,91 +0,0 @@
1
- /** @jsxImportSource @emotion/react */
2
- import { css } from "@emotion/react";
3
- import styled from "@emotion/styled";
4
- import React from "react";
5
- import Button, { ButtonProps } from "../../components/Button";
6
- import { ReactComponent as EmptyStateIcon } from "./empty-state-icon.svg";
7
-
8
- export interface EmptyStateProps {
9
- className?: string;
10
- component?: React.ElementType;
11
-
12
- /** 상단에 표시되는 텍스트입니다. */
13
- title: string;
14
-
15
- /** title 하단에 표시되는 텍스트입니다. */
16
- subtitle?: string;
17
-
18
- /** 하단의 영역에 렌더링 될 Button 컴포넌트의 속성 배열입니다. */
19
- buttons?: ButtonProps[];
20
- }
21
-
22
- /**
23
- * [피그마](https://www.figma.com/file/PnQp3tPxiCjgsPZfLUaUL1/Codle-PD-Kit---Patterns?type=design&node-id=181-89918&t=J5yAnjojg5Dm1764-0)
24
- */
25
- export default function EmptyState(props: EmptyStateProps) {
26
- const {
27
- className,
28
- component: Component = "div",
29
- title,
30
- subtitle,
31
- buttons,
32
- } = props;
33
- return (
34
- <Component
35
- className={className}
36
- css={css`
37
- display: flex;
38
- flex-direction: column;
39
- align-items: center;
40
- gap: 10px;
41
-
42
- padding: 120px 10px;
43
- `}
44
- >
45
- <EmptyStateIcon />
46
- <TextDiv>
47
- <Title>{title}</Title>
48
- {subtitle && <Subtitle>{subtitle}</Subtitle>}
49
- {buttons?.length !== 0 && (
50
- <Buttons>
51
- {buttons?.map((buttonProps) => (
52
- <Button {...buttonProps} />
53
- ))}
54
- </Buttons>
55
- )}
56
- </TextDiv>
57
- </Component>
58
- );
59
- }
60
-
61
- const TextDiv = styled.div(
62
- ({ theme }) => css`
63
- display: flex;
64
- flex-direction: column;
65
- align-items: center;
66
- padding: 24px 0px;
67
- gap: 12px;
68
-
69
- font-style: normal;
70
- color: ${theme.color.foreground.neutralBase};
71
- `
72
- );
73
-
74
- const Title = styled.div`
75
- font-weight: 800;
76
- font-size: 36px;
77
- line-height: 44px;
78
- `;
79
-
80
- const Subtitle = styled.div`
81
- font-weight: 400;
82
- font-size: 18px;
83
- line-height: 28px;
84
- `;
85
-
86
- const Buttons = styled.div`
87
- display: flex;
88
- align-items: center;
89
- padding: 4px;
90
- gap: 8px;
91
- `;