@hua-labs/ui 1.0.0 → 1.1.0-alpha.0.1

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 (348) hide show
  1. package/README.md +891 -213
  2. package/dist/ComponentLayout-BxCenSAm.d.mts +73 -0
  3. package/dist/advanced/dashboard.d.ts +7 -0
  4. package/dist/advanced/dashboard.d.ts.map +1 -0
  5. package/dist/advanced/motion.d.ts +2 -0
  6. package/dist/advanced/motion.d.ts.map +1 -0
  7. package/dist/advanced-dashboard.d.mts +4 -0
  8. package/dist/advanced-dashboard.js +2 -0
  9. package/dist/advanced-dashboard.js.map +1 -0
  10. package/dist/advanced-dashboard.mjs +2 -0
  11. package/dist/advanced-dashboard.mjs.map +1 -0
  12. package/dist/advanced-motion.d.mts +93 -0
  13. package/dist/advanced-motion.js +2 -0
  14. package/dist/advanced-motion.js.map +1 -0
  15. package/dist/advanced-motion.mjs +2 -0
  16. package/dist/advanced-motion.mjs.map +1 -0
  17. package/dist/advanced.d.mts +734 -0
  18. package/dist/advanced.d.ts +17 -0
  19. package/dist/advanced.d.ts.map +1 -0
  20. package/dist/advanced.js +2 -0
  21. package/dist/advanced.js.map +1 -0
  22. package/dist/advanced.mjs +2 -0
  23. package/dist/advanced.mjs.map +1 -0
  24. package/dist/chunk-6NXF6ATP.mjs +2 -0
  25. package/dist/chunk-6NXF6ATP.mjs.map +1 -0
  26. package/dist/chunk-ACEKLG37.mjs +2 -0
  27. package/dist/chunk-ACEKLG37.mjs.map +1 -0
  28. package/dist/chunk-DMYT7RZ4.mjs +2 -0
  29. package/dist/chunk-DMYT7RZ4.mjs.map +1 -0
  30. package/dist/chunk-KHEJZ3U4.mjs +2 -0
  31. package/dist/chunk-KHEJZ3U4.mjs.map +1 -0
  32. package/dist/chunk-QXBMXCML.mjs +2 -0
  33. package/dist/chunk-QXBMXCML.mjs.map +1 -0
  34. package/dist/chunk-SGCVGEDR.mjs +2 -0
  35. package/dist/chunk-SGCVGEDR.mjs.map +1 -0
  36. package/dist/chunk-UUHAXGMO.mjs +2 -0
  37. package/dist/chunk-UUHAXGMO.mjs.map +1 -0
  38. package/dist/chunk-VPOFRDYL.mjs +2 -0
  39. package/dist/chunk-VPOFRDYL.mjs.map +1 -0
  40. package/dist/chunk-YY6ZBUVJ.mjs +2 -0
  41. package/dist/chunk-YY6ZBUVJ.mjs.map +1 -0
  42. package/dist/chunk-ZQAAB3P4.mjs +2 -0
  43. package/dist/chunk-ZQAAB3P4.mjs.map +1 -0
  44. package/dist/components/Accordion.d.ts +109 -1
  45. package/dist/components/Accordion.d.ts.map +1 -1
  46. package/dist/components/Action.d.ts +68 -0
  47. package/dist/components/Action.d.ts.map +1 -0
  48. package/dist/components/ActionToolbar.d.ts +65 -0
  49. package/dist/components/ActionToolbar.d.ts.map +1 -0
  50. package/dist/components/Alert.d.ts +49 -0
  51. package/dist/components/Alert.d.ts.map +1 -1
  52. package/dist/components/Autocomplete.d.ts +88 -0
  53. package/dist/components/Autocomplete.d.ts.map +1 -0
  54. package/dist/components/Avatar.d.ts +71 -1
  55. package/dist/components/Avatar.d.ts.map +1 -1
  56. package/dist/components/Badge.d.ts +32 -2
  57. package/dist/components/Badge.d.ts.map +1 -1
  58. package/dist/components/Bookmark.d.ts +49 -0
  59. package/dist/components/Bookmark.d.ts.map +1 -0
  60. package/dist/components/BottomSheet.d.ts +91 -1
  61. package/dist/components/BottomSheet.d.ts.map +1 -1
  62. package/dist/components/Breadcrumb.d.ts +73 -14
  63. package/dist/components/Breadcrumb.d.ts.map +1 -1
  64. package/dist/components/Button.d.ts +82 -7
  65. package/dist/components/Button.d.ts.map +1 -1
  66. package/dist/components/Card.d.ts +122 -5
  67. package/dist/components/Card.d.ts.map +1 -1
  68. package/dist/components/ChatMessage.d.ts +67 -1
  69. package/dist/components/ChatMessage.d.ts.map +1 -1
  70. package/dist/components/Checkbox.d.ts +48 -2
  71. package/dist/components/Checkbox.d.ts.map +1 -1
  72. package/dist/components/Command.d.ts +82 -1
  73. package/dist/components/Command.d.ts.map +1 -1
  74. package/dist/components/ComponentLayout.d.ts +72 -0
  75. package/dist/components/ComponentLayout.d.ts.map +1 -0
  76. package/dist/components/ConfirmModal.d.ts +66 -1
  77. package/dist/components/ConfirmModal.d.ts.map +1 -1
  78. package/dist/components/Container.d.ts +39 -0
  79. package/dist/components/Container.d.ts.map +1 -1
  80. package/dist/components/ContextMenu.d.ts +51 -1
  81. package/dist/components/ContextMenu.d.ts.map +1 -1
  82. package/dist/components/DatePicker.d.ts +62 -0
  83. package/dist/components/DatePicker.d.ts.map +1 -0
  84. package/dist/components/Divider.d.ts +13 -3
  85. package/dist/components/Divider.d.ts.map +1 -1
  86. package/dist/components/Drawer.d.ts +103 -1
  87. package/dist/components/Drawer.d.ts.map +1 -1
  88. package/dist/components/Dropdown.d.ts +51 -1
  89. package/dist/components/Dropdown.d.ts.map +1 -1
  90. package/dist/components/EmotionAnalysis.d.ts +59 -1
  91. package/dist/components/EmotionAnalysis.d.ts.map +1 -1
  92. package/dist/components/EmotionButton.d.ts +35 -1
  93. package/dist/components/EmotionButton.d.ts.map +1 -1
  94. package/dist/components/EmotionMeter.d.ts +38 -2
  95. package/dist/components/EmotionMeter.d.ts.map +1 -1
  96. package/dist/components/EmotionSelector.d.ts +51 -1
  97. package/dist/components/EmotionSelector.d.ts.map +1 -1
  98. package/dist/components/FeatureCard.d.ts +61 -0
  99. package/dist/components/FeatureCard.d.ts.map +1 -0
  100. package/dist/components/Form.d.ts +114 -0
  101. package/dist/components/Form.d.ts.map +1 -0
  102. package/dist/components/Grid.d.ts +42 -1
  103. package/dist/components/Grid.d.ts.map +1 -1
  104. package/dist/components/HeroSection.d.ts +77 -0
  105. package/dist/components/HeroSection.d.ts.map +1 -0
  106. package/dist/components/Icon/Icon.d.ts +159 -0
  107. package/dist/components/Icon/Icon.d.ts.map +1 -0
  108. package/dist/components/Icon/IconProvider.d.ts +94 -0
  109. package/dist/components/Icon/IconProvider.d.ts.map +1 -0
  110. package/dist/components/Icon/icon-store.d.ts +21 -0
  111. package/dist/components/Icon/icon-store.d.ts.map +1 -0
  112. package/dist/components/Icon/index.d.ts +10 -0
  113. package/dist/components/Icon/index.d.ts.map +1 -0
  114. package/dist/components/InfoCard.d.ts +48 -0
  115. package/dist/components/InfoCard.d.ts.map +1 -0
  116. package/dist/components/Input.d.ts +40 -8
  117. package/dist/components/Input.d.ts.map +1 -1
  118. package/dist/components/Label.d.ts +50 -0
  119. package/dist/components/Label.d.ts.map +1 -0
  120. package/dist/components/LanguageToggle.d.ts +41 -1
  121. package/dist/components/LanguageToggle.d.ts.map +1 -1
  122. package/dist/components/Link.d.ts +52 -0
  123. package/dist/components/Link.d.ts.map +1 -0
  124. package/dist/components/LoadingSpinner.d.ts +44 -5
  125. package/dist/components/LoadingSpinner.d.ts.map +1 -1
  126. package/dist/components/Menu.d.ts +92 -1
  127. package/dist/components/Menu.d.ts.map +1 -1
  128. package/dist/components/Modal.d.ts +67 -5
  129. package/dist/components/Modal.d.ts.map +1 -1
  130. package/dist/components/Navigation.d.ts +72 -0
  131. package/dist/components/Navigation.d.ts.map +1 -0
  132. package/dist/components/PageNavigation.d.ts +48 -0
  133. package/dist/components/PageNavigation.d.ts.map +1 -0
  134. package/dist/components/PageTransition.d.ts +44 -1
  135. package/dist/components/PageTransition.d.ts.map +1 -1
  136. package/dist/components/Pagination.d.ts +52 -1
  137. package/dist/components/Pagination.d.ts.map +1 -1
  138. package/dist/components/Panel.d.ts +99 -0
  139. package/dist/components/Panel.d.ts.map +1 -0
  140. package/dist/components/Popover.d.ts +46 -1
  141. package/dist/components/Popover.d.ts.map +1 -1
  142. package/dist/components/Progress.d.ts +52 -3
  143. package/dist/components/Progress.d.ts.map +1 -1
  144. package/dist/components/Radio.d.ts +44 -2
  145. package/dist/components/Radio.d.ts.map +1 -1
  146. package/dist/components/ScrollArea.d.ts +53 -1
  147. package/dist/components/ScrollArea.d.ts.map +1 -1
  148. package/dist/components/ScrollIndicator.d.ts +43 -1
  149. package/dist/components/ScrollIndicator.d.ts.map +1 -1
  150. package/dist/components/ScrollProgress.d.ts +37 -0
  151. package/dist/components/ScrollProgress.d.ts.map +1 -1
  152. package/dist/components/ScrollToTop.d.ts +48 -11
  153. package/dist/components/ScrollToTop.d.ts.map +1 -1
  154. package/dist/components/SectionHeader.d.ts +42 -0
  155. package/dist/components/SectionHeader.d.ts.map +1 -0
  156. package/dist/components/Select.d.ts +59 -2
  157. package/dist/components/Select.d.ts.map +1 -1
  158. package/dist/components/Skeleton.d.ts +44 -1
  159. package/dist/components/Skeleton.d.ts.map +1 -1
  160. package/dist/components/Slider.d.ts +75 -0
  161. package/dist/components/Slider.d.ts.map +1 -0
  162. package/dist/components/Stack.d.ts +42 -1
  163. package/dist/components/Stack.d.ts.map +1 -1
  164. package/dist/components/StatsPanel.d.ts +72 -0
  165. package/dist/components/StatsPanel.d.ts.map +1 -0
  166. package/dist/components/Switch.d.ts +48 -2
  167. package/dist/components/Switch.d.ts.map +1 -1
  168. package/dist/components/Table.d.ts +206 -0
  169. package/dist/components/Table.d.ts.map +1 -0
  170. package/dist/components/Tabs.d.ts +123 -10
  171. package/dist/components/Tabs.d.ts.map +1 -1
  172. package/dist/components/Textarea.d.ts +48 -2
  173. package/dist/components/Textarea.d.ts.map +1 -1
  174. package/dist/components/ThemeProvider.d.ts +67 -2
  175. package/dist/components/ThemeProvider.d.ts.map +1 -1
  176. package/dist/components/ThemeToggle.d.ts +44 -0
  177. package/dist/components/ThemeToggle.d.ts.map +1 -1
  178. package/dist/components/Toast.d.ts +75 -1
  179. package/dist/components/Toast.d.ts.map +1 -1
  180. package/dist/components/Toggle.d.ts +62 -0
  181. package/dist/components/Toggle.d.ts.map +1 -0
  182. package/dist/components/Tooltip.d.ts +48 -1
  183. package/dist/components/Tooltip.d.ts.map +1 -1
  184. package/dist/components/Upload.d.ts +87 -0
  185. package/dist/components/Upload.d.ts.map +1 -0
  186. package/dist/components/advanced/AdvancedPageTransition.d.ts +25 -0
  187. package/dist/components/advanced/AdvancedPageTransition.d.ts.map +1 -0
  188. package/dist/components/advanced/index.d.ts +4 -0
  189. package/dist/components/advanced/index.d.ts.map +1 -0
  190. package/dist/components/advanced/usePageTransition.d.ts +33 -0
  191. package/dist/components/advanced/usePageTransition.d.ts.map +1 -0
  192. package/dist/components/advanced/usePageTransitionManager.d.ts +44 -0
  193. package/dist/components/advanced/usePageTransitionManager.d.ts.map +1 -0
  194. package/dist/components/dashboard/ActivityFeed.d.ts +87 -0
  195. package/dist/components/dashboard/ActivityFeed.d.ts.map +1 -0
  196. package/dist/components/dashboard/BarChart.d.ts +82 -0
  197. package/dist/components/dashboard/BarChart.d.ts.map +1 -0
  198. package/dist/components/dashboard/DashboardGrid.d.ts +44 -0
  199. package/dist/components/dashboard/DashboardGrid.d.ts.map +1 -0
  200. package/dist/components/dashboard/DashboardSidebar.d.ts +105 -0
  201. package/dist/components/dashboard/DashboardSidebar.d.ts.map +1 -0
  202. package/dist/components/dashboard/DashboardToolbar.d.ts +120 -0
  203. package/dist/components/dashboard/DashboardToolbar.d.ts.map +1 -0
  204. package/dist/components/dashboard/EmptyState.d.ts +61 -0
  205. package/dist/components/dashboard/EmptyState.d.ts.map +1 -0
  206. package/dist/components/dashboard/MembershipBadge.d.ts +45 -0
  207. package/dist/components/dashboard/MembershipBadge.d.ts.map +1 -0
  208. package/dist/components/dashboard/MerchantList.d.ts +98 -0
  209. package/dist/components/dashboard/MerchantList.d.ts.map +1 -0
  210. package/dist/components/dashboard/MetricCard.d.ts +75 -0
  211. package/dist/components/dashboard/MetricCard.d.ts.map +1 -0
  212. package/dist/components/dashboard/MiniBarChart.d.ts +60 -0
  213. package/dist/components/dashboard/MiniBarChart.d.ts.map +1 -0
  214. package/dist/components/dashboard/NotificationCard.d.ts +89 -0
  215. package/dist/components/dashboard/NotificationCard.d.ts.map +1 -0
  216. package/dist/components/dashboard/ProfileCard.d.ts +82 -0
  217. package/dist/components/dashboard/ProfileCard.d.ts.map +1 -0
  218. package/dist/components/dashboard/ProgressCard.d.ts +71 -0
  219. package/dist/components/dashboard/ProgressCard.d.ts.map +1 -0
  220. package/dist/components/dashboard/QuickActionCard.d.ts +63 -0
  221. package/dist/components/dashboard/QuickActionCard.d.ts.map +1 -0
  222. package/dist/components/dashboard/RoutingBreakdownCard.d.ts +88 -0
  223. package/dist/components/dashboard/RoutingBreakdownCard.d.ts.map +1 -0
  224. package/dist/components/dashboard/SettlementTimeline.d.ts +90 -0
  225. package/dist/components/dashboard/SettlementTimeline.d.ts.map +1 -0
  226. package/dist/components/dashboard/StatCard.d.ts +70 -0
  227. package/dist/components/dashboard/StatCard.d.ts.map +1 -0
  228. package/dist/components/dashboard/SummaryCard.d.ts +73 -0
  229. package/dist/components/dashboard/SummaryCard.d.ts.map +1 -0
  230. package/dist/components/dashboard/TransactionDetailDrawer.d.ts +183 -0
  231. package/dist/components/dashboard/TransactionDetailDrawer.d.ts.map +1 -0
  232. package/dist/components/dashboard/TransactionsTable.d.ts +137 -0
  233. package/dist/components/dashboard/TransactionsTable.d.ts.map +1 -0
  234. package/dist/components/dashboard/TrendChart.d.ts +75 -0
  235. package/dist/components/dashboard/TrendChart.d.ts.map +1 -0
  236. package/dist/components/dashboard/index.d.ts +41 -0
  237. package/dist/components/dashboard/index.d.ts.map +1 -0
  238. package/dist/components/scrollbar/scrollbar.d.ts +12 -0
  239. package/dist/components/scrollbar/scrollbar.d.ts.map +1 -0
  240. package/dist/dashboard-QMssHf5j.d.mts +1801 -0
  241. package/dist/feedback.d.mts +103 -0
  242. package/dist/feedback.d.ts +21 -0
  243. package/dist/feedback.d.ts.map +1 -0
  244. package/dist/feedback.js +2 -0
  245. package/dist/feedback.js.map +1 -0
  246. package/dist/feedback.mjs +2 -0
  247. package/dist/feedback.mjs.map +1 -0
  248. package/dist/form.d.mts +803 -0
  249. package/dist/form.d.ts +42 -0
  250. package/dist/form.d.ts.map +1 -0
  251. package/dist/form.js +2 -0
  252. package/dist/form.js.map +1 -0
  253. package/dist/form.mjs +2 -0
  254. package/dist/form.mjs.map +1 -0
  255. package/dist/hooks/useScrollToggle.d.ts +12 -0
  256. package/dist/hooks/useScrollToggle.d.ts.map +1 -0
  257. package/dist/icons-DoSGIez_.d.mts +135 -0
  258. package/dist/index.d.mts +3770 -0
  259. package/dist/index.d.ts +76 -38
  260. package/dist/index.d.ts.map +1 -1
  261. package/dist/index.js +37 -49
  262. package/dist/index.js.map +1 -0
  263. package/dist/index.mjs +37 -0
  264. package/dist/index.mjs.map +1 -0
  265. package/dist/lib/icon-aliases.d.ts +24 -0
  266. package/dist/lib/icon-aliases.d.ts.map +1 -0
  267. package/dist/lib/icon-names.d.ts +47 -0
  268. package/dist/lib/icon-names.d.ts.map +1 -0
  269. package/dist/lib/icon-providers.d.ts +560 -0
  270. package/dist/lib/icon-providers.d.ts.map +1 -0
  271. package/dist/lib/icons.d.ts +113 -24
  272. package/dist/lib/icons.d.ts.map +1 -1
  273. package/dist/lib/phosphor-icons.d.ts +6 -0
  274. package/dist/lib/phosphor-icons.d.ts.map +1 -0
  275. package/dist/lib/styles/colors.d.ts +131 -0
  276. package/dist/lib/styles/colors.d.ts.map +1 -0
  277. package/dist/lib/styles/index.d.ts +8 -0
  278. package/dist/lib/styles/index.d.ts.map +1 -0
  279. package/dist/lib/styles/utils.d.ts +87 -0
  280. package/dist/lib/styles/utils.d.ts.map +1 -0
  281. package/dist/lib/styles/variants.d.ts +79 -0
  282. package/dist/lib/styles/variants.d.ts.map +1 -0
  283. package/dist/lib/types/common.d.ts +80 -0
  284. package/dist/lib/types/common.d.ts.map +1 -0
  285. package/dist/lib/types/index.d.ts +6 -0
  286. package/dist/lib/types/index.d.ts.map +1 -0
  287. package/dist/lib/utils.d.ts +73 -1
  288. package/dist/lib/utils.d.ts.map +1 -1
  289. package/dist/navigation.d.mts +105 -0
  290. package/dist/navigation.d.ts +22 -0
  291. package/dist/navigation.d.ts.map +1 -0
  292. package/dist/navigation.js +2 -0
  293. package/dist/navigation.js.map +1 -0
  294. package/dist/navigation.mjs +2 -0
  295. package/dist/navigation.mjs.map +1 -0
  296. package/package.json +85 -19
  297. package/src/styles/toast.css +23 -0
  298. package/dist/components/Accordion.js +0 -84
  299. package/dist/components/Alert.js +0 -61
  300. package/dist/components/Avatar.js +0 -18
  301. package/dist/components/Badge.js +0 -15
  302. package/dist/components/BottomSheet.js +0 -96
  303. package/dist/components/Breadcrumb.js +0 -47
  304. package/dist/components/Button.js +0 -23
  305. package/dist/components/Card.js +0 -18
  306. package/dist/components/ChatMessage.js +0 -59
  307. package/dist/components/Checkbox.js +0 -30
  308. package/dist/components/Command.js +0 -119
  309. package/dist/components/ConfirmModal.js +0 -53
  310. package/dist/components/Container.js +0 -23
  311. package/dist/components/ContextMenu.js +0 -110
  312. package/dist/components/Divider.js +0 -39
  313. package/dist/components/Drawer.js +0 -79
  314. package/dist/components/Dropdown.js +0 -174
  315. package/dist/components/EmotionAnalysis.js +0 -40
  316. package/dist/components/EmotionButton.js +0 -16
  317. package/dist/components/EmotionMeter.js +0 -21
  318. package/dist/components/EmotionSelector.js +0 -46
  319. package/dist/components/Grid.js +0 -44
  320. package/dist/components/Icon.d.ts +0 -26
  321. package/dist/components/Icon.d.ts.map +0 -1
  322. package/dist/components/Icon.js +0 -48
  323. package/dist/components/Input.js +0 -25
  324. package/dist/components/LanguageToggle.js +0 -61
  325. package/dist/components/LoadingSpinner.js +0 -37
  326. package/dist/components/Menu.js +0 -122
  327. package/dist/components/Modal.js +0 -62
  328. package/dist/components/PageTransition.js +0 -39
  329. package/dist/components/Pagination.js +0 -87
  330. package/dist/components/Popover.js +0 -159
  331. package/dist/components/Progress.js +0 -51
  332. package/dist/components/Radio.js +0 -29
  333. package/dist/components/ScrollArea.js +0 -42
  334. package/dist/components/ScrollIndicator.js +0 -60
  335. package/dist/components/ScrollProgress.js +0 -39
  336. package/dist/components/ScrollToTop.js +0 -46
  337. package/dist/components/Select.js +0 -29
  338. package/dist/components/Skeleton.js +0 -71
  339. package/dist/components/Stack.js +0 -34
  340. package/dist/components/Switch.js +0 -29
  341. package/dist/components/Tabs.js +0 -117
  342. package/dist/components/Textarea.js +0 -31
  343. package/dist/components/ThemeProvider.js +0 -76
  344. package/dist/components/ThemeToggle.js +0 -49
  345. package/dist/components/Toast.js +0 -138
  346. package/dist/components/Tooltip.js +0 -102
  347. package/dist/lib/icons.js +0 -321
  348. package/dist/lib/utils.js +0 -5
