@crossangle-org/cs-ui 0.2.6 → 0.2.7

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 (119) hide show
  1. package/dist/components/accordion/cs-accordion.js +116 -0
  2. package/dist/components/accordion/cs-accordion.js.map +1 -0
  3. package/dist/components/alert-dialog/cs-alert-dialog.js +148 -0
  4. package/dist/components/alert-dialog/cs-alert-dialog.js.map +1 -0
  5. package/dist/components/avatar/cs-avatar.js +44 -0
  6. package/dist/components/avatar/cs-avatar.js.map +1 -0
  7. package/dist/components/badge/cs-badge.js +40 -0
  8. package/dist/components/badge/cs-badge.js.map +1 -0
  9. package/dist/components/box/cs-box.js +37 -0
  10. package/dist/components/box/cs-box.js.map +1 -0
  11. package/dist/components/button/cs-button.js +91 -0
  12. package/dist/components/button/cs-button.js.map +1 -0
  13. package/dist/components/calendar/cs-calendar.js +199 -0
  14. package/dist/components/calendar/cs-calendar.js.map +1 -0
  15. package/dist/components/card/cs-card.js +95 -0
  16. package/dist/components/card/cs-card.js.map +1 -0
  17. package/dist/components/chart/cs-chart.js +88 -0
  18. package/dist/components/chart/cs-chart.js.map +1 -0
  19. package/dist/components/checkbox/cs-checkbox.js +55 -0
  20. package/dist/components/checkbox/cs-checkbox.js.map +1 -0
  21. package/dist/components/code-block/cs-code-block.js +39 -0
  22. package/dist/components/code-block/cs-code-block.js.map +1 -0
  23. package/dist/components/code-block/cs-code-highlighter.js +59 -0
  24. package/dist/components/code-block/cs-code-highlighter.js.map +1 -0
  25. package/dist/components/collapsible/cs-collapsible.js +36 -0
  26. package/dist/components/collapsible/cs-collapsible.js.map +1 -0
  27. package/dist/components/date-picker/cs-date-picker.js +25 -0
  28. package/dist/components/date-picker/cs-date-picker.js.map +1 -0
  29. package/dist/components/dialog/cs-dialog.js +131 -0
  30. package/dist/components/dialog/cs-dialog.js.map +1 -0
  31. package/dist/components/drawer/cs-drawer.js +131 -0
  32. package/dist/components/drawer/cs-drawer.js.map +1 -0
  33. package/dist/components/dropdown-menu/cs-dropdown-menu.js +247 -0
  34. package/dist/components/dropdown-menu/cs-dropdown-menu.js.map +1 -0
  35. package/dist/components/dropzone/cs-dropzone.js +147 -0
  36. package/dist/components/dropzone/cs-dropzone.js.map +1 -0
  37. package/dist/components/empty/cs-empty.js +107 -0
  38. package/dist/components/empty/cs-empty.js.map +1 -0
  39. package/dist/components/field/cs-field.js +218 -0
  40. package/dist/components/field/cs-field.js.map +1 -0
  41. package/dist/components/input/cs-input-group.js +207 -0
  42. package/dist/components/input/cs-input-group.js.map +1 -0
  43. package/dist/components/input/cs-input.js +40 -0
  44. package/dist/components/input/cs-input.js.map +1 -0
  45. package/dist/components/label/cs-label.js +26 -0
  46. package/dist/components/label/cs-label.js.map +1 -0
  47. package/dist/components/navigation-menu/cs-navigation-menu.js +214 -0
  48. package/dist/components/navigation-menu/cs-navigation-menu.js.map +1 -0
  49. package/dist/components/pagination/cs-pagination.js +124 -0
  50. package/dist/components/pagination/cs-pagination.js.map +1 -0
  51. package/dist/components/popover/cs-popover.js +60 -0
  52. package/dist/components/popover/cs-popover.js.map +1 -0
  53. package/dist/components/progress/cs-progress.js +62 -0
  54. package/dist/components/progress/cs-progress.js.map +1 -0
  55. package/dist/components/scroll-area/cs-scroll-area.js +61 -0
  56. package/dist/components/scroll-area/cs-scroll-area.js.map +1 -0
  57. package/dist/components/select/cs-select.js +195 -0
  58. package/dist/components/select/cs-select.js.map +1 -0
  59. package/dist/components/select/cs-simple-select.js +32 -0
  60. package/dist/components/select/cs-simple-select.js.map +1 -0
  61. package/dist/components/separator/cs-separator.js +28 -0
  62. package/dist/components/separator/cs-separator.js.map +1 -0
  63. package/dist/components/sheet/cs-sheet.js +128 -0
  64. package/dist/components/sheet/cs-sheet.js.map +1 -0
  65. package/dist/components/sidebar/cs-sidebar.js +657 -0
  66. package/dist/components/sidebar/cs-sidebar.js.map +1 -0
  67. package/dist/components/skeleton/cs-skeleton.js +32 -0
  68. package/dist/components/skeleton/cs-skeleton.js.map +1 -0
  69. package/dist/components/sonner/cs-sonner.js +76 -0
  70. package/dist/components/sonner/cs-sonner.js.map +1 -0
  71. package/dist/components/spinner/cs-spinner.js +34 -0
  72. package/dist/components/spinner/cs-spinner.js.map +1 -0
  73. package/dist/components/switch/cs-switch.js +38 -0
  74. package/dist/components/switch/cs-switch.js.map +1 -0
  75. package/dist/components/table/cs-data-base-table.js +108 -0
  76. package/dist/components/table/cs-data-base-table.js.map +1 -0
  77. package/dist/components/table/cs-data-table.js +32 -0
  78. package/dist/components/table/cs-data-table.js.map +1 -0
  79. package/dist/components/table/cs-skeleton-table.js +41 -0
  80. package/dist/components/table/cs-skeleton-table.js.map +1 -0
  81. package/dist/components/table/cs-table.js +120 -0
  82. package/dist/components/table/cs-table.js.map +1 -0
  83. package/dist/components/tabs/cs-simple-tabs.js +24 -0
  84. package/dist/components/tabs/cs-simple-tabs.js.map +1 -0
  85. package/dist/components/tabs/cs-tabs.js +114 -0
  86. package/dist/components/tabs/cs-tabs.js.map +1 -0
  87. package/dist/components/toggle/cs-toggle-group.js +65 -0
  88. package/dist/components/toggle/cs-toggle-group.js.map +1 -0
  89. package/dist/components/toggle/cs-toggle.js +46 -0
  90. package/dist/components/toggle/cs-toggle.js.map +1 -0
  91. package/dist/components/tooltip/cs-simple-tooltip.js +16 -0
  92. package/dist/components/tooltip/cs-simple-tooltip.js.map +1 -0
  93. package/dist/components/tooltip/cs-tooltip.js +72 -0
  94. package/dist/components/tooltip/cs-tooltip.js.map +1 -0
  95. package/dist/constants/cs-chart-option.constant.js +105 -0
  96. package/dist/constants/cs-chart-option.constant.js.map +1 -0
  97. package/dist/cs-ui.css +5 -96
  98. package/dist/hooks/use-accordion.js +54 -0
  99. package/dist/hooks/use-accordion.js.map +1 -0
  100. package/dist/hooks/use-infinite-scroll.js +40 -0
  101. package/dist/hooks/use-infinite-scroll.js.map +1 -0
  102. package/dist/hooks/use-laptop.js +20 -0
  103. package/dist/hooks/use-laptop.js.map +1 -0
  104. package/dist/hooks/use-mobile.js +20 -0
  105. package/dist/hooks/use-mobile.js.map +1 -0
  106. package/dist/index.d.ts +19 -6
  107. package/dist/index.js +287 -0
  108. package/dist/index.js.map +1 -0
  109. package/dist/lib/chart.util.js +48 -0
  110. package/dist/lib/chart.util.js.map +1 -0
  111. package/dist/lib/style.util.js +19 -0
  112. package/dist/lib/style.util.js.map +1 -0
  113. package/dist/lib/utils.js +27 -0
  114. package/dist/lib/utils.js.map +1 -0
  115. package/package.json +4 -5
  116. package/dist/index.cjs.js +0 -147660
  117. package/dist/index.cjs.js.map +0 -1
  118. package/dist/index.es.js +0 -147625
  119. package/dist/index.es.js.map +0 -1
