@mzc-fe/design-system 0.0.5 → 0.0.7-rc.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/components/accordion/accordion.tsx +114 -0
- package/components/accordion/index.ts +1 -0
- package/components/alert/alert.tsx +97 -0
- package/components/alert/index.ts +1 -0
- package/components/alert-dialog/alert-dialog.tsx +190 -0
- package/components/alert-dialog/index.ts +1 -0
- package/components/aspect-ratio/aspect-ratio.tsx +23 -0
- package/components/aspect-ratio/index.ts +1 -0
- package/components/avatar/avatar.tsx +62 -0
- package/components/avatar/index.ts +1 -0
- package/components/badge/badge.tsx +58 -0
- package/components/badge/index.ts +1 -0
- package/components/breadcrumb/breadcrumb.tsx +132 -0
- package/components/breadcrumb/index.ts +1 -0
- package/components/button/button.tsx +77 -0
- package/components/button/index.ts +1 -0
- package/components/button-group/button-group.tsx +99 -0
- package/components/button-group/index.ts +1 -0
- package/components/calendar/calendar.tsx +235 -0
- package/components/calendar/index.ts +1 -0
- package/components/card/card.tsx +107 -0
- package/components/card/index.ts +1 -0
- package/components/carousel/carousel.tsx +263 -0
- package/components/carousel/index.ts +1 -0
- package/components/chart/chart.tsx +377 -0
- package/components/chart/index.ts +1 -0
- package/components/checkbox/checkbox.tsx +41 -0
- package/components/checkbox/index.ts +1 -0
- package/components/collapsible/collapsible.tsx +44 -0
- package/components/collapsible/index.ts +1 -0
- package/components/command/command.tsx +201 -0
- package/components/command/index.ts +1 -0
- package/components/context-menu/context-menu.tsx +270 -0
- package/components/context-menu/index.ts +1 -0
- package/components/dialog/dialog.tsx +166 -0
- package/components/dialog/index.ts +1 -0
- package/components/drawer/drawer.tsx +154 -0
- package/components/drawer/index.ts +1 -0
- package/components/dropdown-menu/dropdown-menu.tsx +276 -0
- package/components/dropdown-menu/index.ts +1 -0
- package/components/empty/empty.tsx +129 -0
- package/components/empty/index.ts +1 -0
- package/components/field/field.tsx +272 -0
- package/components/field/index.ts +1 -0
- package/components/form/form.tsx +197 -0
- package/components/form/index.ts +1 -0
- package/components/hover-card/hover-card.tsx +57 -0
- package/components/hover-card/index.ts +1 -0
- package/components/input/index.ts +1 -0
- package/components/input/input.tsx +31 -0
- package/components/input-group/index.ts +1 -0
- package/components/input-group/input-group.tsx +189 -0
- package/components/input-otp/index.ts +1 -0
- package/components/input-otp/input-otp.tsx +99 -0
- package/components/item/index.ts +1 -0
- package/components/item/item.tsx +225 -0
- package/components/kbd/index.ts +1 -0
- package/components/kbd/kbd.tsx +38 -0
- package/components/label/index.ts +1 -0
- package/components/label/label.tsx +33 -0
- package/components/menubar/index.ts +1 -0
- package/components/menubar/menubar.tsx +299 -0
- package/components/navigation-menu/index.ts +1 -0
- package/components/navigation-menu/navigation-menu.tsx +194 -0
- package/components/pagination/index.ts +1 -0
- package/components/pagination/pagination.tsx +153 -0
- package/components/popover/index.ts +1 -0
- package/components/popover/popover.tsx +106 -0
- package/components/progress/index.ts +1 -0
- package/components/progress/progress.tsx +39 -0
- package/components/radio-group/index.ts +1 -0
- package/components/radio-group/radio-group.tsx +57 -0
- package/components/resizable/index.ts +1 -0
- package/components/resizable/resizable.tsx +73 -0
- package/components/scroll-area/index.ts +1 -0
- package/components/scroll-area/scroll-area.tsx +72 -0
- package/components/select/index.ts +1 -0
- package/components/select/select.tsx +213 -0
- package/components/separator/index.ts +1 -0
- package/components/separator/separator.tsx +39 -0
- package/components/sheet/index.ts +1 -0
- package/components/sheet/sheet.tsx +160 -0
- package/components/sidebar/index.ts +1 -0
- package/components/sidebar/sidebar.tsx +776 -0
- package/components/skeleton/index.ts +1 -0
- package/components/skeleton/skeleton.tsx +21 -0
- package/components/slider/index.ts +1 -0
- package/components/slider/slider.tsx +75 -0
- package/components/sonner/index.ts +2 -0
- package/components/sonner/sonner.tsx +52 -0
- package/components/spinner/index.ts +1 -0
- package/components/spinner/spinner.tsx +26 -0
- package/components/switch/index.ts +1 -0
- package/components/switch/switch.tsx +39 -0
- package/components/table/index.ts +1 -0
- package/components/table/table.tsx +140 -0
- package/components/tabs/index.ts +1 -0
- package/components/tabs/tabs.tsx +94 -0
- package/components/textarea/index.ts +1 -0
- package/components/textarea/textarea.tsx +26 -0
- package/components/toggle/index.ts +1 -0
- package/components/toggle/toggle.tsx +58 -0
- package/components/toggle-group/index.ts +1 -0
- package/components/toggle-group/toggle-group.tsx +97 -0
- package/components/tooltip/index.ts +1 -0
- package/components/tooltip/tooltip.tsx +82 -0
- package/dist/components/accordion/accordion.d.ts +50 -0
- package/dist/components/alert/alert.d.ts +31 -0
- package/dist/components/alert-dialog/alert-dialog.d.ts +35 -0
- package/dist/components/aspect-ratio/aspect-ratio.d.ts +12 -0
- package/dist/components/avatar/avatar.d.ts +11 -0
- package/dist/components/badge/badge.d.ts +12 -0
- package/dist/components/breadcrumb/breadcrumb.d.ts +23 -0
- package/dist/components/button/button.d.ts +15 -0
- package/dist/components/button-group/button-group.d.ts +16 -0
- package/dist/components/calendar/calendar.d.ts +15 -0
- package/dist/components/card/card.d.ts +15 -0
- package/dist/components/carousel/carousel.d.ts +24 -0
- package/dist/components/chart/chart.d.ts +20 -0
- package/dist/components/checkbox/checkbox.d.ts +9 -0
- package/dist/components/collapsible/collapsible.d.ts +13 -0
- package/dist/components/command/command.d.ts +18 -0
- package/dist/components/context-menu/context-menu.d.ts +18 -0
- package/dist/components/dialog/dialog.d.ts +25 -0
- package/dist/components/drawer/drawer.d.ts +18 -0
- package/dist/components/dropdown-menu/dropdown-menu.d.ts +21 -0
- package/dist/components/empty/empty.d.ts +25 -0
- package/dist/components/field/field.d.ts +26 -0
- package/dist/components/form/form.d.ts +30 -1
- package/dist/components/hover-card/hover-card.d.ts +13 -0
- package/dist/components/input/input.d.ts +10 -0
- package/dist/components/input-group/input-group.d.ts +19 -0
- package/dist/components/input-otp/input-otp.d.ts +23 -0
- package/dist/components/item/item.d.ts +33 -1
- package/dist/components/kbd/kbd.d.ts +10 -0
- package/dist/components/label/label.d.ts +9 -0
- package/dist/components/menubar/menubar.d.ts +25 -0
- package/dist/components/navigation-menu/navigation-menu.d.ts +26 -0
- package/dist/components/pagination/pagination.d.ts +26 -0
- package/dist/components/popover/popover.d.ts +17 -0
- package/dist/components/progress/progress.d.ts +10 -0
- package/dist/components/radio-group/radio-group.d.ts +12 -0
- package/dist/components/resizable/resizable.d.ts +19 -0
- package/dist/components/scroll-area/scroll-area.d.ts +14 -0
- package/dist/components/select/select.d.ts +25 -0
- package/dist/components/separator/separator.d.ts +11 -0
- package/dist/components/sheet/sheet.d.ts +23 -0
- package/dist/components/sidebar/sidebar.d.ts +50 -0
- package/dist/components/skeleton/skeleton.d.ts +8 -0
- package/dist/components/slider/slider.d.ts +12 -0
- package/dist/components/sonner/sonner.d.ts +14 -0
- package/dist/components/spinner/spinner.d.ts +9 -0
- package/dist/components/switch/switch.d.ts +8 -0
- package/dist/components/table/table.d.ts +26 -0
- package/dist/components/tabs/tabs.d.ts +16 -6
- package/dist/components/textarea/textarea.d.ts +8 -0
- package/dist/components/toggle/toggle.d.ts +13 -0
- package/dist/components/toggle-group/toggle-group.d.ts +1 -0
- package/dist/components/tooltip/tooltip.d.ts +21 -0
- package/dist/design-system.css +1 -1
- package/dist/design-system.es.js +3493 -28470
- package/dist/design-system.umd.js +4 -257
- package/dist/index.d.ts +1 -1
- package/foundations/ThemeProvider.tsx +77 -0
- package/foundations/color.css +232 -0
- package/foundations/palette.css +249 -0
- package/foundations/spacing.css +8 -0
- package/foundations/typography.css +143 -0
- package/hooks/use-mobile.ts +19 -0
- package/index.css +173 -0
- package/index.ts +339 -0
- package/lib/utils.ts +6 -0
- package/package.json +40 -19
- package/README.md +0 -184
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Popover as PopoverPrimitive } from "radix-ui"
|
|
4
|
+
import * as React from "react"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 트리거 요소 근처에 팝업 콘텐츠를 표시하는 팝오버 컴포넌트입니다.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <Popover>
|
|
14
|
+
* <PopoverTrigger>열기</PopoverTrigger>
|
|
15
|
+
* <PopoverContent>팝오버 내용</PopoverContent>
|
|
16
|
+
* </Popover>
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
function Popover({
|
|
20
|
+
...props
|
|
21
|
+
}: React.ComponentProps<typeof PopoverPrimitive.Root>) {
|
|
22
|
+
return <PopoverPrimitive.Root data-slot="popover" {...props} />
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** 팝오버를 열기 위한 트리거 요소입니다. */
|
|
26
|
+
function PopoverTrigger({
|
|
27
|
+
...props
|
|
28
|
+
}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
|
|
29
|
+
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 팝오버의 콘텐츠 영역입니다.
|
|
34
|
+
* @param props.align - 정렬 방식 ('start' | 'center' | 'end')
|
|
35
|
+
* @param props.sideOffset - 트리거와의 간격 (기본값: 4)
|
|
36
|
+
*/
|
|
37
|
+
function PopoverContent({
|
|
38
|
+
className,
|
|
39
|
+
align = "center",
|
|
40
|
+
sideOffset = 4,
|
|
41
|
+
...props
|
|
42
|
+
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
|
|
43
|
+
return (
|
|
44
|
+
<PopoverPrimitive.Portal>
|
|
45
|
+
<PopoverPrimitive.Content
|
|
46
|
+
data-slot="popover-content"
|
|
47
|
+
align={align}
|
|
48
|
+
sideOffset={sideOffset}
|
|
49
|
+
className={cn(
|
|
50
|
+
"bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 flex flex-col gap-2.5 rounded-lg p-2.5 text-sm shadow-md ring-1 duration-100 z-50 w-72 origin-(--radix-popover-content-transform-origin) outline-hidden",
|
|
51
|
+
className
|
|
52
|
+
)}
|
|
53
|
+
{...props}
|
|
54
|
+
/>
|
|
55
|
+
</PopoverPrimitive.Portal>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function PopoverAnchor({
|
|
60
|
+
...props
|
|
61
|
+
}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
|
|
62
|
+
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function PopoverHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
66
|
+
return (
|
|
67
|
+
<div
|
|
68
|
+
data-slot="popover-header"
|
|
69
|
+
className={cn("flex flex-col gap-0.5 text-sm", className)}
|
|
70
|
+
{...props}
|
|
71
|
+
/>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function PopoverTitle({ className, ...props }: React.ComponentProps<"h2">) {
|
|
76
|
+
return (
|
|
77
|
+
<div
|
|
78
|
+
data-slot="popover-title"
|
|
79
|
+
className={cn("font-medium", className)}
|
|
80
|
+
{...props}
|
|
81
|
+
/>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function PopoverDescription({
|
|
86
|
+
className,
|
|
87
|
+
...props
|
|
88
|
+
}: React.ComponentProps<"p">) {
|
|
89
|
+
return (
|
|
90
|
+
<p
|
|
91
|
+
data-slot="popover-description"
|
|
92
|
+
className={cn("text-muted-foreground", className)}
|
|
93
|
+
{...props}
|
|
94
|
+
/>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export {
|
|
99
|
+
Popover,
|
|
100
|
+
PopoverAnchor,
|
|
101
|
+
PopoverContent,
|
|
102
|
+
PopoverDescription,
|
|
103
|
+
PopoverHeader,
|
|
104
|
+
PopoverTitle,
|
|
105
|
+
PopoverTrigger
|
|
106
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./progress";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as ProgressPrimitive from "@radix-ui/react-progress"
|
|
3
|
+
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 작업 진행 상태를 시각적으로 표시하는 프로그레스 바 컴포넌트입니다.
|
|
8
|
+
*
|
|
9
|
+
* @param props.value - 진행률 (0-100)
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <Progress value={45} />
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
function Progress({
|
|
17
|
+
className,
|
|
18
|
+
value,
|
|
19
|
+
...props
|
|
20
|
+
}: React.ComponentProps<typeof ProgressPrimitive.Root>) {
|
|
21
|
+
return (
|
|
22
|
+
<ProgressPrimitive.Root
|
|
23
|
+
data-slot="progress"
|
|
24
|
+
className={cn(
|
|
25
|
+
"bg-primary/20 relative h-2 w-full overflow-hidden rounded-full",
|
|
26
|
+
className
|
|
27
|
+
)}
|
|
28
|
+
{...props}
|
|
29
|
+
>
|
|
30
|
+
<ProgressPrimitive.Indicator
|
|
31
|
+
data-slot="progress-indicator"
|
|
32
|
+
className="bg-primary h-full w-full flex-1 transition-all"
|
|
33
|
+
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
|
|
34
|
+
/>
|
|
35
|
+
</ProgressPrimitive.Root>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { Progress }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./radio-group";
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
|
|
5
|
+
import { CircleIcon } from "lucide-react"
|
|
6
|
+
|
|
7
|
+
import { cn } from "@/lib/utils"
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 여러 옵션 중 하나를 선택하는 라디오 그룹 컴포넌트입니다.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* <RadioGroup defaultValue="option1">
|
|
15
|
+
* <RadioGroupItem value="option1" />
|
|
16
|
+
* <RadioGroupItem value="option2" />
|
|
17
|
+
* </RadioGroup>
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
function RadioGroup({
|
|
21
|
+
className,
|
|
22
|
+
...props
|
|
23
|
+
}: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {
|
|
24
|
+
return (
|
|
25
|
+
<RadioGroupPrimitive.Root
|
|
26
|
+
data-slot="radio-group"
|
|
27
|
+
className={cn("grid gap-3", className)}
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** 라디오 그룹의 개별 옵션 아이템입니다. */
|
|
34
|
+
function RadioGroupItem({
|
|
35
|
+
className,
|
|
36
|
+
...props
|
|
37
|
+
}: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {
|
|
38
|
+
return (
|
|
39
|
+
<RadioGroupPrimitive.Item
|
|
40
|
+
data-slot="radio-group-item"
|
|
41
|
+
className={cn(
|
|
42
|
+
"border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 aspect-square size-4 shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
|
43
|
+
className
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
>
|
|
47
|
+
<RadioGroupPrimitive.Indicator
|
|
48
|
+
data-slot="radio-group-indicator"
|
|
49
|
+
className="relative flex items-center justify-center"
|
|
50
|
+
>
|
|
51
|
+
<CircleIcon className="fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2" />
|
|
52
|
+
</RadioGroupPrimitive.Indicator>
|
|
53
|
+
</RadioGroupPrimitive.Item>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export { RadioGroup, RadioGroupItem }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./resizable";
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { GripVerticalIcon } from "lucide-react"
|
|
3
|
+
import * as ResizablePrimitive from "react-resizable-panels"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 크기 조절 가능한 패널 그룹 컴포넌트입니다.
|
|
9
|
+
*
|
|
10
|
+
* @param props.direction - 패널 방향 ('horizontal' | 'vertical')
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* <ResizablePanelGroup direction="horizontal">
|
|
15
|
+
* <ResizablePanel>패널 1</ResizablePanel>
|
|
16
|
+
* <ResizableHandle />
|
|
17
|
+
* <ResizablePanel>패널 2</ResizablePanel>
|
|
18
|
+
* </ResizablePanelGroup>
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
function ResizablePanelGroup({
|
|
22
|
+
className,
|
|
23
|
+
...props
|
|
24
|
+
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) {
|
|
25
|
+
return (
|
|
26
|
+
<ResizablePrimitive.PanelGroup
|
|
27
|
+
data-slot="resizable-panel-group"
|
|
28
|
+
className={cn(
|
|
29
|
+
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
|
|
30
|
+
className
|
|
31
|
+
)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** 크기 조절 가능한 패널입니다. */
|
|
38
|
+
function ResizablePanel({
|
|
39
|
+
...props
|
|
40
|
+
}: React.ComponentProps<typeof ResizablePrimitive.Panel>) {
|
|
41
|
+
return <ResizablePrimitive.Panel data-slot="resizable-panel" {...props} />
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* 패널 크기 조절 핸들입니다.
|
|
46
|
+
* @param props.withHandle - 드래그 핸들 아이콘 표시 여부
|
|
47
|
+
*/
|
|
48
|
+
function ResizableHandle({
|
|
49
|
+
withHandle,
|
|
50
|
+
className,
|
|
51
|
+
...props
|
|
52
|
+
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
|
|
53
|
+
withHandle?: boolean
|
|
54
|
+
}) {
|
|
55
|
+
return (
|
|
56
|
+
<ResizablePrimitive.PanelResizeHandle
|
|
57
|
+
data-slot="resizable-handle"
|
|
58
|
+
className={cn(
|
|
59
|
+
"bg-border focus-visible:ring-ring relative flex w-px items-center justify-center after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-offset-1 focus-visible:outline-hidden data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:translate-x-0 data-[panel-group-direction=vertical]:after:-translate-y-1/2 [&[data-panel-group-direction=vertical]>div]:rotate-90",
|
|
60
|
+
className
|
|
61
|
+
)}
|
|
62
|
+
{...props}
|
|
63
|
+
>
|
|
64
|
+
{withHandle && (
|
|
65
|
+
<div className="bg-border z-10 flex h-4 w-3 items-center justify-center rounded-xs border">
|
|
66
|
+
<GripVerticalIcon className="size-2.5" />
|
|
67
|
+
</div>
|
|
68
|
+
)}
|
|
69
|
+
</ResizablePrimitive.PanelResizeHandle>
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export { ResizablePanelGroup, ResizablePanel, ResizableHandle }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./scroll-area";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 커스텀 스크롤바를 제공하는 스크롤 영역 컴포넌트입니다.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* <ScrollArea className="h-[200px]">
|
|
14
|
+
* <div>스크롤 가능한 콘텐츠</div>
|
|
15
|
+
* </ScrollArea>
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
function ScrollArea({
|
|
19
|
+
className,
|
|
20
|
+
children,
|
|
21
|
+
...props
|
|
22
|
+
}: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {
|
|
23
|
+
return (
|
|
24
|
+
<ScrollAreaPrimitive.Root
|
|
25
|
+
data-slot="scroll-area"
|
|
26
|
+
className={cn("relative", className)}
|
|
27
|
+
{...props}
|
|
28
|
+
>
|
|
29
|
+
<ScrollAreaPrimitive.Viewport
|
|
30
|
+
data-slot="scroll-area-viewport"
|
|
31
|
+
className="focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1"
|
|
32
|
+
>
|
|
33
|
+
{children}
|
|
34
|
+
</ScrollAreaPrimitive.Viewport>
|
|
35
|
+
<ScrollBar />
|
|
36
|
+
<ScrollAreaPrimitive.Corner />
|
|
37
|
+
</ScrollAreaPrimitive.Root>
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 스크롤바 컴포넌트입니다.
|
|
43
|
+
* @param props.orientation - 스크롤바 방향 ('vertical' | 'horizontal')
|
|
44
|
+
*/
|
|
45
|
+
function ScrollBar({
|
|
46
|
+
className,
|
|
47
|
+
orientation = "vertical",
|
|
48
|
+
...props
|
|
49
|
+
}: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
|
|
50
|
+
return (
|
|
51
|
+
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
|
52
|
+
data-slot="scroll-area-scrollbar"
|
|
53
|
+
orientation={orientation}
|
|
54
|
+
className={cn(
|
|
55
|
+
"flex touch-none p-px transition-colors select-none",
|
|
56
|
+
orientation === "vertical" &&
|
|
57
|
+
"h-full w-2.5 border-l border-l-transparent",
|
|
58
|
+
orientation === "horizontal" &&
|
|
59
|
+
"h-2.5 flex-col border-t border-t-transparent",
|
|
60
|
+
className
|
|
61
|
+
)}
|
|
62
|
+
{...props}
|
|
63
|
+
>
|
|
64
|
+
<ScrollAreaPrimitive.ScrollAreaThumb
|
|
65
|
+
data-slot="scroll-area-thumb"
|
|
66
|
+
className="bg-border relative flex-1 rounded-full"
|
|
67
|
+
/>
|
|
68
|
+
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { ScrollArea, ScrollBar }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./select";
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as SelectPrimitive from "@radix-ui/react-select"
|
|
3
|
+
import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 옵션 목록에서 하나의 값을 선택하는 셀렉트 컴포넌트입니다.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* <Select>
|
|
13
|
+
* <SelectTrigger>
|
|
14
|
+
* <SelectValue placeholder="선택하세요" />
|
|
15
|
+
* </SelectTrigger>
|
|
16
|
+
* <SelectContent>
|
|
17
|
+
* <SelectItem value="1">옵션 1</SelectItem>
|
|
18
|
+
* <SelectItem value="2">옵션 2</SelectItem>
|
|
19
|
+
* </SelectContent>
|
|
20
|
+
* </Select>
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
function Select({
|
|
24
|
+
...props
|
|
25
|
+
}: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
|
26
|
+
return <SelectPrimitive.Root data-slot="select" {...props} />
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function SelectGroup({
|
|
30
|
+
...props
|
|
31
|
+
}: React.ComponentProps<typeof SelectPrimitive.Group>) {
|
|
32
|
+
return <SelectPrimitive.Group data-slot="select-group" {...props} />
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function SelectValue({
|
|
36
|
+
...props
|
|
37
|
+
}: React.ComponentProps<typeof SelectPrimitive.Value>) {
|
|
38
|
+
return <SelectPrimitive.Value data-slot="select-value" {...props} />
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 셀렉트 트리거 버튼입니다.
|
|
43
|
+
* @param props.size - 크기 ('sm' | 'default')
|
|
44
|
+
*/
|
|
45
|
+
function SelectTrigger({
|
|
46
|
+
className,
|
|
47
|
+
size = "default",
|
|
48
|
+
children,
|
|
49
|
+
...props
|
|
50
|
+
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
|
|
51
|
+
size?: "sm" | "default"
|
|
52
|
+
}) {
|
|
53
|
+
return (
|
|
54
|
+
<SelectPrimitive.Trigger
|
|
55
|
+
data-slot="select-trigger"
|
|
56
|
+
data-size={size}
|
|
57
|
+
className={cn(
|
|
58
|
+
"border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
59
|
+
className
|
|
60
|
+
)}
|
|
61
|
+
{...props}
|
|
62
|
+
>
|
|
63
|
+
{children}
|
|
64
|
+
<SelectPrimitive.Icon asChild>
|
|
65
|
+
<ChevronDownIcon className="size-4 opacity-50" />
|
|
66
|
+
</SelectPrimitive.Icon>
|
|
67
|
+
</SelectPrimitive.Trigger>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 셀렉트 옵션 목록 콘텐츠입니다.
|
|
73
|
+
* @param props.position - 위치 정렬 방식 ('item-aligned' | 'popper')
|
|
74
|
+
*/
|
|
75
|
+
function SelectContent({
|
|
76
|
+
className,
|
|
77
|
+
children,
|
|
78
|
+
position = "item-aligned",
|
|
79
|
+
align = "center",
|
|
80
|
+
...props
|
|
81
|
+
}: React.ComponentProps<typeof SelectPrimitive.Content>) {
|
|
82
|
+
return (
|
|
83
|
+
<SelectPrimitive.Portal>
|
|
84
|
+
<SelectPrimitive.Content
|
|
85
|
+
data-slot="select-content"
|
|
86
|
+
className={cn(
|
|
87
|
+
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
|
|
88
|
+
position === "popper" &&
|
|
89
|
+
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
90
|
+
className
|
|
91
|
+
)}
|
|
92
|
+
position={position}
|
|
93
|
+
align={align}
|
|
94
|
+
{...props}
|
|
95
|
+
>
|
|
96
|
+
<SelectScrollUpButton />
|
|
97
|
+
<SelectPrimitive.Viewport
|
|
98
|
+
className={cn(
|
|
99
|
+
"p-1",
|
|
100
|
+
position === "popper" &&
|
|
101
|
+
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
|
|
102
|
+
)}
|
|
103
|
+
>
|
|
104
|
+
{children}
|
|
105
|
+
</SelectPrimitive.Viewport>
|
|
106
|
+
<SelectScrollDownButton />
|
|
107
|
+
</SelectPrimitive.Content>
|
|
108
|
+
</SelectPrimitive.Portal>
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function SelectLabel({
|
|
113
|
+
className,
|
|
114
|
+
...props
|
|
115
|
+
}: React.ComponentProps<typeof SelectPrimitive.Label>) {
|
|
116
|
+
return (
|
|
117
|
+
<SelectPrimitive.Label
|
|
118
|
+
data-slot="select-label"
|
|
119
|
+
className={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
|
|
120
|
+
{...props}
|
|
121
|
+
/>
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** 셀렉트 옵션 아이템입니다. */
|
|
126
|
+
function SelectItem({
|
|
127
|
+
className,
|
|
128
|
+
children,
|
|
129
|
+
...props
|
|
130
|
+
}: React.ComponentProps<typeof SelectPrimitive.Item>) {
|
|
131
|
+
return (
|
|
132
|
+
<SelectPrimitive.Item
|
|
133
|
+
data-slot="select-item"
|
|
134
|
+
className={cn(
|
|
135
|
+
"focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
|
136
|
+
className
|
|
137
|
+
)}
|
|
138
|
+
{...props}
|
|
139
|
+
>
|
|
140
|
+
<span
|
|
141
|
+
data-slot="select-item-indicator"
|
|
142
|
+
className="absolute right-2 flex size-3.5 items-center justify-center"
|
|
143
|
+
>
|
|
144
|
+
<SelectPrimitive.ItemIndicator>
|
|
145
|
+
<CheckIcon className="size-4" />
|
|
146
|
+
</SelectPrimitive.ItemIndicator>
|
|
147
|
+
</span>
|
|
148
|
+
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
149
|
+
</SelectPrimitive.Item>
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function SelectSeparator({
|
|
154
|
+
className,
|
|
155
|
+
...props
|
|
156
|
+
}: React.ComponentProps<typeof SelectPrimitive.Separator>) {
|
|
157
|
+
return (
|
|
158
|
+
<SelectPrimitive.Separator
|
|
159
|
+
data-slot="select-separator"
|
|
160
|
+
className={cn("bg-border pointer-events-none -mx-1 my-1 h-px", className)}
|
|
161
|
+
{...props}
|
|
162
|
+
/>
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function SelectScrollUpButton({
|
|
167
|
+
className,
|
|
168
|
+
...props
|
|
169
|
+
}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
|
|
170
|
+
return (
|
|
171
|
+
<SelectPrimitive.ScrollUpButton
|
|
172
|
+
data-slot="select-scroll-up-button"
|
|
173
|
+
className={cn(
|
|
174
|
+
"flex cursor-default items-center justify-center py-1",
|
|
175
|
+
className
|
|
176
|
+
)}
|
|
177
|
+
{...props}
|
|
178
|
+
>
|
|
179
|
+
<ChevronUpIcon className="size-4" />
|
|
180
|
+
</SelectPrimitive.ScrollUpButton>
|
|
181
|
+
)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function SelectScrollDownButton({
|
|
185
|
+
className,
|
|
186
|
+
...props
|
|
187
|
+
}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
|
|
188
|
+
return (
|
|
189
|
+
<SelectPrimitive.ScrollDownButton
|
|
190
|
+
data-slot="select-scroll-down-button"
|
|
191
|
+
className={cn(
|
|
192
|
+
"flex cursor-default items-center justify-center py-1",
|
|
193
|
+
className
|
|
194
|
+
)}
|
|
195
|
+
{...props}
|
|
196
|
+
>
|
|
197
|
+
<ChevronDownIcon className="size-4" />
|
|
198
|
+
</SelectPrimitive.ScrollDownButton>
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export {
|
|
203
|
+
Select,
|
|
204
|
+
SelectContent,
|
|
205
|
+
SelectGroup,
|
|
206
|
+
SelectItem,
|
|
207
|
+
SelectLabel,
|
|
208
|
+
SelectScrollDownButton,
|
|
209
|
+
SelectScrollUpButton,
|
|
210
|
+
SelectSeparator,
|
|
211
|
+
SelectTrigger,
|
|
212
|
+
SelectValue,
|
|
213
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./separator";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as SeparatorPrimitive from "@radix-ui/react-separator"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 콘텐츠를 시각적으로 분리하는 구분선 컴포넌트입니다.
|
|
10
|
+
*
|
|
11
|
+
* @param props.orientation - 방향 ('horizontal' | 'vertical')
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* <Separator />
|
|
16
|
+
* <Separator orientation="vertical" />
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
function Separator({
|
|
20
|
+
className,
|
|
21
|
+
orientation = "horizontal",
|
|
22
|
+
decorative = true,
|
|
23
|
+
...props
|
|
24
|
+
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
|
|
25
|
+
return (
|
|
26
|
+
<SeparatorPrimitive.Root
|
|
27
|
+
data-slot="separator"
|
|
28
|
+
decorative={decorative}
|
|
29
|
+
orientation={orientation}
|
|
30
|
+
className={cn(
|
|
31
|
+
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
|
|
32
|
+
className
|
|
33
|
+
)}
|
|
34
|
+
{...props}
|
|
35
|
+
/>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { Separator }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./sheet";
|