@@ -1,119 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import * as React from "react";
4
- import { cn } from "../lib/utils";
5
- const Command = React.forwardRef(({ className, children, open: controlledOpen, onOpenChange, placeholder = "명령어를 검색하세요...", searchValue: controlledSearchValue, onSearchChange, disabled = false, ...props }, ref) => {
6
- const [internalOpen, setInternalOpen] = React.useState(false);
7
- const [internalSearchValue, setInternalSearchValue] = React.useState("");
8
- const [selectedIndex, setSelectedIndex] = React.useState(0);
9
- const commandRef = React.useRef(null);
10
- const inputRef = React.useRef(null);
11
- const listRef = React.useRef(null);
12
- const isControlled = controlledOpen !== undefined;
13
- const isOpen = isControlled ? controlledOpen : internalOpen;
14
- const searchValue = controlledSearchValue !== undefined ? controlledSearchValue : internalSearchValue;
15
- const handleOpenChange = (newOpen) => {
16
- if (disabled)
17
- return;
18
- if (!isControlled) {
19
- setInternalOpen(newOpen);
20
- }
21
- onOpenChange?.(newOpen);
22
- };
23
- const handleSearchChange = (value) => {
24
- if (!isControlled) {
25
- setInternalSearchValue(value);
26
- }
27
- onSearchChange?.(value);
28
- setSelectedIndex(0);
29
- };
30
- const handleKeyDown = (event) => {
31
- if (disabled)
32
- return;
33
- const items = listRef.current?.querySelectorAll('[data-command-item]');
34
- const itemCount = items?.length || 0;
35
- switch (event.key) {
36
- case 'ArrowDown':
37
- event.preventDefault();
38
- setSelectedIndex((prev) => (prev + 1) % itemCount);
39
- break;
40
- case 'ArrowUp':
41
- event.preventDefault();
42
- setSelectedIndex((prev) => (prev - 1 + itemCount) % itemCount);
43
- break;
44
- case 'Enter':
45
- event.preventDefault();
46
- const selectedItem = items?.[selectedIndex];
47
- selectedItem?.click();
48
- break;
49
- case 'Escape':
50
- event.preventDefault();
51
- handleOpenChange(false);
52
- break;
53
- }
54
- };
55
- React.useEffect(() => {
56
- if (isOpen) {
57
- inputRef.current?.focus();
58
- setSelectedIndex(0);
59
- }
60
- }, [isOpen]);
61
- React.useEffect(() => {
62
- const handleKeyDown = (event) => {
63
- if (event.key === 'k' && (event.metaKey || event.ctrlKey)) {
64
- event.preventDefault();
65
- handleOpenChange(!isOpen);
66
- }
67
- };
68
- document.addEventListener('keydown', handleKeyDown);
69
- return () => {
70
- document.removeEventListener('keydown', handleKeyDown);
71
- };
72
- }, [isOpen]);
73
- React.useEffect(() => {
74
- const selectedItem = listRef.current?.querySelector(`[data-command-item]:nth-child(${selectedIndex + 1})`);
75
- selectedItem?.scrollIntoView({ block: 'nearest' });
76
- }, [selectedIndex]);
77
- return (_jsx("div", { ref: ref, className: cn("relative", className), ...props, children: isOpen && (_jsx("div", { ref: commandRef, className: cn("fixed inset-0 z-50 bg-black/50 backdrop-blur-sm", // 50% 투명도
78
- "flex items-start justify-center pt-16" // 64px 상단 여백
79
- ), onClick: () => handleOpenChange(false), children: _jsxs("div", { className: cn("w-full max-w-2xl mx-4 bg-white dark:bg-gray-800 rounded-lg shadow-2xl", // 보더 대신 섀도우
80
- "border-0 overflow-hidden" // 보더 제거
81
- ), onClick: (e) => e.stopPropagation(), style: {
82
- boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)"
83
- }, children: [_jsxs("div", { className: "p-4 border-b border-gray-200 dark:border-gray-700", children: [" ", _jsx("input", { ref: inputRef, type: "text", placeholder: placeholder, value: searchValue, onChange: (e) => handleSearchChange(e.target.value), onKeyDown: handleKeyDown, className: cn("w-full bg-transparent text-lg font-medium outline-none", // 18px 텍스트
84
- "placeholder:text-gray-500 dark:placeholder:text-gray-400", "text-gray-900 dark:text-gray-100") })] }), _jsx("div", { ref: listRef, className: "max-h-96 overflow-y-auto py-2" // 384px 최대 높이, 8px 패딩
85
- , children: React.Children.map(children, (child, index) => {
86
- if (React.isValidElement(child)) {
87
- return React.cloneElement(child, {
88
- selected: index === selectedIndex,
89
- onSelect: () => {
90
- child.props?.onSelect?.();
91
- handleOpenChange(false);
92
- }
93
- });
94
- }
95
- return child;
96
- }) })] }) })) }));
97
- });
98
- Command.displayName = "Command";
99
- const CommandInput = React.forwardRef(({ className, ...props }, ref) => (_jsx("input", { ref: ref, className: cn("flex h-10 w-full rounded-md bg-transparent px-3 py-2 text-sm outline-none", // 40px 높이, 12px, 8px 패딩
100
- "placeholder:text-gray-500 dark:placeholder:text-gray-400", "disabled:cursor-not-allowed disabled:opacity-50", className), ...props })));
101
- CommandInput.displayName = "CommandInput";
102
- const CommandList = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn("max-h-96 overflow-y-auto py-2", className), ...props })));
103
- CommandList.displayName = "CommandList";
104
- const CommandItem = React.forwardRef(({ className, icon, selected = false, onSelect, children, ...props }, ref) => {
105
- return (_jsxs("button", { ref: ref, "data-command-item": true, className: cn("relative flex w-full items-center gap-3 rounded-sm px-4 py-3 text-sm", // 16px, 12px 패딩
106
- "text-gray-700 dark:text-gray-300", "hover:bg-gray-100 dark:hover:bg-gray-700", "focus:bg-gray-100 dark:focus:bg-gray-700", "focus:outline-none", selected && "bg-gray-100 dark:bg-gray-700", "transition-colors", className), onClick: onSelect, ...props, children: [icon && (_jsx("div", { className: "flex-shrink-0 w-4 h-4 text-gray-500 dark:text-gray-400", children: icon })), _jsx("span", { className: "flex-1 text-left", children: children })] }));
107
- });
108
- CommandItem.displayName = "CommandItem";
109
- const CommandGroup = React.forwardRef(({ className, heading, children, ...props }, ref) => (_jsxs("div", { ref: ref, className: cn("py-2", className), ...props, children: [" ", heading && (_jsxs("div", { className: "px-4 py-2 text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wide", children: [" ", heading] })), _jsxs("div", { className: "space-y-1", children: [" ", children] })] })));
110
- CommandGroup.displayName = "CommandGroup";
111
- const CommandSeparator = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn("h-px bg-gray-200 dark:bg-gray-700 my-2", className), ...props })));
112
- CommandSeparator.displayName = "CommandSeparator";
113
- const CommandEmpty = React.forwardRef(({ className, children = "결과가 없습니다.", ...props }, ref) => (_jsx("div", { ref: ref, className: cn("py-8 text-center text-sm text-gray-500 dark:text-gray-400", // 32px 패딩
114
- className), ...props, children: children })));
115
- CommandEmpty.displayName = "CommandEmpty";
116
- // 편의 컴포넌트들
117
- export const CommandDialog = React.forwardRef(({ className, ...props }, ref) => (_jsx(Command, { ref: ref, className: className, ...props })));
118
- CommandDialog.displayName = "CommandDialog";
119
- export { Command, CommandInput, CommandList, CommandItem, CommandGroup, CommandSeparator, CommandEmpty };
@@ -1,53 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import * as React from "react";
4
- import { cn } from "../lib/utils";
5
- import { Modal } from "./Modal";
6
- import { Button } from "./Button";
7
- const ConfirmModal = React.forwardRef(({ isOpen, onClose, onConfirm, title, message, warning, confirmText = "확인", cancelText = "취소", confirmButtonText, type = "danger", loading = false, disabled = false, showInput = false, inputValue = "", onInputChange, inputPlaceholder, inputLabel, requiredInputValue, showCancel = true, size = "md" }, ref) => {
8
- // 타입별 아이콘과 색상
9
- const typeConfig = {
10
- danger: {
11
- icon: (_jsx("svg", { className: "h-6 w-6 text-red-600 dark:text-red-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z" }) })),
12
- bgColor: "bg-red-100 dark:bg-red-900/20",
13
- buttonColor: "bg-red-600 hover:bg-red-700 focus:ring-red-500",
14
- textColor: "text-red-600 dark:text-red-400"
15
- },
16
- warning: {
17
- icon: (_jsx("svg", { className: "h-6 w-6 text-yellow-600 dark:text-yellow-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z" }) })),
18
- bgColor: "bg-yellow-100 dark:bg-yellow-900/20",
19
- buttonColor: "bg-yellow-600 hover:bg-yellow-700 focus:ring-yellow-500",
20
- textColor: "text-yellow-600 dark:text-yellow-400"
21
- },
22
- info: {
23
- icon: (_jsx("svg", { className: "h-6 w-6 text-blue-600 dark:text-blue-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) })),
24
- bgColor: "bg-blue-100 dark:bg-blue-900/20",
25
- buttonColor: "bg-blue-600 hover:bg-blue-700 focus:ring-blue-500",
26
- textColor: "text-blue-600 dark:text-blue-400"
27
- },
28
- success: {
29
- icon: (_jsx("svg", { className: "h-6 w-6 text-green-600 dark:text-green-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) })),
30
- bgColor: "bg-green-100 dark:bg-green-900/20",
31
- buttonColor: "bg-green-600 hover:bg-green-700 focus:ring-green-500",
32
- textColor: "text-green-600 dark:text-green-400"
33
- },
34
- error: {
35
- icon: (_jsx("svg", { className: "h-6 w-6 text-red-600 dark:text-red-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })),
36
- bgColor: "bg-red-100 dark:bg-red-900/20",
37
- buttonColor: "bg-red-600 hover:bg-red-700 focus:ring-red-500",
38
- textColor: "text-red-600 dark:text-red-400"
39
- }
40
- };
41
- const config = typeConfig[type];
42
- const isInputValid = !showInput || !requiredInputValue || inputValue === requiredInputValue;
43
- const isDisabled = disabled || loading || !isInputValid;
44
- return (_jsx(Modal, { ref: ref, isOpen: isOpen, onClose: onClose, showCloseButton: false, size: size, children: _jsxs("div", { className: "text-center", children: [_jsx("div", { className: cn("mx-auto flex items-center justify-center h-16 w-16 rounded-full mb-6", // 64px 아이콘, 24px 여백
45
- config.bgColor), children: config.icon }), _jsxs("h3", { className: "text-xl font-semibold text-gray-900 dark:text-white mb-4", children: [" ", title] }), _jsxs("div", { className: "mb-6", children: [" ", _jsx("p", { className: "text-sm text-gray-600 dark:text-gray-400", children: message }), warning && (_jsx("p", { className: cn("text-sm mt-3 font-medium", // 12px 여백
46
- config.textColor), children: warning }))] }), showInput && (_jsxs("div", { className: "mb-6", children: [" ", _jsxs("label", { htmlFor: "confirmInput", className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-3 text-left", children: [" ", inputLabel] }), _jsx("input", { type: "text", id: "confirmInput", value: inputValue, onChange: (e) => onInputChange?.(e.target.value), placeholder: inputPlaceholder, className: "w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-red-500 focus:border-transparent dark:bg-gray-700 dark:text-white transition-colors" // 16px, 12px 패딩
47
- })] })), _jsxs("div", { className: cn("flex gap-3", // 12px 간격
48
- showCancel ? "justify-center" : "justify-center"), children: [showCancel && (_jsx(Button, { variant: "outline", onClick: onClose, disabled: loading, className: "px-6 py-3" // 24px, 12px 패딩
49
- , children: cancelText })), _jsx(Button, { variant: "default", onClick: onConfirm, disabled: isDisabled, className: cn("px-6 py-3", // 24px, 12px 패딩
50
- config.buttonColor), children: loading ? (_jsxs("div", { className: "flex items-center", children: [_jsxs("svg", { className: "animate-spin -ml-1 mr-2 h-4 w-4 text-white", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })] }), "\uCC98\uB9AC \uC911..."] })) : (confirmButtonText || confirmText) })] })] }) }));
51
- });
52
- ConfirmModal.displayName = "ConfirmModal";
53
- export { ConfirmModal };
@@ -1,23 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- import React from "react";
4
- import { cn } from "../lib/utils";
5
- const Container = React.forwardRef(({ className, size = "lg", padding = "md", centered = true, fluid = false, ...props }, ref) => {
6
- const sizeClasses = {
7
- sm: "max-w-2xl", // 672px
8
- md: "max-w-4xl", // 896px
9
- lg: "max-w-6xl", // 1152px
10
- xl: "max-w-7xl", // 1280px
11
- full: "max-w-full"
12
- };
13
- const paddingClasses = {
14
- none: "",
15
- sm: "px-4 py-8", // 16px 좌우, 32px 상하
16
- md: "px-6 py-12", // 24px 좌우, 48px 상하
17
- lg: "px-8 py-16", // 32px 좌우, 64px 상하
18
- xl: "px-12 py-20" // 48px 좌우, 80px 상하
19
- };
20
- return (_jsx("div", { ref: ref, className: cn("w-full", !fluid && sizeClasses[size], paddingClasses[padding], centered && "mx-auto", className), ...props }));
21
- });
22
- Container.displayName = "Container";
23
- export { Container };
@@ -1,110 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import * as React from "react";
4
- import { cn } from "../lib/utils";
5
- const ContextMenu = React.forwardRef(({ className, children, open: controlledOpen, onOpenChange, trigger, placement = "bottom", align = "start", offset = 8, disabled = false, ...props }, ref) => {
6
- const [internalOpen, setInternalOpen] = React.useState(false);
7
- const [coords, setCoords] = React.useState({ x: 0, y: 0 });
8
- const triggerRef = React.useRef(null);
9
- const menuRef = React.useRef(null);
10
- const isControlled = controlledOpen !== undefined;
11
- const isOpen = isControlled ? controlledOpen : internalOpen;
12
- const handleOpenChange = (newOpen) => {
13
- if (disabled)
14
- return;
15
- if (!isControlled) {
16
- setInternalOpen(newOpen);
17
- }
18
- onOpenChange?.(newOpen);
19
- };
20
- const handleContextMenu = (event) => {
21
- event.preventDefault();
22
- if (disabled)
23
- return;
24
- const rect = event.currentTarget.getBoundingClientRect();
25
- const x = event.clientX;
26
- const y = event.clientY;
27
- setCoords({ x, y });
28
- handleOpenChange(true);
29
- };
30
- const updatePosition = React.useCallback(() => {
31
- if (!menuRef.current)
32
- return;
33
- const menuRect = menuRef.current.getBoundingClientRect();
34
- const viewportWidth = window.innerWidth;
35
- const viewportHeight = window.innerHeight;
36
- let x = coords.x;
37
- let y = coords.y;
38
- // 뷰포트 경계 확인 및 조정
39
- if (x + menuRect.width > viewportWidth - 8) {
40
- x = viewportWidth - menuRect.width - 8; // 8px 여백
41
- }
42
- if (y + menuRect.height > viewportHeight - 8) {
43
- y = viewportHeight - menuRect.height - 8; // 8px 여백
44
- }
45
- if (x < 8)
46
- x = 8; // 8px 여백
47
- if (y < 8)
48
- y = 8; // 8px 여백
49
- setCoords({ x, y });
50
- }, [coords.x, coords.y]);
51
- React.useEffect(() => {
52
- if (isOpen) {
53
- updatePosition();
54
- window.addEventListener('resize', updatePosition);
55
- window.addEventListener('scroll', updatePosition);
56
- return () => {
57
- window.removeEventListener('resize', updatePosition);
58
- window.removeEventListener('scroll', updatePosition);
59
- };
60
- }
61
- }, [isOpen, updatePosition]);
62
- React.useEffect(() => {
63
- const handleClickOutside = (event) => {
64
- if (triggerRef.current &&
65
- menuRef.current &&
66
- !triggerRef.current.contains(event.target) &&
67
- !menuRef.current.contains(event.target)) {
68
- handleOpenChange(false);
69
- }
70
- };
71
- if (isOpen) {
72
- document.addEventListener('mousedown', handleClickOutside);
73
- return () => {
74
- document.removeEventListener('mousedown', handleClickOutside);
75
- };
76
- }
77
- }, [isOpen]);
78
- return (_jsxs("div", { ref: ref, className: cn("relative", className), ...props, children: [trigger && (_jsx("div", { ref: triggerRef, onContextMenu: handleContextMenu, className: "inline-block", children: trigger })), isOpen && (_jsx("div", { ref: menuRef, className: cn("fixed z-50 bg-white dark:bg-gray-800 rounded-lg shadow-xl backdrop-blur-sm", // 보더 대신 섀도우 사용
79
- "min-w-[200px] py-2", // 16px 패딩
80
- "border-0" // 보더 제거
81
- ), style: {
82
- left: coords.x,
83
- top: coords.y,
84
- boxShadow: "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)"
85
- }, children: children }))] }));
86
- });
87
- ContextMenu.displayName = "ContextMenu";
88
- const ContextMenuItem = React.forwardRef(({ className, icon, variant = "default", children, disabled, ...props }, ref) => {
89
- const getVariantClasses = () => {
90
- switch (variant) {
91
- case "destructive":
92
- return "text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20";
93
- case "disabled":
94
- return "text-gray-400 dark:text-gray-500 cursor-not-allowed";
95
- default:
96
- return "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700";
97
- }
98
- };
99
- return (_jsxs("button", { ref: ref, className: cn("w-full flex items-center gap-3 px-4 py-3 text-sm font-medium transition-colors focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-700", // 16px, 12px 패딩
100
- getVariantClasses(), className), disabled: disabled || variant === "disabled", ...props, children: [icon && (_jsx("div", { className: "flex-shrink-0 w-4 h-4", children: icon })), _jsx("span", { className: "flex-1 text-left", children: children })] }));
101
- });
102
- ContextMenuItem.displayName = "ContextMenuItem";
103
- const ContextMenuSeparator = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn("h-px bg-gray-200 dark:bg-gray-700 my-2", className), ...props })));
104
- ContextMenuSeparator.displayName = "ContextMenuSeparator";
105
- const ContextMenuLabel = React.forwardRef(({ className, children, ...props }, ref) => (_jsx("div", { ref: ref, className: cn("px-4 py-2 text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wide", className), ...props, children: children })));
106
- ContextMenuLabel.displayName = "ContextMenuLabel";
107
- // 편의 컴포넌트들
108
- const ContextMenuGroup = React.forwardRef(({ className, children, ...props }, ref) => (_jsx("div", { ref: ref, className: cn("py-1", className), ...props, children: children })));
109
- ContextMenuGroup.displayName = "ContextMenuGroup";
110
- export { ContextMenu, ContextMenuItem, ContextMenuSeparator, ContextMenuLabel, ContextMenuGroup };
@@ -1,39 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx } from "react/jsx-runtime";
3
- import * as React from "react";
4
- import { cn } from "../lib/utils";
5
- const Divider = React.forwardRef(({ className, orientation = "horizontal", variant = "solid", size = "md", spacing = "md", color = "default", ...props }, ref) => {
6
- const orientationClasses = {
7
- horizontal: "w-full",
8
- vertical: "h-full w-px"
9
- };
10
- const sizeClasses = {
11
- sm: orientation === "horizontal" ? "h-px" : "w-px",
12
- md: orientation === "horizontal" ? "h-0.5" : "w-0.5", // 2px
13
- lg: orientation === "horizontal" ? "h-1" : "w-1" // 4px
14
- };
15
- const variantClasses = {
16
- solid: "",
17
- dashed: "border-dashed",
18
- dotted: "border-dotted",
19
- gradient: orientation === "horizontal"
20
- ? "bg-gradient-to-r from-transparent via-gray-300 to-transparent dark:via-gray-600"
21
- : "bg-gradient-to-b from-transparent via-gray-300 to-transparent dark:via-gray-600"
22
- };
23
- const colorClasses = {
24
- default: "bg-gray-200 dark:bg-gray-700",
25
- muted: "bg-gray-100 dark:bg-gray-800",
26
- primary: "bg-blue-200 dark:bg-blue-700",
27
- secondary: "bg-gray-300 dark:bg-gray-600"
28
- };
29
- const spacingClasses = {
30
- none: "",
31
- sm: orientation === "horizontal" ? "my-4" : "mx-4", // 16px
32
- md: orientation === "horizontal" ? "my-6" : "mx-6", // 24px
33
- lg: orientation === "horizontal" ? "my-8" : "mx-8", // 32px
34
- xl: orientation === "horizontal" ? "my-12" : "mx-12" // 48px
35
- };
36
- return (_jsx("div", { ref: ref, className: cn("flex-shrink-0", orientationClasses[orientation], sizeClasses[size], variant === "gradient" ? variantClasses[variant] : colorClasses[color], variant !== "gradient" && variantClasses[variant], spacingClasses[spacing], className), ...props }));
37
- });
38
- Divider.displayName = "Divider";
39
- export { Divider };
@@ -1,79 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import * as React from "react";
4
- import { cn } from "../lib/utils";
5
- import { Icon } from "./Icon";
6
- const Drawer = React.forwardRef(({ open, onOpenChange, children, className, side = "right", size = "md", showBackdrop = true, closeOnBackdropClick = true, closeOnEscape = true, ...props }, ref) => {
7
- const [isVisible, setIsVisible] = React.useState(false);
8
- const [isAnimating, setIsAnimating] = React.useState(false);
9
- React.useEffect(() => {
10
- if (open) {
11
- setIsVisible(true);
12
- setIsAnimating(true);
13
- // 애니메이션 시작을 위한 지연
14
- const timer = setTimeout(() => setIsAnimating(false), 50);
15
- return () => clearTimeout(timer);
16
- }
17
- else {
18
- setIsAnimating(true);
19
- const timer = setTimeout(() => {
20
- setIsVisible(false);
21
- setIsAnimating(false);
22
- }, 300); // 애니메이션 완료 후 숨김
23
- return () => clearTimeout(timer);
24
- }
25
- }, [open]);
26
- React.useEffect(() => {
27
- if (!closeOnEscape)
28
- return;
29
- const handleEscape = (e) => {
30
- if (e.key === "Escape" && open) {
31
- onOpenChange(false);
32
- }
33
- };
34
- if (open) {
35
- document.addEventListener("keydown", handleEscape);
36
- document.body.style.overflow = "hidden";
37
- }
38
- return () => {
39
- document.removeEventListener("keydown", handleEscape);
40
- document.body.style.overflow = "";
41
- };
42
- }, [open, closeOnEscape, onOpenChange]);
43
- if (!isVisible)
44
- return null;
45
- const sizeClasses = {
46
- sm: side === "left" || side === "right" ? "w-80" : "h-64",
47
- md: side === "left" || side === "right" ? "w-96" : "h-96",
48
- lg: side === "left" || side === "right" ? "w-[28rem]" : "h-[32rem]",
49
- xl: side === "left" || side === "right" ? "w-[32rem]" : "h-[40rem]",
50
- full: side === "left" || side === "right" ? "w-full" : "h-full"
51
- };
52
- const sideClasses = {
53
- left: "left-0 top-0 h-full translate-x-0",
54
- right: "right-0 top-0 h-full translate-x-0",
55
- top: "top-0 left-0 w-full translate-y-0",
56
- bottom: "bottom-0 left-0 w-full translate-y-0"
57
- };
58
- const transformClasses = {
59
- left: isAnimating ? (open ? "translate-x-0" : "-translate-x-full") : "",
60
- right: isAnimating ? (open ? "translate-x-0" : "translate-x-full") : "",
61
- top: isAnimating ? (open ? "translate-y-0" : "-translate-y-full") : "",
62
- bottom: isAnimating ? (open ? "translate-y-0" : "translate-y-full") : ""
63
- };
64
- return (_jsxs("div", { className: "fixed inset-0 z-50", children: [showBackdrop && (_jsx("div", { className: cn("absolute inset-0 bg-black/50 backdrop-blur-sm transition-opacity duration-300", isAnimating ? (open ? "opacity-100" : "opacity-0") : ""), onClick: closeOnBackdropClick ? () => onOpenChange(false) : undefined })), _jsx("div", { ref: ref, className: cn("absolute bg-white/95 dark:!bg-gray-800/95 backdrop-blur-xl border border-gray-200/50 dark:!border-gray-600/50 shadow-2xl transition-transform duration-300 ease-out", sizeClasses[size], sideClasses[side], transformClasses[side], className), ...props, children: children })] }));
65
- });
66
- Drawer.displayName = "Drawer";
67
- const DrawerHeader = React.forwardRef(({ children, className, showCloseButton = true, onClose, ...props }, ref) => {
68
- return (_jsxs("div", { ref: ref, className: cn("flex items-center justify-between p-6 border-b border-gray-200/50 dark:border-gray-700/50", className), ...props, children: [_jsx("div", { className: "flex-1", children: children }), showCloseButton && (_jsx("button", { onClick: onClose, className: "p-2 rounded-lg hover:bg-gray-100/80 dark:hover:bg-gray-800/80 transition-colors", children: _jsx(Icon, { name: "x", size: 20 }) }))] }));
69
- });
70
- DrawerHeader.displayName = "DrawerHeader";
71
- const DrawerContent = React.forwardRef(({ children, className, ...props }, ref) => {
72
- return (_jsx("div", { ref: ref, className: cn("flex-1 p-6 overflow-y-auto", className), ...props, children: children }));
73
- });
74
- DrawerContent.displayName = "DrawerContent";
75
- const DrawerFooter = React.forwardRef(({ children, className, ...props }, ref) => {
76
- return (_jsx("div", { ref: ref, className: cn("flex items-center justify-end gap-3 p-6 border-t border-gray-200/50 dark:border-gray-700/50", className), ...props, children: children }));
77
- });
78
- DrawerFooter.displayName = "DrawerFooter";
79
- export { Drawer, DrawerHeader, DrawerContent, DrawerFooter };
@@ -1,174 +0,0 @@
1
- "use client";
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import * as React from "react";
4
- import { cn } from "../lib/utils";
5
- const Dropdown = React.forwardRef(({ className, trigger, children, open: controlledOpen, onOpenChange, placement = "bottom", align = "start", offset = 8, disabled = false, showArrow = true, ...props }, ref) => {
6
- const [internalOpen, setInternalOpen] = React.useState(false);
7
- const [coords, setCoords] = React.useState({ x: 0, y: 0 });
8
- const triggerRef = React.useRef(null);
9
- const dropdownRef = React.useRef(null);
10
- const isControlled = controlledOpen !== undefined;
11
- const isOpen = isControlled ? controlledOpen : internalOpen;
12
- const handleOpenChange = (newOpen) => {
13
- if (disabled)
14
- return;
15
- if (!isControlled) {
16
- setInternalOpen(newOpen);
17
- }
18
- onOpenChange?.(newOpen);
19
- };
20
- const handleTriggerClick = () => {
21
- handleOpenChange(!isOpen);
22
- };
23
- const updatePosition = React.useCallback(() => {
24
- if (!triggerRef.current || !dropdownRef.current)
25
- return;
26
- const triggerRect = triggerRef.current.getBoundingClientRect();
27
- const dropdownRect = dropdownRef.current.getBoundingClientRect();
28
- const viewportWidth = window.innerWidth;
29
- const viewportHeight = window.innerHeight;
30
- let x = 0;
31
- let y = 0;
32
- // 기본 위치 계산
33
- switch (placement) {
34
- case "top":
35
- x = triggerRect.left;
36
- y = triggerRect.top - offset;
37
- break;
38
- case "bottom":
39
- x = triggerRect.left;
40
- y = triggerRect.bottom + offset;
41
- break;
42
- case "left":
43
- x = triggerRect.left - offset;
44
- y = triggerRect.top;
45
- break;
46
- case "right":
47
- x = triggerRect.right + offset;
48
- y = triggerRect.top;
49
- break;
50
- }
51
- // 정렬 조정
52
- switch (align) {
53
- case "center":
54
- if (placement === "top" || placement === "bottom") {
55
- x = triggerRect.left + triggerRect.width / 2 - dropdownRect.width / 2;
56
- }
57
- else {
58
- y = triggerRect.top + triggerRect.height / 2 - dropdownRect.height / 2;
59
- }
60
- break;
61
- case "end":
62
- if (placement === "top" || placement === "bottom") {
63
- x = triggerRect.right - dropdownRect.width;
64
- }
65
- else {
66
- y = triggerRect.bottom - dropdownRect.height;
67
- }
68
- break;
69
- case "start":
70
- default:
71
- // 기본값은 이미 start 정렬
72
- break;
73
- }
74
- // 뷰포트 경계 확인 및 조정
75
- if (x < 8)
76
- x = 8; // 8px 여백
77
- if (x + dropdownRect.width > viewportWidth - 8) {
78
- x = viewportWidth - dropdownRect.width - 8; // 8px 여백
79
- }
80
- if (y < 8)
81
- y = 8; // 8px 여백
82
- if (y + dropdownRect.height > viewportHeight - 8) {
83
- y = viewportHeight - dropdownRect.height - 8; // 8px 여백
84
- }
85
- setCoords({ x, y });
86
- }, [placement, align, offset]);
87
- React.useEffect(() => {
88
- if (isOpen) {
89
- updatePosition();
90
- window.addEventListener('resize', updatePosition);
91
- window.addEventListener('scroll', updatePosition);
92
- return () => {
93
- window.removeEventListener('resize', updatePosition);
94
- window.removeEventListener('scroll', updatePosition);
95
- };
96
- }
97
- }, [isOpen, updatePosition]);
98
- React.useEffect(() => {
99
- const handleClickOutside = (event) => {
100
- if (triggerRef.current &&
101
- dropdownRef.current &&
102
- !triggerRef.current.contains(event.target) &&
103
- !dropdownRef.current.contains(event.target)) {
104
- handleOpenChange(false);
105
- }
106
- };
107
- if (isOpen) {
108
- document.addEventListener('mousedown', handleClickOutside);
109
- return () => {
110
- document.removeEventListener('mousedown', handleClickOutside);
111
- };
112
- }
113
- }, [isOpen]);
114
- const getPlacementClasses = () => {
115
- switch (placement) {
116
- case "top":
117
- return "bottom-full left-0 mb-2"; // 8px 간격
118
- case "bottom":
119
- return "top-full left-0 mt-2"; // 8px 간격
120
- case "left":
121
- return "right-full top-0 mr-2"; // 8px 간격
122
- case "right":
123
- return "left-full top-0 ml-2"; // 8px 간격
124
- default:
125
- return "top-full left-0 mt-2";
126
- }
127
- };
128
- const getArrowClasses = () => {
129
- switch (placement) {
130
- case "top":
131
- return "top-full left-4 -translate-x-1/2 border-t-gray-100 dark:border-t-gray-800";
132
- case "bottom":
133
- return "bottom-full left-4 -translate-x-1/2 border-b-gray-100 dark:border-b-gray-800";
134
- case "left":
135
- return "left-full top-4 -translate-y-1/2 border-l-gray-100 dark:border-l-gray-800";
136
- case "right":
137
- return "right-full top-4 -translate-y-1/2 border-r-gray-100 dark:border-r-gray-800";
138
- default:
139
- return "bottom-full left-4 -translate-x-1/2 border-b-gray-100 dark:border-b-gray-800";
140
- }
141
- };
142
- return (_jsxs("div", { ref: ref, className: cn("relative", className), ...props, children: [_jsx("div", { ref: triggerRef, onClick: handleTriggerClick, className: "inline-block cursor-pointer", children: trigger }), isOpen && (_jsxs("div", { ref: dropdownRef, className: cn("absolute z-50 bg-white dark:bg-gray-800 rounded-lg shadow-xl backdrop-blur-sm", // 보더 대신 섀도우 사용
143
- "min-w-[200px] py-2", // 16px 패딩
144
- getPlacementClasses()), style: {
145
- transform: `translate(${coords.x}px, ${coords.y}px)`,
146
- boxShadow: "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)"
147
- }, children: [showArrow && (_jsx("div", { className: cn("absolute w-0 h-0 border-4 border-transparent", getArrowClasses()) })), _jsx("div", { className: "relative z-10", children: children })] }))] }));
148
- });
149
- Dropdown.displayName = "Dropdown";
150
- const DropdownItem = React.forwardRef(({ className, icon, variant = "default", children, disabled, ...props }, ref) => {
151
- const getVariantClasses = () => {
152
- switch (variant) {
153
- case "destructive":
154
- return "text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20";
155
- case "disabled":
156
- return "text-gray-400 dark:text-gray-500 cursor-not-allowed";
157
- default:
158
- return "text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700";
159
- }
160
- };
161
- return (_jsxs("button", { ref: ref, className: cn("w-full flex items-center gap-3 px-4 py-3 text-sm font-medium transition-colors focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-700", // 16px, 12px 패딩
162
- getVariantClasses(), className), disabled: disabled || variant === "disabled", ...props, children: [icon && (_jsx("div", { className: "flex-shrink-0 w-4 h-4", children: icon })), _jsx("span", { className: "flex-1 text-left", children: children })] }));
163
- });
164
- DropdownItem.displayName = "DropdownItem";
165
- const DropdownSeparator = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn("h-px bg-gray-200 dark:bg-gray-700 my-2", className), ...props })));
166
- DropdownSeparator.displayName = "DropdownSeparator";
167
- const DropdownLabel = React.forwardRef(({ className, children, ...props }, ref) => (_jsx("div", { ref: ref, className: cn("px-4 py-2 text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wide", className), ...props, children: children })));
168
- DropdownLabel.displayName = "DropdownLabel";
169
- // 편의 컴포넌트들
170
- const DropdownMenu = React.forwardRef(({ className, children, ...props }, ref) => (_jsx("div", { ref: ref, className: cn("py-1", className), ...props, children: children })));
171
- DropdownMenu.displayName = "DropdownMenu";
172
- const DropdownGroup = React.forwardRef(({ className, children, ...props }, ref) => (_jsx("div", { ref: ref, className: cn("space-y-1", className), ...props, children: children })));
173
- DropdownGroup.displayName = "DropdownGroup";
174
- export { Dropdown, DropdownItem, DropdownSeparator, DropdownLabel, DropdownMenu, DropdownGroup };