@@ -0,0 +1,199 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { ChevronLeftIcon, ChevronRightIcon, ChevronDownIcon } from "lucide-react";
5
+ import { getDefaultClassNames, DayPicker } from "react-day-picker";
6
+ import { cn } from "../../lib/utils.js";
7
+ import { csButtonVariants, CsButton } from "../button/cs-button.js";
8
+ function CsCalendar({
9
+ className,
10
+ classNames,
11
+ showOutsideDays = true,
12
+ captionLayout = "label",
13
+ formatters,
14
+ components,
15
+ ...props
16
+ }) {
17
+ const defaultClassNames = getDefaultClassNames();
18
+ return /* @__PURE__ */ jsx(
19
+ DayPicker,
20
+ {
21
+ showOutsideDays,
22
+ className: cn(
23
+ "bg-(--calendar-container-bg) text-(--calendar-container-font) border-(length:--calendar-container-border-width) border-(--calendar-container-border) rounded-(--calendar-container-radius) group/calendar px-(--calendar-container-padding-x) py-(--calendar-container-padding-y) [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
24
+ String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
25
+ String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
26
+ className
27
+ ),
28
+ captionLayout,
29
+ formatters: {
30
+ formatMonthDropdown: (date) => date.toLocaleString("default", { month: "short" }),
31
+ ...formatters
32
+ },
33
+ classNames: {
34
+ root: cn("w-fit", defaultClassNames.root),
35
+ months: cn(
36
+ "flex gap-(--calendar-container-gap) flex-col md:flex-row relative typo-body-sm",
37
+ defaultClassNames.months
38
+ ),
39
+ month: cn("flex flex-col w-full gap-(--calendar-container-gap)", defaultClassNames.month),
40
+ nav: cn(
41
+ "flex items-center gap-(--calendar-days-radius) w-full absolute top-0 inset-x-0 justify-between",
42
+ defaultClassNames.nav
43
+ ),
44
+ button_previous: cn(
45
+ csButtonVariants({ variant: "ghost" }),
46
+ "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none text-(--calendar-container-icon) border-(length:--calendar-container-border-width) border-(--calendar-container-border) rounded-(--calendar-container-radius)",
47
+ defaultClassNames.button_previous
48
+ ),
49
+ button_next: cn(
50
+ csButtonVariants({ variant: "ghost" }),
51
+ "size-(--cell-size) aria-disabled:opacity-50 p-0 select-none text-(--calendar-container-icon) border-(length:--calendar-container-border-width) border-(--calendar-container-border) rounded-(--calendar-container-radius)",
52
+ defaultClassNames.button_next
53
+ ),
54
+ month_caption: cn(
55
+ "flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)",
56
+ defaultClassNames.month_caption
57
+ ),
58
+ month_grid: cn(
59
+ "typo-body-sm",
60
+ defaultClassNames.month_grid
61
+ ),
62
+ dropdowns: cn(
63
+ "w-full flex items-center font-medium justify-center h-(--cell-size) gap-(--calendar-days-radius)",
64
+ defaultClassNames.dropdowns
65
+ ),
66
+ dropdown_root: cn(
67
+ "relative border-(length:--calendar-container-border-width) border-(--calendar-container-border) rounded-(--calendar-container-radius)",
68
+ defaultClassNames.dropdown_root
69
+ ),
70
+ dropdown: cn(
71
+ "absolute bg-(--calendar-container-bg) inset-0 opacity-0",
72
+ defaultClassNames.dropdown
73
+ ),
74
+ caption_label: cn(
75
+ "select-none font-medium text-(--calendar-container-font)",
76
+ captionLayout === "label" ? "" : "rounded-(--calendar-container-radius) px-(--calendar-container-padding-x) py-(--calendar-container-padding-y) flex items-center gap-(--calendar-container-gap) h-(--scale-control-lg) [&>svg]:size-(--calendar-container-icon-size)",
77
+ defaultClassNames.caption_label
78
+ ),
79
+ table: "w-full border-collapse",
80
+ weekdays: cn("flex", defaultClassNames.weekdays),
81
+ weekday: cn(
82
+ "rounded-(--calendar-container-radius) flex-1 font-normal select-none text-(--calendar-days-week-font)",
83
+ defaultClassNames.weekday
84
+ ),
85
+ week: cn("flex w-full mt-(--calendar-container-gap)", defaultClassNames.week),
86
+ week_number_header: cn(
87
+ "select-none w-(--cell-size)",
88
+ defaultClassNames.week_number_header
89
+ ),
90
+ week_number: cn(
91
+ "select-none",
92
+ defaultClassNames.week_number
93
+ ),
94
+ day: cn(
95
+ "relative w-full h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none",
96
+ props.showWeekNumber ? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md" : "[&:first-child[data-selected=true]_button]:rounded-l-md",
97
+ defaultClassNames.day
98
+ ),
99
+ range_start: cn(
100
+ "rounded-l-md bg-(--calendar-days-current-bg) text-(--calendar-days-current-font)",
101
+ defaultClassNames.range_start
102
+ ),
103
+ range_middle: cn("rounded-none bg-(--calendar-days-selected-bg) text-(--calendar-days-selected-font)", defaultClassNames.range_middle),
104
+ range_end: cn("rounded-r-md bg-(--calendar-days-current-bg) text-(--calendar-days-current-font)", defaultClassNames.range_end),
105
+ today: cn(
106
+ "",
107
+ defaultClassNames.today
108
+ ),
109
+ outside: cn(
110
+ "",
111
+ defaultClassNames.outside
112
+ ),
113
+ disabled: cn(
114
+ "text-(--calendar-days-disabled-font) opacity-50",
115
+ defaultClassNames.disabled
116
+ ),
117
+ hidden: cn("invisible", defaultClassNames.hidden),
118
+ ...classNames
119
+ },
120
+ components: {
121
+ Root: ({ className: className2, rootRef, ...props2 }) => {
122
+ return /* @__PURE__ */ jsx(
123
+ "div",
124
+ {
125
+ "data-slot": "calendar",
126
+ ref: rootRef,
127
+ className: cn(className2),
128
+ ...props2
129
+ }
130
+ );
131
+ },
132
+ Chevron: ({ className: className2, orientation, ...props2 }) => {
133
+ if (orientation === "left") {
134
+ return /* @__PURE__ */ jsx(ChevronLeftIcon, { className: cn("size-4", className2), ...props2 });
135
+ }
136
+ if (orientation === "right") {
137
+ return /* @__PURE__ */ jsx(
138
+ ChevronRightIcon,
139
+ {
140
+ className: cn("size-4", className2),
141
+ ...props2
142
+ }
143
+ );
144
+ }
145
+ return /* @__PURE__ */ jsx(ChevronDownIcon, { className: cn("size-4", className2), ...props2 });
146
+ },
147
+ DayButton: CsCalendarDayButton,
148
+ WeekNumber: ({ children, ...props2 }) => {
149
+ return /* @__PURE__ */ jsx("td", { ...props2, children: /* @__PURE__ */ jsx("div", { className: "flex size-(--cell-size) items-center justify-center text-center", children }) });
150
+ },
151
+ ...components
152
+ },
153
+ ...props
154
+ }
155
+ );
156
+ }
157
+ function CsCalendarDayButton({
158
+ className,
159
+ day,
160
+ modifiers,
161
+ ...props
162
+ }) {
163
+ const defaultClassNames = getDefaultClassNames();
164
+ const ref = React.useRef(null);
165
+ React.useEffect(() => {
166
+ if (modifiers.focused) ref.current?.focus();
167
+ }, [modifiers.focused]);
168
+ return /* @__PURE__ */ jsx(
169
+ CsButton,
170
+ {
171
+ ref,
172
+ variant: "ghost",
173
+ "data-day": day.date.toLocaleDateString(),
174
+ "data-selected-single": modifiers.selected && !modifiers.range_start && !modifiers.range_end && !modifiers.range_middle,
175
+ "data-range-start": modifiers.range_start,
176
+ "data-range-end": modifiers.range_end,
177
+ "data-range-middle": modifiers.range_middle,
178
+ "data-range-middle-start": modifiers.range_middle,
179
+ "data-range-middle-end": modifiers.range_middle,
180
+ className: cn(
181
+ "flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-(--calendar-days-radius) leading-none font-normal rounded-(--calendar-days-radius)",
182
+ "text-(--calendar-days-default-font) hover:bg-(--calendar-days-hover-bg) hover:text-(--calendar-days-hover-font)",
183
+ "data-[selected-single=true]:bg-(--calendar-days-current-bg) data-[selected-single=true]:text-(--calendar-days-current-font)",
184
+ "data-[range-middle=true]:bg-(--calendar-days-selected-bg) data-[range-middle=true]:text-(--calendar-days-selected-font)",
185
+ "data-[range-start=true]:bg-(--calendar-days-current-bg) data-[range-start=true]:text-(--calendar-days-current-font)",
186
+ "data-[range-end=true]:bg-(--calendar-days-current-bg) data-[range-end=true]:text-(--calendar-days-current-font)",
187
+ "data-[range-end=true]:rounded-(--calendar-days-radius) data-[range-end=true]:rounded-r-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-(--calendar-days-radius) data-[range-start=true]:rounded-l-md",
188
+ defaultClassNames.day,
189
+ className
190
+ ),
191
+ ...props
192
+ }
193
+ );
194
+ }
195
+ export {
196
+ CsCalendar,
197
+ CsCalendarDayButton
198
+ };
199
+ //# sourceMappingURL=cs-calendar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cs-calendar.js","sources":["../../../src/components/calendar/cs-calendar.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n} from \"lucide-react\"\nimport { DayButton, DayPicker, getDefaultClassNames } from \"react-day-picker\"\n\nimport { cn } from \"../../lib/utils\"\nimport { CsButton, csButtonVariants } from \"../button\"\n\n/**\n * CsCalendar 스타일 시스템 (Design Token Reference)\n *\n * ## Figma Token → Props 매핑\n * | Figma 토큰 패턴 | 적용 |\n * |----------------|------|\n * | `calendar/container/*` | 컨테이너 스타일 (bg, border, padding 등) |\n * | `calendar/days/*` | 날짜 셀 스타일 |\n *\n * ## State 매핑\n * | UI 상태 | Token state | data 속성 |\n * |---------|-------------|----------|\n * | 기본 | `default` | - |\n * | hover | `hover` | - |\n * | 선택됨 (단일) | `current` | `data-selected-single=\"true\"` |\n * | 범위 시작/끝 | `current` | `data-range-start/end=\"true\"` |\n * | 범위 중간 | `selected` | `data-range-middle=\"true\"` |\n * | 비활성 | `disabled` | - |\n *\n * ## CSS Variables\n * ```css\n * --calendar-container-bg | font | border | border-width | radius | padding-x | padding-y | gap | icon | icon-size\n * --calendar-days-radius | week-font\n * --calendar-days-default-font | hover-bg | hover-font\n * --calendar-days-current-bg | current-font\n * --calendar-days-selected-bg | selected-font\n * --calendar-days-disabled-font\n * ```\n *\n * ## 선택 모드\n * | mode | 설명 |\n * |------|------|\n * | `single` | 단일 날짜 선택 |\n * | `multiple` | 다중 날짜 선택 |\n * | `range` | 날짜 범위 선택 |\n *\n * @see {@link https://react-day-picker.js.org/ | react-day-picker}\n */\n\n/**\n * CS Design System 캘린더 컴포넌트\n *\n * 날짜 선택을 위한 독립 실행형 캘린더 UI. react-day-picker 기반.\n * 단일 날짜, 다중 날짜, 날짜 범위 선택을 지원하며, 월/연도 드롭다운,\n * 특정 날짜 비활성화 등 다양한 옵션을 제공합니다.\n *\n * ## 사용 시나리오\n * - 단일 날짜 선택: `mode=\"single\"` - 생일, 약속 날짜, 이벤트 일자\n * - 날짜 범위 선택: `mode=\"range\"` - 휴가 기간, 예약 기간, 통계 기간\n * - 다중 날짜 선택: `mode=\"multiple\"` - 근무일 선택, 출석 체크\n * - 월 선택 UI: `captionLayout=\"dropdown\"` - 연도/월 드롭다운 표시\n * - 날짜 제한: `disabled` prop - 과거 날짜 비활성화, 특정 날짜 제외\n * - 항상 표시: 페이지 내 고정 캘린더 (예: 대시보드, 일정 페이지)\n *\n * ## 유사 컴포넌트와의 차이\n * - **CsDatePicker**: 버튼 + 팝오버 + 캘린더 - 폼 필드용\n * - Calendar는 독립 실행형 UI, DatePicker는 버튼으로 열리는 선택기\n *\n * @example 기본 (단일 선택)\n * ```tsx\n * <CsCalendar\n * mode=\"single\"\n * selected={date}\n * onSelect={setDate}\n * />\n * ```\n *\n * @example 범위 선택\n * ```tsx\n * <CsCalendar\n * mode=\"range\"\n * selected={dateRange}\n * onSelect={setDateRange}\n * />\n * ```\n *\n * @example 드롭다운 캡션\n * ```tsx\n * <CsCalendar captionLayout=\"dropdown\" />\n * ```\n *\n * @example 특정 날짜 비활성화\n * ```tsx\n * <CsCalendar\n * mode=\"single\"\n * disabled={{ before: new Date() }}\n * />\n * ```\n */\nfunction CsCalendar({\n className,\n classNames,\n showOutsideDays = true,\n captionLayout = \"label\",\n formatters,\n components,\n ...props\n}: React.ComponentProps<typeof DayPicker>) {\n const defaultClassNames = getDefaultClassNames()\n\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\n \"bg-(--calendar-container-bg) text-(--calendar-container-font) border-(length:--calendar-container-border-width) border-(--calendar-container-border) rounded-(--calendar-container-radius) group/calendar px-(--calendar-container-padding-x) py-(--calendar-container-padding-y) [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent\",\n String.raw`rtl:**:[.rdp-button\\_next>svg]:rotate-180`,\n String.raw`rtl:**:[.rdp-button\\_previous>svg]:rotate-180`,\n className\n )}\n captionLayout={captionLayout}\n formatters={{\n formatMonthDropdown: (date) =>\n date.toLocaleString(\"default\", { month: \"short\" }),\n ...formatters,\n }}\n classNames={{\n root: cn(\"w-fit\", defaultClassNames.root),\n months: cn(\n \"flex gap-(--calendar-container-gap) flex-col md:flex-row relative typo-body-sm\",\n defaultClassNames.months\n ),\n month: cn(\"flex flex-col w-full gap-(--calendar-container-gap)\", defaultClassNames.month),\n nav: cn(\n \"flex items-center gap-(--calendar-days-radius) w-full absolute top-0 inset-x-0 justify-between\",\n defaultClassNames.nav\n ),\n button_previous: cn(\n csButtonVariants({ variant: \"ghost\" }),\n \"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none text-(--calendar-container-icon) border-(length:--calendar-container-border-width) border-(--calendar-container-border) rounded-(--calendar-container-radius)\",\n defaultClassNames.button_previous\n ),\n button_next: cn(\n csButtonVariants({ variant: \"ghost\" }),\n \"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none text-(--calendar-container-icon) border-(length:--calendar-container-border-width) border-(--calendar-container-border) rounded-(--calendar-container-radius)\",\n defaultClassNames.button_next\n ),\n month_caption: cn(\n \"flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)\",\n defaultClassNames.month_caption\n ),\n month_grid: cn(\n \"typo-body-sm\",\n defaultClassNames.month_grid\n ),\n dropdowns: cn(\n \"w-full flex items-center font-medium justify-center h-(--cell-size) gap-(--calendar-days-radius)\",\n defaultClassNames.dropdowns\n ),\n dropdown_root: cn(\n \"relative border-(length:--calendar-container-border-width) border-(--calendar-container-border) rounded-(--calendar-container-radius)\",\n defaultClassNames.dropdown_root\n ),\n dropdown: cn(\n \"absolute bg-(--calendar-container-bg) inset-0 opacity-0\",\n defaultClassNames.dropdown\n ),\n caption_label: cn(\n \"select-none font-medium text-(--calendar-container-font)\",\n captionLayout === \"label\"\n ? \"\"\n : \"rounded-(--calendar-container-radius) px-(--calendar-container-padding-x) py-(--calendar-container-padding-y) flex items-center gap-(--calendar-container-gap) h-(--scale-control-lg) [&>svg]:size-(--calendar-container-icon-size)\",\n defaultClassNames.caption_label\n ),\n table: \"w-full border-collapse\",\n weekdays: cn(\"flex\", defaultClassNames.weekdays),\n weekday: cn(\n \"rounded-(--calendar-container-radius) flex-1 font-normal select-none text-(--calendar-days-week-font)\",\n defaultClassNames.weekday\n ),\n week: cn(\"flex w-full mt-(--calendar-container-gap)\", defaultClassNames.week),\n week_number_header: cn(\n \"select-none w-(--cell-size)\",\n defaultClassNames.week_number_header\n ),\n week_number: cn(\n \"select-none\",\n defaultClassNames.week_number\n ),\n day: cn(\n \"relative w-full h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none\",\n props.showWeekNumber\n ? \"[&:nth-child(2)[data-selected=true]_button]:rounded-l-md\"\n : \"[&:first-child[data-selected=true]_button]:rounded-l-md\",\n defaultClassNames.day\n ),\n range_start: cn(\n \"rounded-l-md bg-(--calendar-days-current-bg) text-(--calendar-days-current-font)\",\n defaultClassNames.range_start\n ),\n range_middle: cn(\"rounded-none bg-(--calendar-days-selected-bg) text-(--calendar-days-selected-font)\", defaultClassNames.range_middle),\n range_end: cn(\"rounded-r-md bg-(--calendar-days-current-bg) text-(--calendar-days-current-font)\", defaultClassNames.range_end),\n today: cn(\n \"\",\n defaultClassNames.today\n ),\n outside: cn(\n \"\",\n defaultClassNames.outside\n ),\n disabled: cn(\n \"text-(--calendar-days-disabled-font) opacity-50\",\n defaultClassNames.disabled\n ),\n hidden: cn(\"invisible\", defaultClassNames.hidden),\n ...classNames,\n }}\n components={{\n Root: ({ className, rootRef, ...props }) => {\n return (\n <div\n data-slot=\"calendar\"\n ref={rootRef}\n className={cn(className)}\n {...props}\n />\n )\n },\n Chevron: ({ className, orientation, ...props }) => {\n if (orientation === \"left\") {\n return (\n <ChevronLeftIcon className={cn(\"size-4\", className)} {...props} />\n )\n }\n\n if (orientation === \"right\") {\n return (\n <ChevronRightIcon\n className={cn(\"size-4\", className)}\n {...props}\n />\n )\n }\n\n return (\n <ChevronDownIcon className={cn(\"size-4\", className)} {...props} />\n )\n },\n DayButton: CsCalendarDayButton,\n WeekNumber: ({ children, ...props }) => {\n return (\n <td {...props}>\n <div className=\"flex size-(--cell-size) items-center justify-center text-center\">\n {children}\n </div>\n </td>\n )\n },\n ...components,\n }}\n {...props}\n />\n )\n}\n\n/**\n * 캘린더 날짜 버튼\n *\n * 개별 날짜 셀 렌더링. 선택/범위 상태에 따라 스타일 자동 적용.\n * 내부적으로 CsButton ghost variant 사용.\n */\nfunction CsCalendarDayButton({\n className,\n day,\n modifiers,\n ...props\n}: React.ComponentProps<typeof DayButton>) {\n const defaultClassNames = getDefaultClassNames()\n\n const ref = React.useRef<HTMLButtonElement>(null)\n React.useEffect(() => {\n if (modifiers.focused) ref.current?.focus()\n }, [modifiers.focused])\n\n return (\n <CsButton\n ref={ref}\n variant=\"ghost\"\n data-day={day.date.toLocaleDateString()}\n data-selected-single={\n modifiers.selected &&\n !modifiers.range_start &&\n !modifiers.range_end &&\n !modifiers.range_middle\n }\n data-range-start={modifiers.range_start}\n data-range-end={modifiers.range_end}\n data-range-middle={modifiers.range_middle}\n data-range-middle-start={modifiers.range_middle}\n data-range-middle-end={modifiers.range_middle}\n className={cn(\n \"flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-(--calendar-days-radius) leading-none font-normal rounded-(--calendar-days-radius)\",\n \"text-(--calendar-days-default-font) hover:bg-(--calendar-days-hover-bg) hover:text-(--calendar-days-hover-font)\",\n \"data-[selected-single=true]:bg-(--calendar-days-current-bg) data-[selected-single=true]:text-(--calendar-days-current-font)\",\n \"data-[range-middle=true]:bg-(--calendar-days-selected-bg) data-[range-middle=true]:text-(--calendar-days-selected-font)\",\n \"data-[range-start=true]:bg-(--calendar-days-current-bg) data-[range-start=true]:text-(--calendar-days-current-font)\",\n \"data-[range-end=true]:bg-(--calendar-days-current-bg) data-[range-end=true]:text-(--calendar-days-current-font)\",\n \"data-[range-end=true]:rounded-(--calendar-days-radius) data-[range-end=true]:rounded-r-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-(--calendar-days-radius) data-[range-start=true]:rounded-l-md\",\n defaultClassNames.day,\n className\n )}\n {...props}\n />\n )\n}\n\ntype CsCalendarProps = React.ComponentProps<typeof DayPicker>\n\nexport { CsCalendar, CsCalendarDayButton, type CsCalendarProps }\n"],"names":["props"],"mappings":";;;;;;;AAsGoB,SAClB,WAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA,kBAAgB;AAAA,EAChB,gBAAA;AAAA,EACA;AAAA,EACA;AAAA,EACF,GAA2C;AACzC,GAAA;AAEA,4BACE,qBAAA;AAAA,SAAC;AAAA,IAAA;AAAA,IAAA;AAAA,MAEC;AAAA,MAAW,WACT;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP,OAAA;AAAA,QACF;AAAA,MACA;AAAA,MACA;AAAA,MAAY;QAGV,qBAAG,CAAA,SAAA,KAAA,eAAA,WAAA,EAAA,OAAA,QAAA,CAAA;AAAA,QACL,GAAA;AAAA,MACA;AAAA,MAAY;QAEV,MAAA,GAAQ,SAAA,kBAAA,IAAA;AAAA,QAAA,QACN;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QACA,OAAK,GAAA,uDAAA,kBAAA,KAAA;AAAA,QAAA,KACH;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QAAiB;UAEf,iBAAA,EAAA,SAAA,QAAA,CAAA;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QAAa;UAEX,iBAAA,EAAA,SAAA,QAAA,CAAA;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QAAe,eACb;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QAAY,YACV;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QAAW,WACT;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QAAe,eACb;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QAAU,UACR;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QAAe,eACb;AAAA,UACA;AAAA,UAGA,kBAAkB,UAAA,KAAA;AAAA,UACpB,kBAAA;AAAA,QACA;AAAA,QACA,OAAA;AAAA,QACA,UAAS,GAAA,QAAA,kBAAA,QAAA;AAAA,QAAA,SACP;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QACA,MAAA,GAAA,6CAAoB,kBAAA,IAAA;AAAA,QAAA,oBAClB;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QAAa,aACX;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QAAK,KACH;AAAA,UACA;AAAA,UAGA,uBAAkB,6DAAA;AAAA,UACpB,kBAAA;AAAA,QACA;AAAA,QAAa,aACX;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QACA,cAAc,yFAAoF,kBAAkB,YAAS;AAAA,QAC7H,WAAO,GAAA,oFAAA,kBAAA,SAAA;AAAA,QAAA,OACL;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QAAS,SACP;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QAAU,UACR;AAAA,UACA;AAAA,UACF,kBAAA;AAAA,QACA;AAAA,QACA,QAAG,GAAA,aAAA,kBAAA,MAAA;AAAA,QACL,GAAA;AAAA,MACA;AAAA,MAAY,YACD;AAAA,QACP,gCACE,SAAA,GAAA,OAAA,MAAA;AAAA,iBAAC;AAAA,YAAA;AAAA,YAAA;AAAA,cAEC,aAAK;AAAA,cACL,KAAA;AAAA,cACC,WAAGA,GAAAA,UAAAA;AAAAA,cAAA,GAAA;AAAA,YACN;AAAA,UAEJ;AAAA,QACA;AAAA,QACE,SAAI,CAAA,EAAA,WAAgB,YAAQ,aAAA,GAAA,OAAA,MAAA;AAC1B,sCACE;AAEJ,mBAAA,oBAAA,iBAAA,EAAA,WAAA,GAAA,UAAA,UAAA,GAAA,GAAA,OAAA,CAAA;AAAA,UAEA;AACE,uCACE;AAAA,mBAAC;AAAA,cAAA;AAAA,cAAA;AAAA,gBAEE,WAAGA,GAAAA,UAAAA,UAAAA;AAAAA,gBAAA,GAAA;AAAA,cACN;AAAA,YAEJ;AAAA,UAEA;AAGF,iBAAA,oBAAA,iBAAA,EAAA,WAAA,GAAA,UAAA,UAAA,GAAA,GAAA,OAAA,CAAA;AAAA,QACA;AAAA,QACA;QACE,YAAA,CAAA,EAAA,UACE,GAAA,aAAQA;AAMZ,iBAAA,oBAAA,MAAA,EAAA,GAAA,QAAA,UAAA,oBAAA,OAAA,EAAA,WAAA,mEAAA,SAAA,CAAA,EAAA,CAAA;AAAA,QACA;AAAA,QACF,GAAA;AAAA,MACC;AAAA,MAAG,GAAA;AAAA,IACN;AAAA,EAEJ;AAQA;AAA6B,SAC3B,oBAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACF,GAA2C;AACzC,GAAA;AAEA,QAAM,yCAA0C;AAChD,QAAM,MAAA,MAAU,OAAM,IAAA;AACpB,QAAI,UAAU,MAAA;AAChB,kBAAc,QAAQ,KAAA,SAAA,MAAA;AAAA,EAEtB;AACE,SAAC;AAAA,IAAA;AAAA,IAAA;AAAA,MAEC;AAAA,MACA;MACA,wCACY;AAAA,MAKZ,wBAAkB,UAAU,YAAA,CAAA,UAAA,eAAA,CAAA,UAAA,aAAA,CAAA,UAAA;AAAA,MAC5B,oBAAgB,UAAU;AAAA,MAC1B,kBAAA,UAAmB;AAAA,MACnB,qBAAA,UAAyB;AAAA,MACzB,2BAAuB,UAAU;AAAA,MACjC,yBAAW,UAAA;AAAA,MAAA,WACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,kBAAA;AAAA,QACF;AAAA,MACC;AAAA,MAAG,GAAA;AAAA,IACN;AAAA,EAEJ;;"}
@@ -0,0 +1,95 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/utils.js";
3
+ function CsCard({ className, ...props }) {
4
+ return /* @__PURE__ */ jsx(
5
+ "div",
6
+ {
7
+ "data-slot": "card",
8
+ className: cn(
9
+ "bg-(--card-common-bg) flex flex-col rounded-(--card-common-radius) border-(length:--card-common-border-width) border-(--card-common-border) gap-(--card-common-gap) max-mobile:gap-(--card-common-gap-mobile) py-(--card-common-padding-y) max-mobile:py-(--card-common-padding-y-mobile) px-(--card-common-padding-x) max-mobile:px-(--card-common-padding-x-mobile) hover:bg-(--card-common-bg-hover) hover:border-(--card-common-border-hover)",
10
+ className
11
+ ),
12
+ ...props
13
+ }
14
+ );
15
+ }
16
+ function CsCardHeader({ className, ...props }) {
17
+ return /* @__PURE__ */ jsx(
18
+ "div",
19
+ {
20
+ "data-slot": "card-header",
21
+ className: cn(
22
+ "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-(--card-container-header-gap) has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-(--card-common-padding-y) [.border-b]:border-(--card-common-border)",
23
+ className
24
+ ),
25
+ ...props
26
+ }
27
+ );
28
+ }
29
+ function CsCardTitle({ className, ...props }) {
30
+ return /* @__PURE__ */ jsx(
31
+ "div",
32
+ {
33
+ "data-slot": "card-title",
34
+ className: cn(
35
+ "typo-heading-md",
36
+ "text-(--card-container-header-title)",
37
+ className
38
+ ),
39
+ ...props
40
+ }
41
+ );
42
+ }
43
+ function CsCardDescription({ className, ...props }) {
44
+ return /* @__PURE__ */ jsx(
45
+ "div",
46
+ {
47
+ "data-slot": "card-description",
48
+ className: cn("typo-body-sm text-(--card-container-header-description)", className),
49
+ ...props
50
+ }
51
+ );
52
+ }
53
+ function CsCardAction({ className, ...props }) {
54
+ return /* @__PURE__ */ jsx(
55
+ "div",
56
+ {
57
+ "data-slot": "card-action",
58
+ className: cn(
59
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
60
+ className
61
+ ),
62
+ ...props
63
+ }
64
+ );
65
+ }
66
+ function CsCardContent({ className, ...props }) {
67
+ return /* @__PURE__ */ jsx(
68
+ "div",
69
+ {
70
+ "data-slot": "card-content",
71
+ className: cn("flex flex-col gap-(--card-container-content-gap)", className),
72
+ ...props
73
+ }
74
+ );
75
+ }
76
+ function CsCardFooter({ className, ...props }) {
77
+ return /* @__PURE__ */ jsx(
78
+ "div",
79
+ {
80
+ "data-slot": "card-footer",
81
+ className: cn("flex items-center gap-(--card-container-footer-gap) [.border-t]:pt-(--card-common-padding-y) [.border-t]:border-(--card-common-border)", className),
82
+ ...props
83
+ }
84
+ );
85
+ }
86
+ export {
87
+ CsCard,
88
+ CsCardAction,
89
+ CsCardContent,
90
+ CsCardDescription,
91
+ CsCardFooter,
92
+ CsCardHeader,
93
+ CsCardTitle
94
+ };
95
+ //# sourceMappingURL=cs-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cs-card.js","sources":["../../../src/components/card/cs-card.tsx"],"sourcesContent":["import * as React from \"react\"\n\nimport { cn } from \"../../lib/utils\"\n\n/**\n * CsCard 스타일 시스템 (Design Token Reference)\n *\n * ## Figma Token → Props 매핑\n * | Figma 토큰 패턴 | 컴포넌트 |\n * |----------------|---------|\n * | `card/common/*` | `CsCard` (컨테이너) |\n * | `card/container/header-*` | `CsCardHeader`, `CsCardTitle`, `CsCardDescription` |\n * | `card/container/content-*` | `CsCardContent` |\n * | `card/container/footer-*` | `CsCardFooter` |\n *\n * ## State 매핑\n * | UI 상태 | Token state | 적용 |\n * |---------|-------------|------|\n * | 기본 | `default` | bg, border |\n * | hover: | `hover` | bg-hover, border-hover |\n *\n * ## CSS Variables\n * ```css\n * --card-common-bg | radius | border | border-width | gap | padding-x | padding-y\n * --card-common-bg-hover | border-hover\n * --card-common-*-mobile (반응형)\n * --card-container-header-gap | header-title | header-description\n * --card-container-content-gap | footer-gap\n * ```\n *\n * ## 서브 컴포넌트 구조\n * ```\n * CsCard\n * ├── CsCardHeader\n * │ ├── CsCardTitle\n * │ ├── CsCardDescription\n * │ └── CsCardAction (선택)\n * ├── CsCardContent\n * └── CsCardFooter\n * ```\n */\n\n/**\n * CsCard Props\n *\n * HTML div 요소의 모든 속성을 상속받습니다.\n * 추가 variant나 size props 없이 토큰 기반 스타일링 적용.\n */\ntype CsCardProps = React.ComponentProps<\"div\">\n\n/**\n * CS Design System 카드 컨테이너\n *\n * 관련 콘텐츠를 그룹화하는 상호작용 가능한 레이아웃 컴포넌트.\n * 대시보드, 리스트, 프로필 카드 등에 사용되며, hover 효과와 클릭 상호작용이 있습니다.\n * 서브 컴포넌트를 조합하여 다양한 카드 UI를 구성할 수 있습니다.\n *\n * ## 사용 시나리오\n * - 대시보드 카드: 통계, 그래프, 요약 정보를 담는 패널\n * - 리스트 아이템: 프로젝트, 제품, 사용자 카드 목록\n * - 프로필 카드: 사용자 정보, 팀 멤버 소개\n * - 콘텐츠 그룹: 관련 정보를 시각적으로 묶어서 표시\n *\n * ## 유사 컴포넌트와의 차이\n * - **CsBox**: 상호작용 없는 단순 컨테이너 (hover, click 없음)\n * - Card는 hover/click 있음, Box는 정적 레이아웃만\n *\n * @example 기본 조합\n * ```tsx\n * <CsCard>\n * <CsCardHeader>\n * <CsCardTitle>제목</CsCardTitle>\n * <CsCardDescription>설명 텍스트</CsCardDescription>\n * </CsCardHeader>\n * <CsCardContent>본문 내용</CsCardContent>\n * <CsCardFooter>하단 영역</CsCardFooter>\n * </CsCard>\n * ```\n *\n * @example 헤더 액션 버튼\n * ```tsx\n * <CsCardHeader>\n * <CsCardTitle>제목</CsCardTitle>\n * <CsCardAction><CsButton>액션</CsButton></CsCardAction>\n * </CsCardHeader>\n * ```\n *\n * @example 구분선 추가\n * ```tsx\n * <CsCardHeader className=\"border-b\">...</CsCardHeader>\n * <CsCardFooter className=\"border-t\">...</CsCardFooter>\n * ```\n */\nfunction CsCard({ className, ...props }: CsCardProps) {\n return (\n <div\n data-slot=\"card\"\n className={cn(\n \"bg-(--card-common-bg) flex flex-col rounded-(--card-common-radius) border-(length:--card-common-border-width) border-(--card-common-border) gap-(--card-common-gap) max-mobile:gap-(--card-common-gap-mobile) py-(--card-common-padding-y) max-mobile:py-(--card-common-padding-y-mobile) px-(--card-common-padding-x) max-mobile:px-(--card-common-padding-x-mobile) hover:bg-(--card-common-bg-hover) hover:border-(--card-common-border-hover)\",\n className\n )}\n {...props}\n />\n )\n}\n\n/**\n * 카드 헤더 영역\n *\n * CsCardAction 포함 시 자동으로 2열 그리드 레이아웃 적용.\n * `border-b` 클래스 추가 시 하단 구분선 표시.\n *\n * @example\n * ```tsx\n * <CsCardHeader>\n * <CsCardTitle>제목</CsCardTitle>\n * <CsCardDescription>설명</CsCardDescription>\n * </CsCardHeader>\n * ```\n */\nfunction CsCardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-(--card-container-header-gap) has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-(--card-common-padding-y) [.border-b]:border-(--card-common-border)\",\n className\n )}\n {...props}\n />\n )\n}\n\n/**\n * 카드 제목\n *\n * `typo-heading-md` 타이포그래피 적용.\n * 색상: `--card-container-header-title`\n */\nfunction CsCardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\n \"typo-heading-md\",\n \"text-(--card-container-header-title)\",\n className\n )}\n {...props}\n />\n )\n}\n\n/**\n * 카드 설명 텍스트\n *\n * `typo-body-sm` 타이포그래피 적용.\n * 색상: `--card-container-header-description`\n */\nfunction CsCardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"typo-body-sm text-(--card-container-header-description)\", className)}\n {...props}\n />\n )\n}\n\n/**\n * 헤더 우측 액션 영역\n *\n * CsCardHeader 내에서 사용. 자동으로 우측 상단에 배치됨.\n * 버튼, 드롭다운 등 액션 요소 배치용.\n *\n * @example\n * ```tsx\n * <CsCardAction>\n * <CsButton variant=\"ghost\" size=\"small\"><MoreVertical /></CsButton>\n * </CsCardAction>\n * ```\n */\nfunction CsCardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\n/**\n * 카드 본문 영역\n *\n * 내부 요소 간 간격: `--card-container-content-gap`\n * flex column 레이아웃 적용.\n */\nfunction CsCardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"flex flex-col gap-(--card-container-content-gap)\", className)}\n {...props}\n />\n )\n}\n\n/**\n * 카드 하단 영역\n *\n * `border-t` 클래스 추가 시 상단 구분선 표시.\n * 내부 요소 간 간격: `--card-container-footer-gap`\n *\n * @example\n * ```tsx\n * <CsCardFooter className=\"border-t\">\n * <CsButton variant=\"outline\">취소</CsButton>\n * <CsButton>저장</CsButton>\n * </CsCardFooter>\n * ```\n */\nfunction CsCardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\"flex items-center gap-(--card-container-footer-gap) [.border-t]:pt-(--card-common-padding-y) [.border-t]:border-(--card-common-border)\", className)}\n {...props}\n />\n )\n}\n\nexport {\n CsCard,\n CsCardHeader,\n CsCardFooter,\n CsCardTitle,\n CsCardAction,\n CsCardDescription,\n CsCardContent,\n type CsCardProps,\n}\n"],"names":[],"mappings":";;AA6FA,SAAS,OAAO,EAAE,WAAW,GAAG,SAAsB;AACpD,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAED,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV;AAgBA,SAAS,aAAa,EAAE,WAAW,GAAG,SAAsC;AAC1E,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAED,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV;AAQA,SAAS,YAAY,EAAE,WAAW,GAAG,SAAsC;AACzE,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,MAED,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV;AAQA,SAAS,kBAAkB,EAAE,WAAW,GAAG,SAAsC;AAC/E,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,2DAA2D,SAAS;AAAA,MACjF,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV;AAeA,SAAS,aAAa,EAAE,WAAW,GAAG,SAAsC;AAC1E,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MAAA;AAAA,MAED,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV;AAQA,SAAS,cAAc,EAAE,WAAW,GAAG,SAAsC;AAC3E,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,oDAAoD,SAAS;AAAA,MAC1E,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV;AAgBA,SAAS,aAAa,EAAE,WAAW,GAAG,SAAsC;AAC1E,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,WAAW,GAAG,0IAA0I,SAAS;AAAA,MAChK,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV;"}
@@ -0,0 +1,88 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { XChartsBody } from "x-charts";
3
+ import { getAreaOpacity, getPieChartColors, getChartColors, mergeOptions } from "../../lib/chart.util.js";
4
+ import { CsLineChartTheme, CsChartBaseOptions, getCsChartZoomOptions, CsChartAxisOptions } from "../../constants/cs-chart-option.constant.js";
5
+ function CsChartBase({ customOptions, style, renderer = "svg", ...rest }) {
6
+ return /* @__PURE__ */ jsx(
7
+ XChartsBody,
8
+ {
9
+ renderer,
10
+ ...rest,
11
+ customOptions: { ...customOptions },
12
+ style: {
13
+ height: "300px",
14
+ width: "100%",
15
+ ...style
16
+ }
17
+ }
18
+ );
19
+ }
20
+ function useChartOptions(props, defaultType) {
21
+ const { customOptions: userCustomOptions, series, ...rest } = props;
22
+ const seriesCount = series?.length || userCustomOptions?.series?.length || rest.data?.length || 0;
23
+ const colors = defaultType === "pie" ? getPieChartColors() : getChartColors(seriesCount);
24
+ const baseDefaults = [CsChartBaseOptions];
25
+ if (defaultType !== "pie") {
26
+ baseDefaults.push(CsChartAxisOptions);
27
+ }
28
+ if (defaultType === "line" || defaultType === "area") {
29
+ baseDefaults.push(getCsChartZoomOptions());
30
+ }
31
+ const defaultOptions = mergeOptions(...baseDefaults);
32
+ if (defaultType === "pie") {
33
+ const pieDefaults = { xAxis: { show: false }, yAxis: { show: false } };
34
+ Object.assign(defaultOptions, pieDefaults);
35
+ }
36
+ const mergedCustomOptions = mergeOptions(
37
+ defaultOptions,
38
+ userCustomOptions,
39
+ colors && defaultType !== "pie" ? { color: colors } : {},
40
+ // Pie handles colors in seriesTheme
41
+ { series }
42
+ );
43
+ return { mergedCustomOptions, rest, colors };
44
+ }
45
+ function CsLineChart(props) {
46
+ const { mergedCustomOptions, rest } = useChartOptions(props, "line");
47
+ return /* @__PURE__ */ jsx(CsChartBase, { defaultType: "line", theme: CsLineChartTheme, customOptions: mergedCustomOptions, ...rest });
48
+ }
49
+ function CsAreaChart(props) {
50
+ const { mergedCustomOptions, rest } = useChartOptions(props, "area");
51
+ const areaOpacity = getAreaOpacity();
52
+ const themeWithOpacity = {
53
+ ...CsLineChartTheme,
54
+ line: {
55
+ ...CsLineChartTheme.line,
56
+ areaStyle: {
57
+ opacity: areaOpacity
58
+ }
59
+ }
60
+ };
61
+ return /* @__PURE__ */ jsx(CsChartBase, { defaultType: "line", theme: themeWithOpacity, customOptions: mergedCustomOptions, ...rest });
62
+ }
63
+ function CsBarChart(props) {
64
+ const { mergedCustomOptions, rest } = useChartOptions(props, "bar");
65
+ return /* @__PURE__ */ jsx(CsChartBase, { defaultType: "bar", customOptions: mergedCustomOptions, ...rest });
66
+ }
67
+ function CsPieChart(props) {
68
+ const { mergedCustomOptions, rest, colors } = useChartOptions(props, "pie");
69
+ return /* @__PURE__ */ jsx(
70
+ CsChartBase,
71
+ {
72
+ defaultType: "pie",
73
+ customOptions: mergedCustomOptions,
74
+ seriesTheme: { radius: ["40%", "70%"], color: colors, ...props.seriesTheme },
75
+ ...rest
76
+ }
77
+ );
78
+ }
79
+ export {
80
+ CsAreaChart,
81
+ CsBarChart,
82
+ CsChartBase as CsChart,
83
+ CsChartBase,
84
+ CsLineChart,
85
+ CsLineChartTheme,
86
+ CsPieChart
87
+ };
88
+ //# sourceMappingURL=cs-chart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cs-chart.js","sources":["../../../src/components/chart/cs-chart.tsx"],"sourcesContent":["import { XChartsBody } from 'x-charts'\nimport { IXChartBodyProps } from 'x-charts/components/chart/x-charts-body'\nimport { getChartColors, mergeOptions, getAreaOpacity, getPieChartColors } from '../../lib/chart.util'\nimport { CsChartAxisOptions, CsChartBaseOptions, getCsChartZoomOptions, CsLineChartTheme } from '../../constants/cs-chart-option.constant'\n\n/**\n * CsChart 스타일 시스템 (Design Token Reference)\n *\n * ## 차트 컴포넌트 종류\n * | 컴포넌트 | 용도 |\n * |----------|------|\n * | CsLineChart | 선형 차트 |\n * | CsAreaChart | 영역 차트 (투명도 적용) |\n * | CsBarChart | 막대 차트 |\n * | CsPieChart | 파이 차트 (도넛형) |\n * | CsChartBase | 커스텀 차트용 베이스 |\n *\n * ## 토큰 관리\n * 디자인 토큰은 `chart.util.ts`에서 관리:\n * - `getChartColors()`: 시리즈 색상\n * - `getPieChartColors()`: 파이 차트 색상\n * - `getAreaOpacity()`: 영역 투명도\n *\n * ## 차트 옵션 상수\n * `cs-chart-option.constant.ts`:\n * - `CsChartBaseOptions`: 기본 옵션\n * - `CsChartAxisOptions`: 축 옵션\n * - `getCsChartZoomOptions()`: 줌 옵션\n * - `CsLineChartTheme`: 선형 차트 테마\n *\n * @see {@link https://echarts.apache.org/ | ECharts}\n */\n\n/**\n * CS Design System 차트 컴포넌트\n *\n * ECharts 기반 데이터 시각화 컴포넌트. Line, Area, Bar, Pie 차트 제공.\n * 통계, 추이, 비율 등 다양한 데이터를 그래프로 표현할 때 사용됩니다.\n * x-charts 라이브러리를 래핑하여 일관된 스타일을 제공합니다.\n *\n * ## 사용 시나리오\n * - 추이 분석 (`CsLineChart`): 시간별 매출, 방문자 추이, 주가 변동\n * - 영역 비교 (`CsAreaChart`): 누적 데이터, 범위 표시, 다중 계열 비교\n * - 항목 비교 (`CsBarChart`): 카테고리별 판매량, 지역별 통계, 순위\n * - 비율 표시 (`CsPieChart`): 시장 점유율, 예산 배분, 응답 분포\n * - 대시보드: 여러 차트를 조합한 통계 대시보드\n * - 실시간 데이터: customOptions로 실시간 업데이트\n *\n * @example Line Chart\n * ```tsx\n * <CsLineChart\n * customOptions={{\n * xAxis: { data: ['Mon', 'Tue', 'Wed'] },\n * series: [{ data: [150, 230, 224] }]\n * }}\n * />\n * ```\n *\n * @example Area Chart\n * ```tsx\n * <CsAreaChart customOptions={{ ... }} />\n * ```\n *\n * @example Bar Chart\n * ```tsx\n * <CsBarChart customOptions={{ ... }} />\n * ```\n *\n * @example Pie Chart\n * ```tsx\n * <CsPieChart\n * customOptions={{\n * series: [{\n * data: [\n * { value: 1048, name: 'Search' },\n * { value: 735, name: 'Direct' },\n * ]\n * }]\n * }}\n * />\n * ```\n */\n/**\n * CsChartBase Props\n */\ntype CsChartBaseProps = IXChartBodyProps & {\n /**\n * 렌더러 타입\n * @default 'svg'\n */\n renderer?: 'svg' | 'canvas'\n}\n\n/** 차트 베이스 컴포넌트 - 커스텀 차트 구현용 */\nexport function CsChartBase({ customOptions, style, renderer='svg', ...rest }: CsChartBaseProps) {\n return (\n <XChartsBody \n renderer={renderer}\n {...rest} \n customOptions={{ ...customOptions }} \n style={{ \n height: '300px', \n width: '100%', \n ...style \n }} \n />\n )\n}\n\n// Internal Hook for shared options logic\nfunction useChartOptions(props: IXChartBodyProps, defaultType: 'line' | 'bar' | 'pie') {\n const { customOptions: userCustomOptions, series, ...rest } = props as any\n const seriesCount = series?.length || userCustomOptions?.series?.length || rest.data?.length || 0;\n \n const colors = defaultType === 'pie' \n ? getPieChartColors() \n : getChartColors(seriesCount);\n\n // Common defaults\n const baseDefaults = [CsChartBaseOptions];\n\n if (defaultType !== 'pie') {\n baseDefaults.push(CsChartAxisOptions);\n }\n\n if (defaultType === 'line' || (defaultType as string) === 'area') {\n baseDefaults.push(getCsChartZoomOptions());\n }\n\n const defaultOptions = mergeOptions(...baseDefaults);\n \n // Specific default for Pie\n if (defaultType === 'pie') {\n // Pie chart specific axes hiding\n const pieDefaults = { xAxis: { show: false }, yAxis: { show: false } };\n Object.assign(defaultOptions, pieDefaults); // mergeOptions creates deep copy, so safe to mutate or just pass to next merge\n }\n\n const mergedCustomOptions = mergeOptions(\n defaultOptions,\n userCustomOptions,\n (colors && defaultType !== 'pie') ? { color: colors } : {}, // Pie handles colors in seriesTheme\n { series }\n );\n\n return { mergedCustomOptions, rest, colors };\n}\n\n\n/** 선형 차트 */\nexport function CsLineChart(props: IXChartBodyProps) {\n const { mergedCustomOptions, rest } = useChartOptions(props, 'line');\n return <CsChartBase defaultType=\"line\" theme={CsLineChartTheme} customOptions={mergedCustomOptions} {...rest} />\n}\n\n/** 영역 차트 - 투명도 자동 적용 */\nexport function CsAreaChart(props: IXChartBodyProps) {\n const { mergedCustomOptions, rest } = useChartOptions(props, 'area' as any); // Treat area as line for zoom options\n const areaOpacity = getAreaOpacity();\n\n const themeWithOpacity = {\n ...CsLineChartTheme,\n line: {\n ...CsLineChartTheme.line,\n areaStyle: {\n opacity: areaOpacity\n }\n }\n }\n\n return <CsChartBase defaultType=\"line\" theme={themeWithOpacity} customOptions={mergedCustomOptions} {...rest} />\n}\n\n/** 막대 차트 */\nexport function CsBarChart(props: IXChartBodyProps) {\n const { mergedCustomOptions, rest } = useChartOptions(props, 'bar');\n return <CsChartBase defaultType=\"bar\" customOptions={mergedCustomOptions} {...rest} />\n}\n\n/** 파이 차트 - 도넛형 기본 적용 */\nexport function CsPieChart(props: IXChartBodyProps) {\n const { mergedCustomOptions, rest, colors } = useChartOptions(props, 'pie');\n \n return (\n <CsChartBase \n defaultType=\"pie\" \n customOptions={mergedCustomOptions} \n seriesTheme={{ radius: ['40%', '70%'], color: colors, ...props.seriesTheme } as any} \n {...rest} \n />\n )\n}\n\n\nexport { CsChartBase as CsChart, type CsChartBaseProps }\nexport { CsLineChartTheme } from '../../constants/cs-chart-option.constant'"],"names":[],"mappings":";;;;AA8FO,SAAS,YAAY,EAAE,eAAe,OAAO,WAAS,OAAO,GAAG,QAA0B;AAC/F,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC;AAAA,MACC,GAAG;AAAA,MACJ,eAAe,EAAE,GAAG,cAAA;AAAA,MACpB,OAAO;AAAA,QACL,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,GAAG;AAAA,MAAA;AAAA,IACL;AAAA,EAAA;AAGN;AAGA,SAAS,gBAAgB,OAAyB,aAAqC;AACrF,QAAM,EAAE,eAAe,mBAAmB,QAAQ,GAAG,SAAS;AAC9D,QAAM,cAAc,QAAQ,UAAU,mBAAmB,QAAQ,UAAU,KAAK,MAAM,UAAU;AAEhG,QAAM,SAAS,gBAAgB,QAC3B,kBAAA,IACA,eAAe,WAAW;AAG9B,QAAM,eAAe,CAAC,kBAAkB;AAExC,MAAI,gBAAgB,OAAO;AACzB,iBAAa,KAAK,kBAAkB;AAAA,EACtC;AAEA,MAAI,gBAAgB,UAAW,gBAA2B,QAAQ;AAChE,iBAAa,KAAK,uBAAuB;AAAA,EAC3C;AAEA,QAAM,iBAAiB,aAAa,GAAG,YAAY;AAGnD,MAAI,gBAAgB,OAAO;AAExB,UAAM,cAAc,EAAE,OAAO,EAAE,MAAM,MAAA,GAAS,OAAO,EAAE,MAAM,QAAM;AACnE,WAAO,OAAO,gBAAgB,WAAW;AAAA,EAC5C;AAEA,QAAM,sBAAsB;AAAA,IAC1B;AAAA,IACA;AAAA,IACC,UAAU,gBAAgB,QAAS,EAAE,OAAO,OAAA,IAAW,CAAA;AAAA;AAAA,IACxD,EAAE,OAAA;AAAA,EAAO;AAGX,SAAO,EAAE,qBAAqB,MAAM,OAAA;AACtC;AAIO,SAAS,YAAY,OAAyB;AACnD,QAAM,EAAE,qBAAqB,KAAA,IAAS,gBAAgB,OAAO,MAAM;AACnE,SAAO,oBAAC,eAAY,aAAY,QAAO,OAAO,kBAAkB,eAAe,qBAAsB,GAAG,KAAA,CAAM;AAChH;AAGO,SAAS,YAAY,OAAyB;AACnD,QAAM,EAAE,qBAAqB,KAAA,IAAS,gBAAgB,OAAO,MAAa;AAC1E,QAAM,cAAc,eAAA;AAEpB,QAAM,mBAAmB;AAAA,IACvB,GAAG;AAAA,IACH,MAAM;AAAA,MACJ,GAAG,iBAAiB;AAAA,MACpB,WAAW;AAAA,QACT,SAAS;AAAA,MAAA;AAAA,IACX;AAAA,EACF;AAGF,SAAO,oBAAC,eAAY,aAAY,QAAO,OAAO,kBAAkB,eAAe,qBAAsB,GAAG,KAAA,CAAM;AAChH;AAGO,SAAS,WAAW,OAAyB;AAClD,QAAM,EAAE,qBAAqB,KAAA,IAAS,gBAAgB,OAAO,KAAK;AAClE,6BAAQ,aAAA,EAAY,aAAY,OAAM,eAAe,qBAAsB,GAAG,MAAM;AACtF;AAGO,SAAS,WAAW,OAAyB;AAClD,QAAM,EAAE,qBAAqB,MAAM,WAAW,gBAAgB,OAAO,KAAK;AAE1E,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAY;AAAA,MACZ,eAAe;AAAA,MACf,aAAa,EAAE,QAAQ,CAAC,OAAO,KAAK,GAAG,OAAO,QAAQ,GAAG,MAAM,YAAA;AAAA,MAC9D,GAAG;AAAA,IAAA;AAAA,EAAA;AAGV;"}
@@ -0,0 +1,55 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
4
+ import { CheckIcon } from "lucide-react";
5
+ import { cn } from "../../lib/utils.js";
6
+ import { cva } from "class-variance-authority";
7
+ const csCheckboxVariants = cva(
8
+ "peer focus-visible:ring-0 size-(--checkbox-common-scale) shrink-0 transition-colors outline-none disabled:cursor-not-allowed rounded-(--checkbox-common-radius) disabled:opacity-(--checkbox-common-opacity) [&_svg]:size-(--checkbox-common-icon-size)",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ solid: [
13
+ "bg-(--checkbox-solid-default-bg) hover:bg-(--checkbox-solid-hover-bg)",
14
+ "data-[state=checked]:bg-(--checkbox-solid-checked-bg) data-[state=checked]:[&_svg]:text-(--checkbox-solid-checked-icon)"
15
+ ].join(" "),
16
+ outline: [
17
+ "bg-(--checkbox-outline-default-bg) border-(length:--checkbox-outline-border-width) border-(--checkbox-outline-default-border)",
18
+ "hover:bg-(--checkbox-outline-hover-bg) hover:border-(--checkbox-outline-hover-border)",
19
+ "data-[state=checked]:bg-(--checkbox-outline-checked-bg) data-[state=checked]:border-(--checkbox-outline-checked-border) data-[state=checked]:[&_svg]:text-(--checkbox-outline-checked-icon)"
20
+ ].join(" ")
21
+ }
22
+ },
23
+ defaultVariants: {
24
+ variant: "solid"
25
+ }
26
+ }
27
+ );
28
+ function CsCheckbox({
29
+ className,
30
+ variant,
31
+ children,
32
+ ...props
33
+ }) {
34
+ return /* @__PURE__ */ jsx(
35
+ CheckboxPrimitive.Root,
36
+ {
37
+ "data-slot": "checkbox",
38
+ className: cn(csCheckboxVariants({ variant }), className),
39
+ ...props,
40
+ children: /* @__PURE__ */ jsx(
41
+ CheckboxPrimitive.Indicator,
42
+ {
43
+ "data-slot": "checkbox-indicator",
44
+ className: "grid place-content-center text-current transition-none",
45
+ children: children ?? /* @__PURE__ */ jsx(CheckIcon, {})
46
+ }
47
+ )
48
+ }
49
+ );
50
+ }
51
+ export {
52
+ CsCheckbox,
53
+ csCheckboxVariants
54
+ };
55
+ //# sourceMappingURL=cs-checkbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cs-checkbox.js","sources":["../../../src/components/checkbox/cs-checkbox.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\"\nimport { CheckIcon } from \"lucide-react\"\n\nimport { cn } from \"../../lib/utils\"\nimport { cva, VariantProps } from \"class-variance-authority\"\n\n/**\n * CsCheckbox 스타일 시스템 (Design Token Reference)\n *\n * ## Figma Token → Props 매핑\n * | Figma 토큰 패턴 | Props |\n * |----------------|-------|\n * | `checkbox/solid/*` | `variant=\"solid\"` (기본) |\n * | `checkbox/outline/*` | `variant=\"outline\"` |\n *\n * ## State 매핑\n * | UI 상태 | Token state |\n * |---------|-------------|\n * | 기본 | default |\n * | hover: | hover |\n * | 체크됨 (data-[state=checked]) | checked |\n *\n * ## CSS Variables\n * ```css\n * --checkbox-common-scale | radius | icon-size | opacity\n * --checkbox-{variant}-{state}-bg | icon | border (outline only)\n * ```\n */\nconst csCheckboxVariants = cva(\n \"peer focus-visible:ring-0 size-(--checkbox-common-scale) shrink-0 transition-colors outline-none disabled:cursor-not-allowed \" +\n \"rounded-(--checkbox-common-radius) disabled:opacity-(--checkbox-common-opacity) [&_svg]:size-(--checkbox-common-icon-size)\",\n {\n variants: {\n variant: {\n solid: [\n \"bg-(--checkbox-solid-default-bg) hover:bg-(--checkbox-solid-hover-bg)\",\n \"data-[state=checked]:bg-(--checkbox-solid-checked-bg) data-[state=checked]:[&_svg]:text-(--checkbox-solid-checked-icon)\",\n ].join(' '),\n outline: [\n \"bg-(--checkbox-outline-default-bg) border-(length:--checkbox-outline-border-width) border-(--checkbox-outline-default-border)\",\n \"hover:bg-(--checkbox-outline-hover-bg) hover:border-(--checkbox-outline-hover-border)\",\n \"data-[state=checked]:bg-(--checkbox-outline-checked-bg) data-[state=checked]:border-(--checkbox-outline-checked-border) data-[state=checked]:[&_svg]:text-(--checkbox-outline-checked-icon)\",\n ].join(' '),\n },\n },\n defaultVariants: {\n variant: \"solid\",\n },\n }\n)\n\n/**\n * CsCheckbox Props\n */\ntype CsCheckboxProps = React.ComponentProps<typeof CheckboxPrimitive.Root> & VariantProps<typeof csCheckboxVariants> & {\n /**\n * 체크박스 스타일\n * - `solid`: 채워진 배경 (기본) - 일반 폼\n * - `outline`: 테두리 스타일 - 강조가 필요한 경우\n * @default 'solid'\n */\n variant?: 'solid' | 'outline'\n /**\n * 커스텀 체크 아이콘\n * 기본값: CheckIcon\n * indeterminate 상태 등에 Minus 아이콘 사용 가능\n */\n children?: React.ReactNode\n}\n\n/**\n * CS Design System 체크박스 컴포넌트\n *\n * 체크/언체크 상태를 표시하고 토글하는 컴포넌트.\n * 다중 선택, 약관 동의, 옵션 활성화 등에 사용됩니다.\n * Radix UI 기반으로 기본 CheckIcon 사용, children으로 커스텀 아이콘 가능합니다.\n *\n * ## 사용 시나리오\n * - 약관 동의: 이용약관, 개인정보처리방침 등 동의 체크\n * - 다중 선택: 여러 항목을 독립적으로 선택 (필터, 설정)\n * - 옵션 활성화: 기능 켜기/끄기 (알림 수신, 자동 로그인)\n * - 일괄 선택: 전체 선택 체크박스 (indeterminate 상태 활용)\n * - 폼 입력: 관심사, 선호 카테고리 등 여러 항목 선택\n *\n * ## 유사 컴포넌트와의 차이\n * - **CsSwitch**: 즉시 적용되는 설정 토글 (UI에서 바로 반영)\n * - Checkbox는 폼 제출 전까지 임시 상태, Switch는 토글 즉시 반영\n *\n * @example 기본 (solid)\n * ```tsx\n * <CsCheckbox checked={checked} onCheckedChange={setChecked} />\n * ```\n *\n * @example outline 스타일\n * ```tsx\n * <CsCheckbox variant=\"outline\" checked={checked} onCheckedChange={setChecked} />\n * ```\n *\n * @example 라벨과 함께\n * ```tsx\n * <CsLabel className=\"flex items-center gap-2\">\n * <CsCheckbox checked={agreed} onCheckedChange={setAgreed} />\n * 이용약관에 동의합니다\n * </CsLabel>\n * ```\n *\n * @example 커스텀 아이콘 (indeterminate 상태)\n * ```tsx\n * <CsCheckbox checked=\"indeterminate\">\n * <Minus />\n * </CsCheckbox>\n * ```\n *\n * @see {@link https://www.radix-ui.com/primitives/docs/components/checkbox | Radix Checkbox}\n */\nfunction CsCheckbox({\n className,\n variant,\n children,\n ...props\n}: CsCheckboxProps) {\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n className={cn(csCheckboxVariants({ variant }), className)}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"grid place-content-center text-current transition-none\"\n >\n {children ?? <CheckIcon />}\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n}\n\nexport { CsCheckbox, csCheckboxVariants, type CsCheckboxProps }\n"],"names":[],"mappings":";;;;;;AA+B2B,MACzB,qBAAA;AAAA,EAEA;AAAA,EAAA;AAAA,IACY,UACR;AAAA,MAAS,SACA;AAAA,QAAA,OACL;AAAA,UACA;AAAA,UACA;AAAA,QACF,OAAA,GAAS;AAAA,QAAA,SACP;AAAA,UACA;AAAA,UACA;AAAA,UACC;AAAA,QAAQ,EAAA,KAAA,GAAA;AAAA,MAEf;AAAA,IACA;AAAA,IAAiB,iBACN;AAAA,MAAA,SAAA;AAAA,IACX;AAAA,EAEJ;AAkEA;AAAoB,SAClB,WAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACF,GAAoB;AAClB;AACE,SAAmB;AAAA,IAAlB,kBAAA;AAAA,IAAA;AAAA,MAEC,aAAW;AAAA,MACV,WAAG,GAAA,mBAAA,EAAA,QAAA,CAAA,GAAA,SAAA;AAAA,MAEJ,GAAA;AAAA,MAAA,UAAmB;AAAA,QAAlB,kBAAA;AAAA,QAAA;AAAA,UAEC,aAAU;AAAA,UAET,WAAA;AAAA,UAAuB,UAAA,YAAA,oBAAA,WAAA,CAAA,CAAA;AAAA,QAAA;AAAA,MAC1B;AAAA,IACF;AAAA,EAEJ;;"}
@@ -0,0 +1,39 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { cva } from "class-variance-authority";
4
+ import { cn } from "../../lib/utils.js";
5
+ import { CsScrollArea } from "../scroll-area/cs-scroll-area.js";
6
+ const csCodeBlockVariants = cva(
7
+ "text-(--code-block-solid-font)",
8
+ {
9
+ variants: {
10
+ variant: {
11
+ solid: "bg-(--code-block-solid-bg) rounded-(--code-block-solid-radius)",
12
+ outline: "bg-(--code-block-outline-bg) border-(--code-block-outline-border) border-(length:--code-block-outline-border-width) rounded-(--code-block-outline-radius) text-(--code-block-outline-font)"
13
+ }
14
+ },
15
+ defaultVariants: {
16
+ variant: "solid"
17
+ }
18
+ }
19
+ );
20
+ function CsCodeBlock({
21
+ className,
22
+ variant = "solid",
23
+ ...props
24
+ }) {
25
+ const paddingClass = variant === "outline" ? "px-(--code-block-outline-padding-x) py-(--code-block-outline-padding-y)" : "px-(--code-block-solid-padding-x) py-(--code-block-solid-padding-y)";
26
+ return /* @__PURE__ */ jsx(CsScrollArea, { className: cn(csCodeBlockVariants({ variant }), className), children: /* @__PURE__ */ jsx(
27
+ "pre",
28
+ {
29
+ "data-slot": "code-block",
30
+ className: cn("h-full max-h-48 typo-productive-code-sm whitespace-pre-wrap", paddingClass),
31
+ ...props
32
+ }
33
+ ) });
34
+ }
35
+ export {
36
+ CsCodeBlock,
37
+ csCodeBlockVariants
38
+ };
39
+ //# sourceMappingURL=cs-code-block.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cs-code-block.js","sources":["../../../src/components/code-block/cs-code-block.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../lib/utils\"\nimport { CsScrollArea } from \"../scroll-area\"\n\n/**\n * CsCodeBlock 스타일 시스템 (Design Token Reference)\n *\n * ## Figma Token → Props 매핑\n * | Figma 토큰 패턴 | Props |\n * |----------------|-------|\n * | `code-block/solid/*` | `variant=\"solid\"` (default) |\n * | `code-block/outline/*` | `variant=\"outline\"` |\n *\n * ## CSS Variables\n * ```css\n * --code-block-solid-bg | font | radius | padding-x | padding-y\n * --code-block-outline-bg | font | border | border-width | radius | padding-x | padding-y\n * ```\n */\nconst csCodeBlockVariants = cva(\n \"text-(--code-block-solid-font)\",\n {\n variants: {\n variant: {\n solid: \"bg-(--code-block-solid-bg) rounded-(--code-block-solid-radius)\",\n outline: \"bg-(--code-block-outline-bg) border-(--code-block-outline-border) border-(length:--code-block-outline-border-width) rounded-(--code-block-outline-radius) text-(--code-block-outline-font)\",\n },\n },\n defaultVariants: {\n variant: \"solid\",\n },\n }\n)\n\n/**\n * CsCodeBlock Props\n */\ntype CsCodeBlockProps = React.ComponentProps<\"pre\"> & VariantProps<typeof csCodeBlockVariants> & {\n /**\n * 코드 블록 스타일\n * - `solid`: 채워진 배경 (기본) - 일반 코드 표시\n * - `outline`: 테두리 스타일 - 강조가 필요한 코드\n * @default 'solid'\n */\n variant?: 'solid' | 'outline'\n}\n\n/**\n * CS Design System 코드 블록 컴포넌트\n *\n * 코드 스니펫, 로그, 설정 파일 등을 표시하는 pre 기반 컴포넌트.\n * 자동 스크롤 영역이 내장되어 있으며, monospace 폰트가 적용됩니다.\n * typo-productive-code-sm 타이포그래피로 읽기 편한 코드 표시를 제공합니다.\n *\n * ## 사용 시나리오\n * - API 예제: `variant=\"solid\"` - 요청/응답 JSON, curl 명령어\n * - 에러 로그: `variant=\"solid\"` - 스택 트레이스, 에러 메시지\n * - 설정 파일: `variant=\"outline\"` - YAML, JSON, 환경 변수\n * - 코드 스니펫: 함수 예제, 스크립트 샘플\n * - 터미널 출력: 명령어 실행 결과, 빌드 로그\n * - 여러 줄 코드: 자동 스크롤로 긴 코드 표시\n *\n * ## 유사 컴포넌트와의 차이\n * - **CsCodeHighlighter**: 구문 강조 필요 시 (highlight.js 기반)\n * - CsCodeBlock은 단순 코드 표시 (구문 강조 없음)\n *\n * @example 기본 (solid)\n * ```tsx\n * <CsCodeBlock>\n * {`const hello = \"world\";`}\n * </CsCodeBlock>\n * ```\n *\n * @example outline 스타일\n * ```tsx\n * <CsCodeBlock variant=\"outline\">\n * {codeString}\n * </CsCodeBlock>\n * ```\n *\n * @example 여러 줄 코드\n * ```tsx\n * <CsCodeBlock>\n * {`function greet(name) {\n * return \"Hello, \" + name;\n * }`}\n * </CsCodeBlock>\n * ```\n *\n * @see CsCodeHighlighter - 구문 강조가 필요한 코드 표시 시\n */\nfunction CsCodeBlock({\n className,\n variant = 'solid',\n ...props\n}: CsCodeBlockProps) {\n const paddingClass = variant === 'outline'\n ? \"px-(--code-block-outline-padding-x) py-(--code-block-outline-padding-y)\"\n : \"px-(--code-block-solid-padding-x) py-(--code-block-solid-padding-y)\"\n\n return (\n <CsScrollArea className={cn(csCodeBlockVariants({ variant }), className)}>\n <pre\n data-slot=\"code-block\"\n className={cn(\"h-full max-h-48 typo-productive-code-sm whitespace-pre-wrap\", paddingClass)}\n {...props}\n />\n </CsScrollArea>\n )\n}\n\nexport { CsCodeBlock, csCodeBlockVariants, type CsCodeBlockProps }\n"],"names":[],"mappings":";;;;;AAuB4B,MAC1B,sBAAA;AAAA,EACA;AAAA,EAAA;AAAA,IACY,UACR;AAAA,MAAS,SACA;AAAA,QACP,OAAA;AAAA,QAAS,SAAA;AAAA,MAEb;AAAA,IACA;AAAA,IAAiB,iBACN;AAAA,MAAA,SAAA;AAAA,IACX;AAAA,EAEJ;AA2DA;AAAqB,SACnB,YAAA;AAAA,EACA;AAAA,EACA,UAAG;AAAA,EACL,GAAqB;AACnB,GAAA;AAIA,QAAA,eAAA,YACG,YAAa,4EACZ;AAAA,SAAC,oBAAA,cAAA,EAAA,WAAA,GAAA,oBAAA,EAAA,QAAA,CAAA,GAAA,SAAA,GAAA,UAAA;AAAA,IAAA;AAAA,IAAA;AAAA,MAEC,aAAW;AAAA,MACV,WAAG,GAAA,+DAAA,YAAA;AAAA,MAAA,GAAA;AAAA;EAIZ,EAAA,CAAA;;"}
@@ -0,0 +1,59 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useMemo } from "react";
4
+ import hljs from "highlight.js";
5
+ import { cva } from "class-variance-authority";
6
+ import { cn } from "../../lib/utils.js";
7
+ import "highlight.js/styles/atom-one-dark.css";
8
+ import { CsScrollArea } from "../scroll-area/cs-scroll-area.js";
9
+ const csCodeHighlighterVariants = cva(
10
+ "typo-productive-code-sm whitespace-pre-wrap text-(--code-block-solid-font)",
11
+ {
12
+ variants: {
13
+ variant: {
14
+ solid: "bg-(--code-block-solid-bg) rounded-(--code-block-solid-radius) px-(--code-block-solid-padding-x) py-(--code-block-solid-padding-y)",
15
+ outline: "bg-(--code-block-outline-bg) border-(--code-block-outline-border) border-(length:--code-block-outline-border-width) rounded-(--code-block-outline-radius) text-(--code-block-outline-font) px-(--code-block-outline-padding-x) py-(--code-block-outline-padding-y)"
16
+ }
17
+ },
18
+ defaultVariants: {
19
+ variant: "solid"
20
+ }
21
+ }
22
+ );
23
+ function CsCodeHighlighter({
24
+ children,
25
+ language,
26
+ variant = "solid",
27
+ className
28
+ }) {
29
+ const highlightedCode = useMemo(() => {
30
+ if (!children) return "";
31
+ try {
32
+ if (language) {
33
+ return hljs.highlight(children, { language, ignoreIllegals: true }).value;
34
+ }
35
+ return hljs.highlightAuto(children).value;
36
+ } catch {
37
+ return children;
38
+ }
39
+ }, [children, language]);
40
+ return /* @__PURE__ */ jsx(CsScrollArea, { children: /* @__PURE__ */ jsx(
41
+ "pre",
42
+ {
43
+ "data-slot": "code-highlighter",
44
+ className: cn(csCodeHighlighterVariants({ variant }), className),
45
+ children: /* @__PURE__ */ jsx(
46
+ "code",
47
+ {
48
+ className: "hljs",
49
+ style: { backgroundColor: "transparent" },
50
+ dangerouslySetInnerHTML: { __html: highlightedCode }
51
+ }
52
+ )
53
+ }
54
+ ) });
55
+ }
56
+ export {
57
+ CsCodeHighlighter
58
+ };
59
+ //# sourceMappingURL=cs-code-highlighter.js.map