@mzc-fe/design-system 0.0.6 → 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.
Files changed (173) hide show
  1. package/components/accordion/accordion.tsx +114 -0
  2. package/components/accordion/index.ts +1 -0
  3. package/components/alert/alert.tsx +97 -0
  4. package/components/alert/index.ts +1 -0
  5. package/components/alert-dialog/alert-dialog.tsx +190 -0
  6. package/components/alert-dialog/index.ts +1 -0
  7. package/components/aspect-ratio/aspect-ratio.tsx +23 -0
  8. package/components/aspect-ratio/index.ts +1 -0
  9. package/components/avatar/avatar.tsx +62 -0
  10. package/components/avatar/index.ts +1 -0
  11. package/components/badge/badge.tsx +58 -0
  12. package/components/badge/index.ts +1 -0
  13. package/components/breadcrumb/breadcrumb.tsx +132 -0
  14. package/components/breadcrumb/index.ts +1 -0
  15. package/components/button/button.tsx +77 -0
  16. package/components/button/index.ts +1 -0
  17. package/components/button-group/button-group.tsx +99 -0
  18. package/components/button-group/index.ts +1 -0
  19. package/components/calendar/calendar.tsx +235 -0
  20. package/components/calendar/index.ts +1 -0
  21. package/components/card/card.tsx +107 -0
  22. package/components/card/index.ts +1 -0
  23. package/components/carousel/carousel.tsx +263 -0
  24. package/components/carousel/index.ts +1 -0
  25. package/components/chart/chart.tsx +377 -0
  26. package/components/chart/index.ts +1 -0
  27. package/components/checkbox/checkbox.tsx +41 -0
  28. package/components/checkbox/index.ts +1 -0
  29. package/components/collapsible/collapsible.tsx +44 -0
  30. package/components/collapsible/index.ts +1 -0
  31. package/components/command/command.tsx +201 -0
  32. package/components/command/index.ts +1 -0
  33. package/components/context-menu/context-menu.tsx +270 -0
  34. package/components/context-menu/index.ts +1 -0
  35. package/components/dialog/dialog.tsx +166 -0
  36. package/components/dialog/index.ts +1 -0
  37. package/components/drawer/drawer.tsx +154 -0
  38. package/components/drawer/index.ts +1 -0
  39. package/components/dropdown-menu/dropdown-menu.tsx +276 -0
  40. package/components/dropdown-menu/index.ts +1 -0
  41. package/components/empty/empty.tsx +129 -0
  42. package/components/empty/index.ts +1 -0
  43. package/components/field/field.tsx +272 -0
  44. package/components/field/index.ts +1 -0
  45. package/components/form/form.tsx +197 -0
  46. package/components/form/index.ts +1 -0
  47. package/components/hover-card/hover-card.tsx +57 -0
  48. package/components/hover-card/index.ts +1 -0
  49. package/components/input/index.ts +1 -0
  50. package/components/input/input.tsx +31 -0
  51. package/components/input-group/index.ts +1 -0
  52. package/components/input-group/input-group.tsx +189 -0
  53. package/components/input-otp/index.ts +1 -0
  54. package/components/input-otp/input-otp.tsx +99 -0
  55. package/components/item/index.ts +1 -0
  56. package/components/item/item.tsx +225 -0
  57. package/components/kbd/index.ts +1 -0
  58. package/components/kbd/kbd.tsx +38 -0
  59. package/components/label/index.ts +1 -0
  60. package/components/label/label.tsx +33 -0
  61. package/components/menubar/index.ts +1 -0
  62. package/components/menubar/menubar.tsx +299 -0
  63. package/components/navigation-menu/index.ts +1 -0
  64. package/components/navigation-menu/navigation-menu.tsx +194 -0
  65. package/components/pagination/index.ts +1 -0
  66. package/components/pagination/pagination.tsx +153 -0
  67. package/components/popover/index.ts +1 -0
  68. package/components/popover/popover.tsx +106 -0
  69. package/components/progress/index.ts +1 -0
  70. package/components/progress/progress.tsx +39 -0
  71. package/components/radio-group/index.ts +1 -0
  72. package/components/radio-group/radio-group.tsx +57 -0
  73. package/components/resizable/index.ts +1 -0
  74. package/components/resizable/resizable.tsx +73 -0
  75. package/components/scroll-area/index.ts +1 -0
  76. package/components/scroll-area/scroll-area.tsx +72 -0
  77. package/components/select/index.ts +1 -0
  78. package/components/select/select.tsx +213 -0
  79. package/components/separator/index.ts +1 -0
  80. package/components/separator/separator.tsx +39 -0
  81. package/components/sheet/index.ts +1 -0
  82. package/components/sheet/sheet.tsx +160 -0
  83. package/components/sidebar/index.ts +1 -0
  84. package/components/sidebar/sidebar.tsx +776 -0
  85. package/components/skeleton/index.ts +1 -0
  86. package/components/skeleton/skeleton.tsx +21 -0
  87. package/components/slider/index.ts +1 -0
  88. package/components/slider/slider.tsx +75 -0
  89. package/components/sonner/index.ts +2 -0
  90. package/components/sonner/sonner.tsx +52 -0
  91. package/components/spinner/index.ts +1 -0
  92. package/components/spinner/spinner.tsx +26 -0
  93. package/components/switch/index.ts +1 -0
  94. package/components/switch/switch.tsx +39 -0
  95. package/components/table/index.ts +1 -0
  96. package/components/table/table.tsx +140 -0
  97. package/components/tabs/index.ts +1 -0
  98. package/components/tabs/tabs.tsx +94 -0
  99. package/components/textarea/index.ts +1 -0
  100. package/components/textarea/textarea.tsx +26 -0
  101. package/components/toggle/index.ts +1 -0
  102. package/components/toggle/toggle.tsx +58 -0
  103. package/components/toggle-group/index.ts +1 -0
  104. package/components/toggle-group/toggle-group.tsx +97 -0
  105. package/components/tooltip/index.ts +1 -0
  106. package/components/tooltip/tooltip.tsx +82 -0
  107. package/dist/components/accordion/accordion.d.ts +50 -0
  108. package/dist/components/alert/alert.d.ts +31 -0
  109. package/dist/components/alert-dialog/alert-dialog.d.ts +35 -0
  110. package/dist/components/aspect-ratio/aspect-ratio.d.ts +12 -0
  111. package/dist/components/avatar/avatar.d.ts +11 -0
  112. package/dist/components/badge/badge.d.ts +12 -0
  113. package/dist/components/breadcrumb/breadcrumb.d.ts +23 -0
  114. package/dist/components/button/button.d.ts +15 -0
  115. package/dist/components/button-group/button-group.d.ts +16 -0
  116. package/dist/components/calendar/calendar.d.ts +15 -0
  117. package/dist/components/card/card.d.ts +15 -0
  118. package/dist/components/carousel/carousel.d.ts +24 -0
  119. package/dist/components/chart/chart.d.ts +20 -0
  120. package/dist/components/checkbox/checkbox.d.ts +9 -0
  121. package/dist/components/collapsible/collapsible.d.ts +13 -0
  122. package/dist/components/command/command.d.ts +18 -0
  123. package/dist/components/context-menu/context-menu.d.ts +18 -0
  124. package/dist/components/dialog/dialog.d.ts +25 -0
  125. package/dist/components/drawer/drawer.d.ts +18 -0
  126. package/dist/components/dropdown-menu/dropdown-menu.d.ts +21 -0
  127. package/dist/components/empty/empty.d.ts +25 -0
  128. package/dist/components/field/field.d.ts +26 -0
  129. package/dist/components/form/form.d.ts +30 -1
  130. package/dist/components/hover-card/hover-card.d.ts +13 -0
  131. package/dist/components/input/input.d.ts +10 -0
  132. package/dist/components/input-group/input-group.d.ts +19 -0
  133. package/dist/components/input-otp/input-otp.d.ts +23 -0
  134. package/dist/components/item/item.d.ts +33 -1
  135. package/dist/components/kbd/kbd.d.ts +10 -0
  136. package/dist/components/label/label.d.ts +9 -0
  137. package/dist/components/menubar/menubar.d.ts +25 -0
  138. package/dist/components/navigation-menu/navigation-menu.d.ts +26 -0
  139. package/dist/components/pagination/pagination.d.ts +26 -0
  140. package/dist/components/popover/popover.d.ts +17 -0
  141. package/dist/components/progress/progress.d.ts +10 -0
  142. package/dist/components/radio-group/radio-group.d.ts +12 -0
  143. package/dist/components/resizable/resizable.d.ts +19 -0
  144. package/dist/components/scroll-area/scroll-area.d.ts +14 -0
  145. package/dist/components/select/select.d.ts +25 -0
  146. package/dist/components/separator/separator.d.ts +11 -0
  147. package/dist/components/sheet/sheet.d.ts +23 -0
  148. package/dist/components/sidebar/sidebar.d.ts +50 -0
  149. package/dist/components/skeleton/skeleton.d.ts +8 -0
  150. package/dist/components/slider/slider.d.ts +12 -0
  151. package/dist/components/sonner/sonner.d.ts +14 -0
  152. package/dist/components/spinner/spinner.d.ts +9 -0
  153. package/dist/components/switch/switch.d.ts +8 -0
  154. package/dist/components/table/table.d.ts +26 -0
  155. package/dist/components/tabs/tabs.d.ts +16 -6
  156. package/dist/components/textarea/textarea.d.ts +8 -0
  157. package/dist/components/toggle/toggle.d.ts +13 -0
  158. package/dist/components/toggle-group/toggle-group.d.ts +1 -0
  159. package/dist/components/tooltip/tooltip.d.ts +21 -0
  160. package/dist/design-system.css +1 -1
  161. package/dist/design-system.es.js +3481 -28494
  162. package/dist/design-system.umd.js +4 -257
  163. package/foundations/ThemeProvider.tsx +77 -0
  164. package/foundations/color.css +232 -0
  165. package/foundations/palette.css +249 -0
  166. package/foundations/spacing.css +8 -0
  167. package/foundations/typography.css +143 -0
  168. package/hooks/use-mobile.ts +19 -0
  169. package/index.css +173 -0
  170. package/index.ts +339 -0
  171. package/lib/utils.ts +6 -0
  172. package/package.json +40 -19
  173. package/README.md +0 -184
