@jk-core/components 1.0.2 → 1.1.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.
- package/dist/index.js +1275 -732
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +5 -5
- package/dist/index.umd.cjs.map +1 -1
- package/dist/src/Calendar/components/DateLabel/index.d.ts +1 -1
- package/dist/src/Calendar/components/DayTile/index.d.ts +1 -1
- package/dist/src/Calendar/components/ViewSelector/index.d.ts +1 -1
- package/dist/src/common/Accordion/index.d.ts +12 -0
- package/dist/src/common/Breadcrumbs/index.d.ts +40 -0
- package/dist/src/common/Button/index.d.ts +27 -0
- package/dist/src/common/Card/index.d.ts +6 -0
- package/dist/src/common/DropDown/List.d.ts +10 -0
- package/dist/src/common/DropDown/index.d.ts +29 -0
- package/dist/src/common/Pagination/index.d.ts +16 -0
- package/dist/src/common/SegmentButton/index.d.ts +26 -0
- package/dist/src/common/Skeleton/index.d.ts +28 -0
- package/dist/src/common/SwitchButton/index.d.ts +19 -0
- package/dist/src/index.d.ts +10 -1
- package/dist/src/utils/ts/allowDecimal.d.ts +1 -0
- package/dist/src/utils/ts/autoHypen.d.ts +1 -0
- package/dist/src/utils/ts/calculateMax.d.ts +9 -0
- package/dist/src/utils/ts/checkIsMobilePlatform.d.ts +2 -0
- package/dist/src/utils/ts/formatFileSize.d.ts +4 -0
- package/dist/src/utils/ts/formatMoney.d.ts +2 -0
- package/dist/src/utils/ts/gradientRatio.d.ts +19 -0
- package/dist/src/utils/ts/kiloToMega.d.ts +6 -0
- package/dist/src/utils/ts/maskingPhone.d.ts +2 -0
- package/dist/src/utils/ts/toQueryString.d.ts +5 -0
- package/dist/src/utils/ts/valueAsNumber.d.ts +12 -0
- package/package.json +33 -25
- package/src/Calendar/RangeCalendar.tsx +5 -5
- package/src/Calendar/ScrollCalendar.tsx +3 -3
- package/src/Calendar/SingleCalendar.tsx +15 -15
- package/src/Calendar/components/DateLabel/index.tsx +19 -19
- package/src/Calendar/components/DayTile/index.tsx +4 -4
- package/src/Calendar/components/MonthTile/index.tsx +2 -2
- package/src/Calendar/components/ViewSelector/index.tsx +7 -7
- package/src/Calendar/components/YearTile/YearTile.module.scss +0 -1
- package/src/Calendar/components/YearTile/index.tsx +1 -1
- package/src/Calendar/index.tsx +3 -3
- package/src/Calendar/utils/isInRange.ts +1 -1
- package/src/common/Accordion/Accordion.module.scss +52 -0
- package/src/common/Accordion/arrow-down.svg +3 -0
- package/src/common/Accordion/arrow-up.svg +3 -0
- package/src/common/Accordion/index.tsx +55 -0
- package/src/common/Breadcrumbs/Breadcrumbs.module.scss +45 -0
- package/src/common/Breadcrumbs/home.svg +5 -0
- package/src/common/Breadcrumbs/index.tsx +82 -0
- package/src/common/Button/Button.module.scss +130 -0
- package/src/common/Button/index.tsx +60 -0
- package/src/common/Card/Card.module.scss +27 -0
- package/src/common/Card/index.tsx +19 -0
- package/src/common/DropDown/DropDown.module.scss +135 -0
- package/src/common/DropDown/List.tsx +157 -0
- package/src/common/DropDown/arrow-down.svg +3 -0
- package/src/common/DropDown/index.tsx +104 -0
- package/src/common/DropDown/search.svg +4 -0
- package/src/common/Pagination/Pagination.module.scss +177 -0
- package/src/common/Pagination/arrow-left.svg +12 -0
- package/src/common/Pagination/arrow-right.svg +12 -0
- package/src/common/Pagination/index.tsx +141 -0
- package/src/common/SegmentButton/SegmentButton.module.scss +44 -0
- package/src/common/SegmentButton/index.tsx +66 -0
- package/src/common/Skeleton/Skeleton.module.scss +80 -0
- package/src/common/Skeleton/index.tsx +48 -0
- package/src/common/SwitchButton/SwitchButton.module.scss +65 -0
- package/src/common/SwitchButton/index.tsx +56 -0
- package/src/index.scss +1 -0
- package/src/index.tsx +17 -1
- package/src/styles/color.scss +94 -0
- package/src/styles/font-face.scss +18 -0
- package/src/styles/font.scss +49 -0
- package/src/styles/scrollbar.scss +71 -0
- package/src/svg.d.ts +4 -2
- package/src/utils/styles/mediaQuery.scss +22 -0
- package/src/utils/ts/allowDecimal.ts +5 -0
- package/src/utils/ts/autoHypen.ts +33 -0
- package/src/utils/ts/calculateMax.ts +24 -0
- package/src/utils/ts/checkIsMobilePlatform.ts +15 -0
- package/src/utils/ts/formatFileSize.ts +16 -0
- package/src/utils/ts/formatMoney.ts +16 -0
- package/src/utils/ts/gradientRatio.ts +61 -0
- package/src/utils/ts/kiloToMega.ts +30 -0
- package/src/utils/ts/maskingPhone.ts +9 -0
- package/src/utils/ts/toQueryString.ts +7 -0
- package/src/utils/ts/valueAsNumber.ts +16 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
.accordion {
|
|
2
|
+
width: 500px;
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
border: 1px solid var(--G-20);
|
|
7
|
+
transition: margin-bottom 0.25s;
|
|
8
|
+
border-radius: 5px;
|
|
9
|
+
|
|
10
|
+
&--visible {
|
|
11
|
+
margin-bottom: 10px;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.button {
|
|
16
|
+
width: 100%;
|
|
17
|
+
background-color: white;
|
|
18
|
+
transition: padding 0.25s;
|
|
19
|
+
display: flex;
|
|
20
|
+
justify-content: space-between;
|
|
21
|
+
align-items: center;
|
|
22
|
+
padding: 20px 10px;
|
|
23
|
+
font-size: 18px;
|
|
24
|
+
font-weight: 500;
|
|
25
|
+
|
|
26
|
+
&__arrow {
|
|
27
|
+
width: 15px;
|
|
28
|
+
height: 15px;
|
|
29
|
+
stroke: var(--G-50);
|
|
30
|
+
transition: transform 0.25s;
|
|
31
|
+
|
|
32
|
+
&--up {
|
|
33
|
+
transform: rotate(180deg);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&--visible {
|
|
38
|
+
padding: 30px 10px;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.wrapper {
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
transition: height 0.25s;
|
|
45
|
+
background-color: white;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.content {
|
|
49
|
+
white-space: pre-wrap;
|
|
50
|
+
font-size: 16px;
|
|
51
|
+
padding: 20px;
|
|
52
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useRef, useState } from 'react';
|
|
2
|
+
import { cn } from '@jk-core/utils';
|
|
3
|
+
import styles from './Accordion.module.scss';
|
|
4
|
+
import DownIcon from './arrow-down.svg';
|
|
5
|
+
|
|
6
|
+
interface AccordionProps {
|
|
7
|
+
/**
|
|
8
|
+
* 아코디언의 내용
|
|
9
|
+
*/
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 아코디언 컴포넌트
|
|
15
|
+
* 클릭 시 내용이 확장되거나 축소되는 UI 컴포넌트입니다.
|
|
16
|
+
*/
|
|
17
|
+
export default function Accordion({ children }: AccordionProps) {
|
|
18
|
+
const contentRef = useRef<HTMLDivElement>(null);
|
|
19
|
+
const [visible, setVisible] = useState(false);
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div className={cn({
|
|
23
|
+
[styles.accordion]: true,
|
|
24
|
+
[styles['accordion--visible']]: visible,
|
|
25
|
+
})}
|
|
26
|
+
>
|
|
27
|
+
<button
|
|
28
|
+
className={cn({
|
|
29
|
+
[styles.button]: true,
|
|
30
|
+
[styles['button--visible']]: visible,
|
|
31
|
+
})}
|
|
32
|
+
type="button"
|
|
33
|
+
onClick={() => setVisible(!visible)}
|
|
34
|
+
>
|
|
35
|
+
Accordion
|
|
36
|
+
<DownIcon className={cn({
|
|
37
|
+
[styles.button__arrow]: true,
|
|
38
|
+
[styles['button__arrow--up']]: visible,
|
|
39
|
+
})}
|
|
40
|
+
/>
|
|
41
|
+
</button>
|
|
42
|
+
<div
|
|
43
|
+
className={cn({
|
|
44
|
+
[styles.wrapper]: true,
|
|
45
|
+
[styles['wrapper--visible']]: visible,
|
|
46
|
+
})}
|
|
47
|
+
style={{ height: visible ? ((contentRef.current?.scrollHeight ?? 0)) : '0px' }}
|
|
48
|
+
>
|
|
49
|
+
<div className={styles.content} ref={contentRef}>
|
|
50
|
+
{children}
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
.breadcrumbs {
|
|
2
|
+
width: fit-content;
|
|
3
|
+
display: flex;
|
|
4
|
+
align-items: center;
|
|
5
|
+
gap: 8px;
|
|
6
|
+
color: var(--G-60);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.separator {
|
|
10
|
+
font-size: 12px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.item {
|
|
14
|
+
display: flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
color: var(--G-60);
|
|
17
|
+
font-size: 15px;
|
|
18
|
+
font-weight: 500;
|
|
19
|
+
|
|
20
|
+
& > svg {
|
|
21
|
+
width: 16px;
|
|
22
|
+
height: 16px;
|
|
23
|
+
stroke: var(--G-60);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&:hover {
|
|
27
|
+
text-decoration: underline;
|
|
28
|
+
|
|
29
|
+
&:hover > svg {
|
|
30
|
+
stroke: var(--G-80);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
&:last-child {
|
|
35
|
+
color: var(--G-80);
|
|
36
|
+
|
|
37
|
+
& > svg {
|
|
38
|
+
stroke: var(--G-80);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
&:hover {
|
|
42
|
+
text-decoration: none;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import styles from './Breadcrumbs.module.scss';
|
|
3
|
+
import HomeIcon from './home.svg';
|
|
4
|
+
|
|
5
|
+
interface BreadcumbsProps {
|
|
6
|
+
/**
|
|
7
|
+
* 자식 요소로 BreadcrumbsItem 컴포넌트를 받습니다.
|
|
8
|
+
* 각 BreadcrumbsItem은 경로를 나타내며, 클릭 시 해당 경로로 이동합니다.
|
|
9
|
+
*/
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Breadcrumbs 컴포넌트
|
|
15
|
+
* 여러 개의 ```<BreadcrumbsItem />```을 자식으로 받아 경로를 표시합니다.
|
|
16
|
+
* 각 ```BreadcrumbsItem```은 경로를 나타내며, 클릭 시 해당 경로로 이동합니다.
|
|
17
|
+
*/
|
|
18
|
+
export default function Breadcrumbs({ children }: BreadcumbsProps) {
|
|
19
|
+
return (
|
|
20
|
+
<div className={styles.breadcrumbs}>
|
|
21
|
+
{Array.isArray(children)
|
|
22
|
+
? children.map((child, idx) => (
|
|
23
|
+
<Fragment key={idx}>
|
|
24
|
+
{idx > 0 && (
|
|
25
|
+
<div className={styles.separator}>
|
|
26
|
+
{'>'}
|
|
27
|
+
</div>
|
|
28
|
+
)}
|
|
29
|
+
{child}
|
|
30
|
+
</Fragment>
|
|
31
|
+
))
|
|
32
|
+
: children}
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface BreadcrumbsItemProps {
|
|
38
|
+
/**
|
|
39
|
+
* BreadcrumbsItem의 자식 요소로 표시될 텍스트입니다.
|
|
40
|
+
* 경로를 나타내며, 클릭 시 해당 경로로 이동합니다.
|
|
41
|
+
*/
|
|
42
|
+
children?: React.ReactNode;
|
|
43
|
+
/**
|
|
44
|
+
* BreadcrumbsItem이 클릭되었을 때 이동할 경로입니다.
|
|
45
|
+
* 기본값은 '/'로 설정되어 있습니다.
|
|
46
|
+
*
|
|
47
|
+
*/
|
|
48
|
+
path: string;
|
|
49
|
+
/**
|
|
50
|
+
* BreadcrumbsItem이 홈 아이콘을 표시할지 여부입니다.
|
|
51
|
+
* 기본값은 false로 설정되어 있습니다.
|
|
52
|
+
* true로 설정하면 홈 아이콘이 표시됩니다.
|
|
53
|
+
*/
|
|
54
|
+
root?: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* BreadcrumbsItem 컴포넌트
|
|
59
|
+
* Breadcrumbs 컴포넌트의 자식으로 사용되며, 경로를 나타냅니다.
|
|
60
|
+
* 클릭 시 해당 경로로 이동합니다.
|
|
61
|
+
* 기본적으로 홈 아이콘과 함께 표시됩니다.
|
|
62
|
+
*/
|
|
63
|
+
export function BreadcrumbsItem({ children, path, root }: BreadcrumbsItemProps) {
|
|
64
|
+
return (
|
|
65
|
+
<button
|
|
66
|
+
className={styles.item}
|
|
67
|
+
type="button"
|
|
68
|
+
onClick={() => {
|
|
69
|
+
window.location.assign(path);
|
|
70
|
+
}}
|
|
71
|
+
>
|
|
72
|
+
{root
|
|
73
|
+
? (
|
|
74
|
+
<>
|
|
75
|
+
<HomeIcon className={styles.icon} />
|
|
76
|
+
{children}
|
|
77
|
+
</>
|
|
78
|
+
)
|
|
79
|
+
: children}
|
|
80
|
+
</button>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
@keyframes loading {
|
|
2
|
+
0%,
|
|
3
|
+
100% {
|
|
4
|
+
transform: scale(1);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
50% {
|
|
8
|
+
transform: scale(1.3);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.loading-dot {
|
|
13
|
+
position: absolute;
|
|
14
|
+
top: 50%;
|
|
15
|
+
left: 50%;
|
|
16
|
+
transform: translate(-50%, -50%);
|
|
17
|
+
display: flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
justify-content: center;
|
|
20
|
+
gap: 5px;
|
|
21
|
+
|
|
22
|
+
div {
|
|
23
|
+
width: 6px;
|
|
24
|
+
height: 6px;
|
|
25
|
+
background-color: var(--white);
|
|
26
|
+
border-radius: 100%;
|
|
27
|
+
|
|
28
|
+
&:nth-child(1) {
|
|
29
|
+
animation: loading 1s infinite;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
&:nth-child(2) {
|
|
33
|
+
animation: loading 1s 0.25s infinite;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
&:nth-child(3) {
|
|
37
|
+
animation: loading 1s 0.5s infinite;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.button {
|
|
43
|
+
position: relative;
|
|
44
|
+
width: fit-content;
|
|
45
|
+
border-radius: 8px;
|
|
46
|
+
padding: 10px 24px;
|
|
47
|
+
transition: background-color 0.1s;
|
|
48
|
+
font-size: 17px;
|
|
49
|
+
font-weight: 500;
|
|
50
|
+
|
|
51
|
+
&__loading {
|
|
52
|
+
color: transparent !important;
|
|
53
|
+
user-select: none;
|
|
54
|
+
pointer-events: none;
|
|
55
|
+
cursor: default !important;
|
|
56
|
+
|
|
57
|
+
&:hover,
|
|
58
|
+
&:active {
|
|
59
|
+
background-color: inherit;
|
|
60
|
+
border-color: inherit;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
&__tertiary {
|
|
65
|
+
border: 1px solid var(--G-40);
|
|
66
|
+
|
|
67
|
+
&:hover {
|
|
68
|
+
background-color: var(--G-5);
|
|
69
|
+
border-color: var(--G-80);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
&:active {
|
|
73
|
+
background-color: var(--G-10);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
&__secondary {
|
|
78
|
+
color: var(--P-50);
|
|
79
|
+
background-color: var(--P-5);
|
|
80
|
+
border: 1px solid var(--P-50);
|
|
81
|
+
|
|
82
|
+
&:hover {
|
|
83
|
+
background-color: var(--P-10);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
&:active {
|
|
87
|
+
background-color: var(--P-20);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
&__primary {
|
|
92
|
+
color: var(--white);
|
|
93
|
+
background-color: var(--P-50);
|
|
94
|
+
|
|
95
|
+
&:hover {
|
|
96
|
+
background-color: var(--P-60);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
&:active {
|
|
100
|
+
background-color: var(--P-70);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
&__cancel {
|
|
105
|
+
color: var(--white);
|
|
106
|
+
background-color: var(--Point-50);
|
|
107
|
+
|
|
108
|
+
&:hover {
|
|
109
|
+
background-color: var(--Point-60);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
&:active {
|
|
113
|
+
background-color: var(--Point-70);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
&__disabled {
|
|
118
|
+
color: var(--white);
|
|
119
|
+
background-color: var(--G-40) !important;
|
|
120
|
+
cursor: default;
|
|
121
|
+
|
|
122
|
+
&:hover {
|
|
123
|
+
background-color: var(--P-60);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
&:active {
|
|
127
|
+
background-color: var(--P-70);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { cn } from '@jk-core/utils';
|
|
2
|
+
import styles from './Button.module.scss';
|
|
3
|
+
|
|
4
|
+
interface Props extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
5
|
+
/** 버튼 내용 */
|
|
6
|
+
text: string;
|
|
7
|
+
/** 버튼 등급 (Primary, Secondary, Tertiary, Cancel) */
|
|
8
|
+
grade?: 'tertiary' | 'secondary' | 'primary' | 'cancel';
|
|
9
|
+
/** 버튼 비활성화 여부 */
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
/** 버튼 클래스 */
|
|
12
|
+
className?: string;
|
|
13
|
+
/** 로딩 중 여부, 버튼 내부 스피너 표시 */
|
|
14
|
+
isLoading?: boolean;
|
|
15
|
+
/** 버튼 클릭 이벤트 핸들러 */
|
|
16
|
+
onClick?: () => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 공용 버튼 컴포넌트입니다.
|
|
21
|
+
*
|
|
22
|
+
* 다양한 등급(grade)과 상태(로딩, 비활성화 등)를 지원하며, 텍스트와 클릭 이벤트를 전달할 수 있습니다.
|
|
23
|
+
*
|
|
24
|
+
* - `grade` prop을 통해 버튼의 스타일(Primary, Secondary, Tertiary, Cancel)을 지정할 수 있습니다.
|
|
25
|
+
* - `isLoading`이 true일 때 로딩 애니메이션이 표시됩니다.
|
|
26
|
+
* - `disabled`가 true이면 버튼이 비활성화됩니다.
|
|
27
|
+
* - `text` prop으로 버튼에 표시할 텍스트를 지정합니다.
|
|
28
|
+
* - 추가적으로 button의 모든 기본 속성(React.)을 지원합니다.
|
|
29
|
+
*/
|
|
30
|
+
export function Button({
|
|
31
|
+
text, grade = 'primary', disabled = false, onClick, className = '', isLoading = false, ...props
|
|
32
|
+
}: Props) {
|
|
33
|
+
return (
|
|
34
|
+
<button
|
|
35
|
+
className={cn({
|
|
36
|
+
[styles.button]: true,
|
|
37
|
+
[styles.button__loading]: isLoading,
|
|
38
|
+
[styles.button__disabled]: !!disabled,
|
|
39
|
+
[styles.button__tertiary]: grade === 'tertiary',
|
|
40
|
+
[styles.button__secondary]: grade === 'secondary',
|
|
41
|
+
[styles.button__primary]: grade === 'primary',
|
|
42
|
+
[styles.button__cancel]: grade === 'cancel',
|
|
43
|
+
[className]: !!className,
|
|
44
|
+
})}
|
|
45
|
+
type="button"
|
|
46
|
+
disabled={disabled}
|
|
47
|
+
onClick={onClick}
|
|
48
|
+
{...props}
|
|
49
|
+
>
|
|
50
|
+
{text}
|
|
51
|
+
{isLoading && (
|
|
52
|
+
<div className={styles['loading-dot']}>
|
|
53
|
+
<div />
|
|
54
|
+
<div />
|
|
55
|
+
<div />
|
|
56
|
+
</div>
|
|
57
|
+
)}
|
|
58
|
+
</button>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
.card {
|
|
2
|
+
width: 100%;
|
|
3
|
+
background-color: var(--white);
|
|
4
|
+
border-radius: 5px;
|
|
5
|
+
padding: 10px;
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
box-shadow:
|
|
9
|
+
0px 2px 1px -1px rgba(0, 0, 0, 0.2),
|
|
10
|
+
0px 1px 1px 0px rgba(0, 0, 0, 0.14),
|
|
11
|
+
0px 1px 3px 0px rgba(0, 0, 0, 0.12),
|
|
12
|
+
0px 1px 3px 0px rgba(0, 0, 0, 0.14);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.title {
|
|
16
|
+
color: var(--G-80);
|
|
17
|
+
margin-bottom: 10px;
|
|
18
|
+
font-size: 20px;
|
|
19
|
+
font-weight: 600;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.content {
|
|
23
|
+
color: var(--G-60);
|
|
24
|
+
white-space: pre-wrap;
|
|
25
|
+
font-size: 16px;
|
|
26
|
+
font-weight: 500;
|
|
27
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import styles from './Card.module.scss';
|
|
2
|
+
|
|
3
|
+
interface CardProps {
|
|
4
|
+
title: string | React.ReactNode;
|
|
5
|
+
children?: React.ReactNode;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export default function Card({ title, children }:CardProps) {
|
|
9
|
+
return (
|
|
10
|
+
<div className={styles.card}>
|
|
11
|
+
<div className={styles.title}>
|
|
12
|
+
{title}
|
|
13
|
+
</div>
|
|
14
|
+
<div className={styles.content}>
|
|
15
|
+
{children}
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
@use "@/styles/scrollbar.scss" as scrollbar;
|
|
2
|
+
|
|
3
|
+
.wrapper {
|
|
4
|
+
position: relative;
|
|
5
|
+
width: fit-content;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.title {
|
|
9
|
+
width: 180px;
|
|
10
|
+
height: 50px;
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
justify-content: space-between;
|
|
14
|
+
background-color: var(--white);
|
|
15
|
+
border: 1px solid #ccc;
|
|
16
|
+
border-radius: 5px;
|
|
17
|
+
padding: 10px;
|
|
18
|
+
font-size: 16px;
|
|
19
|
+
cursor: pointer;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.icon {
|
|
23
|
+
width: 15px;
|
|
24
|
+
height: 15px;
|
|
25
|
+
stroke: var(--G-60);
|
|
26
|
+
transition: transform 0.25s;
|
|
27
|
+
|
|
28
|
+
&--up {
|
|
29
|
+
transform: rotate(180deg);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.list-portal {
|
|
34
|
+
display: contents;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.list-wrapper {
|
|
38
|
+
height: 0;
|
|
39
|
+
position: absolute;
|
|
40
|
+
isolation: isolate;
|
|
41
|
+
background-color: var(--white);
|
|
42
|
+
transition: height 0.25s;
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
border: 1px solid var(--G-30);
|
|
45
|
+
z-index: 10000;
|
|
46
|
+
|
|
47
|
+
&--up {
|
|
48
|
+
border-radius: 0 0 5px 5px;
|
|
49
|
+
box-shadow: 0 2px 10px 4px rgba(0, 0, 0, 0.2);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
&--down {
|
|
53
|
+
border-radius: 5px 5px 0 0;
|
|
54
|
+
box-shadow: 0 -2px 10px 2px rgba(0, 0, 0, 0.2);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.list {
|
|
59
|
+
position: relative;
|
|
60
|
+
display: flex;
|
|
61
|
+
flex-direction: column;
|
|
62
|
+
overflow-y: scroll;
|
|
63
|
+
max-height: 300px;
|
|
64
|
+
|
|
65
|
+
@include scrollbar.custom-scrollbar($background: var(--G-10), $color: var(--G-50));
|
|
66
|
+
|
|
67
|
+
&__search {
|
|
68
|
+
position: sticky;
|
|
69
|
+
top: 0;
|
|
70
|
+
width: 100%;
|
|
71
|
+
height: 40px;
|
|
72
|
+
flex-shrink: 0;
|
|
73
|
+
display: flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
gap: 5px;
|
|
76
|
+
border: none;
|
|
77
|
+
border-bottom: 1px solid var(--G-20);
|
|
78
|
+
font-size: 16px;
|
|
79
|
+
outline: none;
|
|
80
|
+
box-sizing: border-box;
|
|
81
|
+
padding: 8px;
|
|
82
|
+
border-radius: 5px 5px 0 0;
|
|
83
|
+
background-color: var(--white);
|
|
84
|
+
|
|
85
|
+
&:focus-within {
|
|
86
|
+
outline: 2px solid var(--P-20);
|
|
87
|
+
outline-offset: -2px;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
& > svg {
|
|
91
|
+
width: 11px;
|
|
92
|
+
height: 11px;
|
|
93
|
+
flex-shrink: 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
& > input {
|
|
97
|
+
border: none;
|
|
98
|
+
outline: none;
|
|
99
|
+
background-color: transparent;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
&__item {
|
|
104
|
+
min-height: 50px;
|
|
105
|
+
padding: 8px;
|
|
106
|
+
|
|
107
|
+
& + & {
|
|
108
|
+
border-top: 1px solid var(--G-20);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
&:hover {
|
|
112
|
+
background-color: var(--G-5);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
&--selected {
|
|
116
|
+
background-color: var(--G-20);
|
|
117
|
+
font-weight: 600;
|
|
118
|
+
|
|
119
|
+
&:hover {
|
|
120
|
+
background-color: var(--G-20);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
&__empty {
|
|
126
|
+
height: 50px;
|
|
127
|
+
display: flex;
|
|
128
|
+
align-items: center;
|
|
129
|
+
justify-content: center;
|
|
130
|
+
padding: 10px;
|
|
131
|
+
text-align: center;
|
|
132
|
+
color: var(--G-50);
|
|
133
|
+
font-size: 16px;
|
|
134
|
+
}
|
|
135
|
+
}
|