@@ -0,0 +1,114 @@
1
+ import * as React from "react"
2
+ import * as AccordionPrimitive from "@radix-ui/react-accordion"
3
+ import { ChevronDownIcon } from "lucide-react"
4
+
5
+ import { cn } from "@/lib/utils"
6
+
7
+ /**
8
+ * 접을 수 있는 콘텐츠 섹션을 제공하는 아코디언 컴포넌트입니다.
9
+ * Radix UI의 Accordion primitive를 기반으로 합니다.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * <Accordion type="single" collapsible>
14
+ * <AccordionItem value="item-1">
15
+ * <AccordionTrigger>제목</AccordionTrigger>
16
+ * <AccordionContent>내용</AccordionContent>
17
+ * </AccordionItem>
18
+ * </Accordion>
19
+ * ```
20
+ *
21
+ * @param props - Radix UI Accordion.Root props
22
+ * @param props.type - 'single'은 하나의 아이템만, 'multiple'은 여러 아이템을 동시에 열 수 있습니다
23
+ * @param props.collapsible - type이 'single'일 때, 열린 아이템을 다시 클릭하여 닫을 수 있게 합니다
24
+ * @param props.defaultValue - 초기에 열려있을 아이템의 value
25
+ * @param props.value - 제어 모드에서 열려있는 아이템의 value
26
+ * @param props.onValueChange - 열린 아이템이 변경될 때 호출되는 콜백
27
+ * @param props.disabled - 모든 아이템을 비활성화합니다
28
+ */
29
+ function Accordion({
30
+ ...props
31
+ }: React.ComponentProps<typeof AccordionPrimitive.Root>) {
32
+ return <AccordionPrimitive.Root data-slot="accordion" {...props} />
33
+ }
34
+
35
+ /**
36
+ * 아코디언의 개별 아이템을 나타내는 컴포넌트입니다.
37
+ * 각 아이템은 고유한 value를 가져야 합니다.
38
+ *
39
+ * @param props - Radix UI Accordion.Item props
40
+ * @param props.value - 아이템의 고유 식별자 (필수)
41
+ * @param props.disabled - 이 아이템만 비활성화합니다
42
+ * @param props.className - 추가 CSS 클래스
43
+ */
44
+ function AccordionItem({
45
+ className,
46
+ ...props
47
+ }: React.ComponentProps<typeof AccordionPrimitive.Item>) {
48
+ return (
49
+ <AccordionPrimitive.Item
50
+ data-slot="accordion-item"
51
+ className={cn("border-b last:border-b-0", className)}
52
+ {...props}
53
+ />
54
+ )
55
+ }
56
+
57
+ /**
58
+ * 아코디언 아이템을 열고 닫는 트리거 버튼입니다.
59
+ * 클릭하면 해당 아이템의 콘텐츠가 펼쳐지거나 접힙니다.
60
+ * 우측에 화살표 아이콘이 표시되며, 열린 상태에서는 회전합니다.
61
+ *
62
+ * @param props - Radix UI Accordion.Trigger props
63
+ * @param props.children - 트리거에 표시될 텍스트 또는 요소
64
+ * @param props.className - 추가 CSS 클래스
65
+ * @param props.disabled - 트리거를 비활성화합니다
66
+ */
67
+ function AccordionTrigger({
68
+ className,
69
+ children,
70
+ ...props
71
+ }: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
72
+ return (
73
+ <AccordionPrimitive.Header className="flex">
74
+ <AccordionPrimitive.Trigger
75
+ data-slot="accordion-trigger"
76
+ className={cn(
77
+ "focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180",
78
+ className
79
+ )}
80
+ {...props}
81
+ >
82
+ {children}
83
+ <ChevronDownIcon className="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" />
84
+ </AccordionPrimitive.Trigger>
85
+ </AccordionPrimitive.Header>
86
+ )
87
+ }
88
+
89
+ /**
90
+ * 아코디언 아이템의 접히는 콘텐츠 영역입니다.
91
+ * 트리거를 클릭하면 애니메이션과 함께 펼쳐지거나 접힙니다.
92
+ *
93
+ * @param props - Radix UI Accordion.Content props
94
+ * @param props.children - 콘텐츠 영역에 표시될 내용
95
+ * @param props.className - 내부 콘텐츠 래퍼에 적용될 추가 CSS 클래스
96
+ * @param props.forceMount - 닫힌 상태에서도 DOM에 마운트 유지 (애니메이션용)
97
+ */
98
+ function AccordionContent({
99
+ className,
100
+ children,
101
+ ...props
102
+ }: React.ComponentProps<typeof AccordionPrimitive.Content>) {
103
+ return (
104
+ <AccordionPrimitive.Content
105
+ data-slot="accordion-content"
106
+ className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm"
107
+ {...props}
108
+ >
109
+ <div className={cn("pt-0 pb-4", className)}>{children}</div>
110
+ </AccordionPrimitive.Content>
111
+ )
112
+ }
113
+
114
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
@@ -0,0 +1 @@
1
+ export * from "./accordion";
@@ -0,0 +1,97 @@
1
+ import * as React from "react"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ /**
7
+ * Alert 컴포넌트의 스타일 변형을 정의합니다.
8
+ */
9
+ const alertVariants = cva(
10
+ "relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
11
+ {
12
+ variants: {
13
+ variant: {
14
+ default: "bg-card text-card-foreground",
15
+ destructive:
16
+ "text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90",
17
+ },
18
+ },
19
+ defaultVariants: {
20
+ variant: "default",
21
+ },
22
+ }
23
+ )
24
+
25
+ /**
26
+ * 사용자에게 중요한 정보를 전달하는 알림 컴포넌트입니다.
27
+ * 아이콘, 제목, 설명을 포함할 수 있습니다.
28
+ *
29
+ * @example
30
+ * ```tsx
31
+ * <Alert variant="default">
32
+ * <InfoIcon />
33
+ * <AlertTitle>알림</AlertTitle>
34
+ * <AlertDescription>중요한 정보입니다.</AlertDescription>
35
+ * </Alert>
36
+ * ```
37
+ *
38
+ * @param props.variant - 'default' | 'destructive' 스타일 변형
39
+ * @param props.className - 추가 CSS 클래스
40
+ */
41
+ function Alert({
42
+ className,
43
+ variant,
44
+ ...props
45
+ }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
46
+ return (
47
+ <div
48
+ data-slot="alert"
49
+ role="alert"
50
+ className={cn(alertVariants({ variant }), className)}
51
+ {...props}
52
+ />
53
+ )
54
+ }
55
+
56
+ /**
57
+ * Alert의 제목을 표시하는 컴포넌트입니다.
58
+ *
59
+ * @param props.className - 추가 CSS 클래스
60
+ * @param props.children - 제목 텍스트
61
+ */
62
+ function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
63
+ return (
64
+ <div
65
+ data-slot="alert-title"
66
+ className={cn(
67
+ "col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight",
68
+ className
69
+ )}
70
+ {...props}
71
+ />
72
+ )
73
+ }
74
+
75
+ /**
76
+ * Alert의 상세 설명을 표시하는 컴포넌트입니다.
77
+ *
78
+ * @param props.className - 추가 CSS 클래스
79
+ * @param props.children - 설명 내용
80
+ */
81
+ function AlertDescription({
82
+ className,
83
+ ...props
84
+ }: React.ComponentProps<"div">) {
85
+ return (
86
+ <div
87
+ data-slot="alert-description"
88
+ className={cn(
89
+ "text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed",
90
+ className
91
+ )}
92
+ {...props}
93
+ />
94
+ )
95
+ }
96
+
97
+ export { Alert, AlertTitle, AlertDescription }
@@ -0,0 +1 @@
1
+ export * from "./alert";
@@ -0,0 +1,190 @@
1
+ import * as React from "react";
2
+ import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
3
+
4
+ import { cn } from "@/lib/utils";
5
+ import { buttonVariants } from "@/components/button";
6
+
7
+ /**
8
+ * 사용자의 확인이 필요한 중요한 작업에 대한 모달 다이얼로그입니다.
9
+ * 일반 Dialog와 달리 배경 클릭이나 Escape로 닫히지 않습니다.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * <AlertDialog>
14
+ * <AlertDialogTrigger asChild>
15
+ * <Button>삭제</Button>
16
+ * </AlertDialogTrigger>
17
+ * <AlertDialogContent>
18
+ * <AlertDialogHeader>
19
+ * <AlertDialogTitle>정말 삭제하시겠습니까?</AlertDialogTitle>
20
+ * <AlertDialogDescription>이 작업은 취소할 수 없습니다.</AlertDialogDescription>
21
+ * </AlertDialogHeader>
22
+ * <AlertDialogFooter>
23
+ * <AlertDialogCancel>취소</AlertDialogCancel>
24
+ * <AlertDialogAction>삭제</AlertDialogAction>
25
+ * </AlertDialogFooter>
26
+ * </AlertDialogContent>
27
+ * </AlertDialog>
28
+ * ```
29
+ */
30
+ function AlertDialog({
31
+ ...props
32
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
33
+ return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
34
+ }
35
+
36
+ function AlertDialogTrigger({
37
+ ...props
38
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
39
+ return (
40
+ <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
41
+ );
42
+ }
43
+
44
+ function AlertDialogPortal({
45
+ ...props
46
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
47
+ return (
48
+ <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
49
+ );
50
+ }
51
+
52
+ function AlertDialogOverlay({
53
+ className,
54
+ ...props
55
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
56
+ return (
57
+ <AlertDialogPrimitive.Overlay
58
+ data-slot="alert-dialog-overlay"
59
+ className={cn(
60
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
61
+ className
62
+ )}
63
+ {...props}
64
+ />
65
+ );
66
+ }
67
+
68
+ /**
69
+ * AlertDialog의 메인 콘텐츠 영역입니다.
70
+ * 자동으로 Overlay와 Portal을 포함합니다.
71
+ */
72
+ function AlertDialogContent({
73
+ className,
74
+ ...props
75
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Content>) {
76
+ return (
77
+ <AlertDialogPortal>
78
+ <AlertDialogOverlay />
79
+ <AlertDialogPrimitive.Content
80
+ data-slot="alert-dialog-content"
81
+ className={cn(
82
+ "bg-background 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 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
83
+ className
84
+ )}
85
+ {...props}
86
+ />
87
+ </AlertDialogPortal>
88
+ );
89
+ }
90
+
91
+ function AlertDialogHeader({
92
+ className,
93
+ ...props
94
+ }: React.ComponentProps<"div">) {
95
+ return (
96
+ <div
97
+ data-slot="alert-dialog-header"
98
+ className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
99
+ {...props}
100
+ />
101
+ );
102
+ }
103
+
104
+ function AlertDialogFooter({
105
+ className,
106
+ ...props
107
+ }: React.ComponentProps<"div">) {
108
+ return (
109
+ <div
110
+ data-slot="alert-dialog-footer"
111
+ className={cn(
112
+ "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
113
+ className
114
+ )}
115
+ {...props}
116
+ />
117
+ );
118
+ }
119
+
120
+ function AlertDialogTitle({
121
+ className,
122
+ ...props
123
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
124
+ return (
125
+ <AlertDialogPrimitive.Title
126
+ data-slot="alert-dialog-title"
127
+ className={cn("text-lg font-semibold", className)}
128
+ {...props}
129
+ />
130
+ );
131
+ }
132
+
133
+ function AlertDialogDescription({
134
+ className,
135
+ ...props
136
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
137
+ return (
138
+ <AlertDialogPrimitive.Description
139
+ data-slot="alert-dialog-description"
140
+ className={cn("text-muted-foreground text-sm", className)}
141
+ {...props}
142
+ />
143
+ );
144
+ }
145
+
146
+ /**
147
+ * AlertDialog의 확인 버튼입니다.
148
+ * 클릭 시 다이얼로그가 닫히고 지정된 액션이 실행됩니다.
149
+ */
150
+ function AlertDialogAction({
151
+ className,
152
+ ...props
153
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {
154
+ return (
155
+ <AlertDialogPrimitive.Action
156
+ className={cn(buttonVariants(), className)}
157
+ {...props}
158
+ />
159
+ );
160
+ }
161
+
162
+ /**
163
+ * AlertDialog의 취소 버튼입니다.
164
+ * 클릭 시 다이얼로그가 닫히고 아무 작업도 수행하지 않습니다.
165
+ */
166
+ function AlertDialogCancel({
167
+ className,
168
+ ...props
169
+ }: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {
170
+ return (
171
+ <AlertDialogPrimitive.Cancel
172
+ className={cn(buttonVariants({ variant: "outline" }), className)}
173
+ {...props}
174
+ />
175
+ );
176
+ }
177
+
178
+ export {
179
+ AlertDialog,
180
+ AlertDialogPortal,
181
+ AlertDialogOverlay,
182
+ AlertDialogTrigger,
183
+ AlertDialogContent,
184
+ AlertDialogHeader,
185
+ AlertDialogFooter,
186
+ AlertDialogTitle,
187
+ AlertDialogDescription,
188
+ AlertDialogAction,
189
+ AlertDialogCancel,
190
+ };
@@ -0,0 +1 @@
1
+ export * from "./alert-dialog";
@@ -0,0 +1,23 @@
1
+ "use client"
2
+
3
+ import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"
4
+
5
+ /**
6
+ * 지정된 비율로 콘텐츠 영역을 유지하는 컴포넌트입니다.
7
+ *
8
+ * @param props.ratio - 가로:세로 비율 (예: 16/9, 4/3, 1)
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * <AspectRatio ratio={16/9}>
13
+ * <img src="image.jpg" className="object-cover" />
14
+ * </AspectRatio>
15
+ * ```
16
+ */
17
+ function AspectRatio({
18
+ ...props
19
+ }: React.ComponentProps<typeof AspectRatioPrimitive.Root>) {
20
+ return <AspectRatioPrimitive.Root data-slot="aspect-ratio" {...props} />
21
+ }
22
+
23
+ export { AspectRatio }
@@ -0,0 +1 @@
1
+ export * from "./aspect-ratio";
@@ -0,0 +1,62 @@
1
+ import * as React from "react"
2
+ import * as AvatarPrimitive from "@radix-ui/react-avatar"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ /**
7
+ * 사용자의 프로필 이미지나 이니셜을 표시하는 아바타 컴포넌트입니다.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * <Avatar>
12
+ * <AvatarImage src="/profile.jpg" alt="사용자" />
13
+ * <AvatarFallback>AB</AvatarFallback>
14
+ * </Avatar>
15
+ * ```
16
+ */
17
+ function Avatar({
18
+ className,
19
+ ...props
20
+ }: React.ComponentProps<typeof AvatarPrimitive.Root>) {
21
+ return (
22
+ <AvatarPrimitive.Root
23
+ data-slot="avatar"
24
+ className={cn(
25
+ "relative flex size-8 shrink-0 overflow-hidden rounded-full",
26
+ className
27
+ )}
28
+ {...props}
29
+ />
30
+ )
31
+ }
32
+
33
+ function AvatarImage({
34
+ className,
35
+ ...props
36
+ }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
37
+ return (
38
+ <AvatarPrimitive.Image
39
+ data-slot="avatar-image"
40
+ className={cn("aspect-square size-full", className)}
41
+ {...props}
42
+ />
43
+ )
44
+ }
45
+
46
+ function AvatarFallback({
47
+ className,
48
+ ...props
49
+ }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
50
+ return (
51
+ <AvatarPrimitive.Fallback
52
+ data-slot="avatar-fallback"
53
+ className={cn(
54
+ "bg-muted flex size-full items-center justify-center rounded-full",
55
+ className
56
+ )}
57
+ {...props}
58
+ />
59
+ )
60
+ }
61
+
62
+ export { Avatar, AvatarImage, AvatarFallback }
@@ -0,0 +1 @@
1
+ export * from "./avatar";
@@ -0,0 +1,58 @@
1
+ import * as React from "react"
2
+ import { Slot } from "@radix-ui/react-slot"
3
+ import { cva, type VariantProps } from "class-variance-authority"
4
+
5
+ import { cn } from "@/lib/utils"
6
+
7
+ const badgeVariants = cva(
8
+ "inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default:
13
+ "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
14
+ secondary:
15
+ "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
16
+ destructive:
17
+ "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
18
+ outline:
19
+ "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
20
+ },
21
+ },
22
+ defaultVariants: {
23
+ variant: "default",
24
+ },
25
+ }
26
+ )
27
+
28
+ /**
29
+ * 상태, 카테고리, 카운트 등을 표시하는 뱃지 컴포넌트입니다.
30
+ *
31
+ * @example
32
+ * ```tsx
33
+ * <Badge variant="default">New</Badge>
34
+ * <Badge variant="destructive">Error</Badge>
35
+ * ```
36
+ *
37
+ * @param props.variant - 'default' | 'secondary' | 'destructive' | 'outline'
38
+ * @param props.asChild - true면 자식 요소로 렌더링 (링크 등)
39
+ */
40
+ function Badge({
41
+ className,
42
+ variant,
43
+ asChild = false,
44
+ ...props
45
+ }: React.ComponentProps<"span"> &
46
+ VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
47
+ const Comp = asChild ? Slot : "span"
48
+
49
+ return (
50
+ <Comp
51
+ data-slot="badge"
52
+ className={cn(badgeVariants({ variant }), className)}
53
+ {...props}
54
+ />
55
+ )
56
+ }
57
+
58
+ export { Badge, badgeVariants }
@@ -0,0 +1 @@
1
+ export * from "./badge";
@@ -0,0 +1,132 @@
1
+ import * as React from "react"
2
+ import { Slot } from "@radix-ui/react-slot"
3
+ import { ChevronRight, MoreHorizontal } from "lucide-react"
4
+
5
+ import { cn } from "@/lib/utils"
6
+
7
+ /**
8
+ * 현재 페이지의 경로를 계층적으로 보여주는 브레드크럼 컴포넌트입니다.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * <Breadcrumb>
13
+ * <BreadcrumbList>
14
+ * <BreadcrumbItem>
15
+ * <BreadcrumbLink href="/">홈</BreadcrumbLink>
16
+ * </BreadcrumbItem>
17
+ * <BreadcrumbSeparator />
18
+ * <BreadcrumbItem>
19
+ * <BreadcrumbPage>현재 페이지</BreadcrumbPage>
20
+ * </BreadcrumbItem>
21
+ * </BreadcrumbList>
22
+ * </Breadcrumb>
23
+ * ```
24
+ */
25
+ function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
26
+ return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />
27
+ }
28
+
29
+ /** 브레드크럼 아이템들을 감싸는 리스트입니다. */
30
+ function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
31
+ return (
32
+ <ol
33
+ data-slot="breadcrumb-list"
34
+ className={cn(
35
+ "text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5",
36
+ className
37
+ )}
38
+ {...props}
39
+ />
40
+ )
41
+ }
42
+
43
+ /** 브레드크럼 개별 아이템입니다. */
44
+ function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
45
+ return (
46
+ <li
47
+ data-slot="breadcrumb-item"
48
+ className={cn("inline-flex items-center gap-1.5", className)}
49
+ {...props}
50
+ />
51
+ )
52
+ }
53
+
54
+ /** 클릭 가능한 브레드크럼 링크입니다. */
55
+ function BreadcrumbLink({
56
+ asChild,
57
+ className,
58
+ ...props
59
+ }: React.ComponentProps<"a"> & {
60
+ asChild?: boolean
61
+ }) {
62
+ const Comp = asChild ? Slot : "a"
63
+
64
+ return (
65
+ <Comp
66
+ data-slot="breadcrumb-link"
67
+ className={cn("hover:text-foreground transition-colors", className)}
68
+ {...props}
69
+ />
70
+ )
71
+ }
72
+
73
+ /** 현재 페이지를 나타내는 비활성 텍스트입니다. */
74
+ function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
75
+ return (
76
+ <span
77
+ data-slot="breadcrumb-page"
78
+ role="link"
79
+ aria-disabled="true"
80
+ aria-current="page"
81
+ className={cn("text-foreground font-normal", className)}
82
+ {...props}
83
+ />
84
+ )
85
+ }
86
+
87
+ /** 아이템 사이의 구분자입니다. */
88
+ function BreadcrumbSeparator({
89
+ children,
90
+ className,
91
+ ...props
92
+ }: React.ComponentProps<"li">) {
93
+ return (
94
+ <li
95
+ data-slot="breadcrumb-separator"
96
+ role="presentation"
97
+ aria-hidden="true"
98
+ className={cn("[&>svg]:size-3.5", className)}
99
+ {...props}
100
+ >
101
+ {children ?? <ChevronRight />}
102
+ </li>
103
+ )
104
+ }
105
+
106
+ function BreadcrumbEllipsis({
107
+ className,
108
+ ...props
109
+ }: React.ComponentProps<"span">) {
110
+ return (
111
+ <span
112
+ data-slot="breadcrumb-ellipsis"
113
+ role="presentation"
114
+ aria-hidden="true"
115
+ className={cn("flex size-9 items-center justify-center", className)}
116
+ {...props}
117
+ >
118
+ <MoreHorizontal className="size-4" />
119
+ <span className="sr-only">More</span>
120
+ </span>
121
+ )
122
+ }
123
+
124
+ export {
125
+ Breadcrumb,
126
+ BreadcrumbList,
127
+ BreadcrumbItem,
128
+ BreadcrumbLink,
129
+ BreadcrumbPage,
130
+ BreadcrumbSeparator,
131
+ BreadcrumbEllipsis,
132
+ }
@@ -0,0 +1 @@
1
+ export * from "./breadcrumb";