@hua-labs/ui 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/README.md +55 -67
  2. package/dist/{ComponentLayout-btJq4TjA.d.mts → ComponentLayout-BhM4VSoq.d.mts} +1 -1
  3. package/dist/Section-BWzyshgX.d.mts +67 -0
  4. package/dist/advanced/dashboard.d.ts.map +1 -1
  5. package/dist/advanced-dashboard.d.mts +1 -1
  6. package/dist/advanced-dashboard.mjs +3 -3
  7. package/dist/advanced-dashboard.mjs.map +1 -1
  8. package/dist/advanced-emotion.mjs +1 -1
  9. package/dist/advanced-motion.d.mts +74 -7
  10. package/dist/advanced-motion.mjs +1 -1
  11. package/dist/advanced.d.mts +4 -4
  12. package/dist/advanced.mjs +3 -3
  13. package/dist/advanced.mjs.map +1 -1
  14. package/dist/{chunk-GLZKT7JN.mjs → chunk-5DPW7SVD.mjs} +3 -3
  15. package/dist/{chunk-GLZKT7JN.mjs.map → chunk-5DPW7SVD.mjs.map} +1 -1
  16. package/dist/{chunk-X7ZIWYRC.mjs → chunk-5L5HIPKA.mjs} +2 -2
  17. package/dist/{chunk-X7ZIWYRC.mjs.map → chunk-5L5HIPKA.mjs.map} +1 -1
  18. package/dist/chunk-A5YOVVM5.mjs +3 -0
  19. package/dist/chunk-A5YOVVM5.mjs.map +1 -0
  20. package/dist/chunk-CNW22G24.mjs +13 -0
  21. package/dist/chunk-CNW22G24.mjs.map +1 -0
  22. package/dist/chunk-CW66UBQG.mjs +3 -0
  23. package/dist/chunk-CW66UBQG.mjs.map +1 -0
  24. package/dist/chunk-EAZEI74V.mjs +3 -0
  25. package/dist/chunk-EAZEI74V.mjs.map +1 -0
  26. package/dist/{chunk-LH77I6HO.mjs → chunk-EPY3432E.mjs} +2 -2
  27. package/dist/{chunk-LH77I6HO.mjs.map → chunk-EPY3432E.mjs.map} +1 -1
  28. package/dist/{chunk-SGEP3CQE.mjs → chunk-F2M4YDDQ.mjs} +2 -2
  29. package/dist/{chunk-SGEP3CQE.mjs.map → chunk-F2M4YDDQ.mjs.map} +1 -1
  30. package/dist/chunk-FHMFDCX2.mjs +3 -0
  31. package/dist/chunk-FHMFDCX2.mjs.map +1 -0
  32. package/dist/chunk-HBIUCLFL.mjs +3 -0
  33. package/dist/chunk-HBIUCLFL.mjs.map +1 -0
  34. package/dist/{chunk-LOYAJIWO.mjs → chunk-HEBXAFRY.mjs} +2 -2
  35. package/dist/{chunk-LOYAJIWO.mjs.map → chunk-HEBXAFRY.mjs.map} +1 -1
  36. package/dist/chunk-IG47LMOD.mjs +3 -0
  37. package/dist/chunk-IG47LMOD.mjs.map +1 -0
  38. package/dist/{chunk-IFSEJVOR.mjs → chunk-J47ZEXEL.mjs} +2 -2
  39. package/dist/{chunk-IFSEJVOR.mjs.map → chunk-J47ZEXEL.mjs.map} +1 -1
  40. package/dist/{chunk-IN7RWQCJ.mjs → chunk-K2FOFIST.mjs} +2 -2
  41. package/dist/{chunk-IN7RWQCJ.mjs.map → chunk-K2FOFIST.mjs.map} +1 -1
  42. package/dist/{chunk-UWHCM3S6.mjs → chunk-LL6QPRD7.mjs} +2 -2
  43. package/dist/{chunk-UWHCM3S6.mjs.map → chunk-LL6QPRD7.mjs.map} +1 -1
  44. package/dist/{chunk-PAEKNQWW.mjs → chunk-NMJLOK6M.mjs} +2 -2
  45. package/dist/{chunk-PAEKNQWW.mjs.map → chunk-NMJLOK6M.mjs.map} +1 -1
  46. package/dist/chunk-O24K56OS.mjs +3 -0
  47. package/dist/chunk-O24K56OS.mjs.map +1 -0
  48. package/dist/chunk-OIWG3IJ7.mjs +3 -0
  49. package/dist/chunk-OIWG3IJ7.mjs.map +1 -0
  50. package/dist/{chunk-VWSBJUNI.mjs → chunk-OLLU7ZFH.mjs} +2 -2
  51. package/dist/{chunk-VWSBJUNI.mjs.map → chunk-OLLU7ZFH.mjs.map} +1 -1
  52. package/dist/chunk-Q76JW7X5.mjs +73 -0
  53. package/dist/chunk-Q76JW7X5.mjs.map +1 -0
  54. package/dist/chunk-QEMPERUK.mjs +3 -0
  55. package/dist/chunk-QEMPERUK.mjs.map +1 -0
  56. package/dist/{chunk-XV3Y7QVU.mjs → chunk-QRM66RQG.mjs} +2 -2
  57. package/dist/{chunk-XV3Y7QVU.mjs.map → chunk-QRM66RQG.mjs.map} +1 -1
  58. package/dist/{chunk-6KTHJ3EL.mjs → chunk-QRRP7TGF.mjs} +3 -3
  59. package/dist/{chunk-6KTHJ3EL.mjs.map → chunk-QRRP7TGF.mjs.map} +1 -1
  60. package/dist/chunk-SD6XGDAC.mjs +3 -0
  61. package/dist/chunk-SD6XGDAC.mjs.map +1 -0
  62. package/dist/chunk-SDFVGFXT.mjs +3 -0
  63. package/dist/chunk-SDFVGFXT.mjs.map +1 -0
  64. package/dist/{chunk-N7M6RIN4.mjs → chunk-SMLDNOV3.mjs} +3 -3
  65. package/dist/{chunk-N7M6RIN4.mjs.map → chunk-SMLDNOV3.mjs.map} +1 -1
  66. package/dist/{chunk-NBJUE7NR.mjs → chunk-TAP6MYDW.mjs} +2 -2
  67. package/dist/{chunk-NBJUE7NR.mjs.map → chunk-TAP6MYDW.mjs.map} +1 -1
  68. package/dist/{chunk-PYBYZVSL.mjs → chunk-TBZ645BI.mjs} +2 -2
  69. package/dist/{chunk-PYBYZVSL.mjs.map → chunk-TBZ645BI.mjs.map} +1 -1
  70. package/dist/{chunk-C4OACMTB.mjs → chunk-V2DNYJR6.mjs} +2 -2
  71. package/dist/{chunk-C4OACMTB.mjs.map → chunk-V2DNYJR6.mjs.map} +1 -1
  72. package/dist/chunk-VBABZXL7.mjs +3 -0
  73. package/dist/chunk-VBABZXL7.mjs.map +1 -0
  74. package/dist/{chunk-OSCMSA2Q.mjs → chunk-WYBSHTGY.mjs} +2 -2
  75. package/dist/{chunk-OSCMSA2Q.mjs.map → chunk-WYBSHTGY.mjs.map} +1 -1
  76. package/dist/chunk-ZQUMJQYV.mjs +3 -0
  77. package/dist/chunk-ZQUMJQYV.mjs.map +1 -0
  78. package/dist/chunk-ZY23NOT4.mjs +3 -0
  79. package/dist/chunk-ZY23NOT4.mjs.map +1 -0
  80. package/dist/components/Action.d.ts.map +1 -1
  81. package/dist/components/Badge.d.ts +1 -1
  82. package/dist/components/Button.d.ts.map +1 -1
  83. package/dist/components/Card.d.ts.map +1 -1
  84. package/dist/components/DatePicker.d.ts.map +1 -1
  85. package/dist/components/Dropdown.d.ts +0 -50
  86. package/dist/components/Dropdown.d.ts.map +1 -1
  87. package/dist/components/Icon/Icon.d.ts.map +1 -1
  88. package/dist/components/Modal.d.ts.map +1 -1
  89. package/dist/components/Popover.d.ts +2 -0
  90. package/dist/components/Popover.d.ts.map +1 -1
  91. package/dist/components/Progress.d.ts +3 -2
  92. package/dist/components/Progress.d.ts.map +1 -1
  93. package/dist/components/Section.d.ts +44 -0
  94. package/dist/components/Section.d.ts.map +1 -0
  95. package/dist/components/advanced/AnimatedGradient.d.ts.map +1 -1
  96. package/dist/components/advanced/Carousel.d.ts.map +1 -1
  97. package/dist/components/advanced/DotNav.d.ts +26 -0
  98. package/dist/components/advanced/DotNav.d.ts.map +1 -0
  99. package/dist/components/advanced/HorizontalScroll.d.ts +20 -0
  100. package/dist/components/advanced/HorizontalScroll.d.ts.map +1 -0
  101. package/dist/components/advanced/ImageReveal.d.ts +24 -0
  102. package/dist/components/advanced/ImageReveal.d.ts.map +1 -0
  103. package/dist/components/advanced/Parallax.d.ts +9 -6
  104. package/dist/components/advanced/Parallax.d.ts.map +1 -1
  105. package/dist/components/advanced/TextReveal.d.ts.map +1 -1
  106. package/dist/components/advanced/index.d.ts +6 -0
  107. package/dist/components/advanced/index.d.ts.map +1 -1
  108. package/dist/data.mjs +1 -1
  109. package/dist/data.mjs.map +1 -1
  110. package/dist/feedback.mjs +1 -1
  111. package/dist/form.mjs +3 -3
  112. package/dist/form.mjs.map +1 -1
  113. package/dist/{icons-Bj_nr8Ba.d.mts → icons-DcOBy9Hf.d.mts} +10 -1
  114. package/dist/iconsax-extended.mjs +2 -2
  115. package/dist/iconsax-extended.mjs.map +1 -1
  116. package/dist/index.d.mts +10 -109
  117. package/dist/index.d.ts +4 -0
  118. package/dist/index.d.ts.map +1 -1
  119. package/dist/index.mjs +14 -14
  120. package/dist/index.mjs.map +1 -1
  121. package/dist/interactive.mjs +1 -1
  122. package/dist/interactive.mjs.map +1 -1
  123. package/dist/landing/LandingAbout.d.ts +3 -0
  124. package/dist/landing/LandingAbout.d.ts.map +1 -0
  125. package/dist/landing/LandingCTA.d.ts +3 -0
  126. package/dist/landing/LandingCTA.d.ts.map +1 -0
  127. package/dist/landing/LandingContact.d.ts +3 -0
  128. package/dist/landing/LandingContact.d.ts.map +1 -0
  129. package/dist/landing/LandingExperience.d.ts +3 -0
  130. package/dist/landing/LandingExperience.d.ts.map +1 -0
  131. package/dist/landing/LandingFeatures.d.ts +3 -0
  132. package/dist/landing/LandingFeatures.d.ts.map +1 -0
  133. package/dist/landing/LandingHero.d.ts +3 -0
  134. package/dist/landing/LandingHero.d.ts.map +1 -0
  135. package/dist/landing/LandingLogoCloud.d.ts +3 -0
  136. package/dist/landing/LandingLogoCloud.d.ts.map +1 -0
  137. package/dist/landing/LandingMetrics.d.ts +3 -0
  138. package/dist/landing/LandingMetrics.d.ts.map +1 -0
  139. package/dist/landing/LandingProjects.d.ts +3 -0
  140. package/dist/landing/LandingProjects.d.ts.map +1 -0
  141. package/dist/landing/LandingProvider.d.ts +4 -0
  142. package/dist/landing/LandingProvider.d.ts.map +1 -0
  143. package/dist/landing/LandingShowcase.d.ts +3 -0
  144. package/dist/landing/LandingShowcase.d.ts.map +1 -0
  145. package/dist/landing/LandingSkills.d.ts +3 -0
  146. package/dist/landing/LandingSkills.d.ts.map +1 -0
  147. package/dist/landing/LandingStats.d.ts +3 -0
  148. package/dist/landing/LandingStats.d.ts.map +1 -0
  149. package/dist/landing/LandingTestimonials.d.ts +3 -0
  150. package/dist/landing/LandingTestimonials.d.ts.map +1 -0
  151. package/dist/landing/index.d.ts +47 -0
  152. package/dist/landing/index.d.ts.map +1 -0
  153. package/dist/landing/themes/app.d.ts +3 -0
  154. package/dist/landing/themes/app.d.ts.map +1 -0
  155. package/dist/landing/themes/corporate.d.ts +3 -0
  156. package/dist/landing/themes/corporate.d.ts.map +1 -0
  157. package/dist/landing/themes/dashboard.d.ts +3 -0
  158. package/dist/landing/themes/dashboard.d.ts.map +1 -0
  159. package/dist/landing/themes/immersive.d.ts +3 -0
  160. package/dist/landing/themes/immersive.d.ts.map +1 -0
  161. package/dist/landing/themes/index.d.ts +15 -0
  162. package/dist/landing/themes/index.d.ts.map +1 -0
  163. package/dist/landing/themes/marketing.d.ts +3 -0
  164. package/dist/landing/themes/marketing.d.ts.map +1 -0
  165. package/dist/landing/themes/portfolio.d.ts +3 -0
  166. package/dist/landing/themes/portfolio.d.ts.map +1 -0
  167. package/dist/landing/themes/product.d.ts +3 -0
  168. package/dist/landing/themes/product.d.ts.map +1 -0
  169. package/dist/landing/types.d.ts +346 -0
  170. package/dist/landing/types.d.ts.map +1 -0
  171. package/dist/landing.d.mts +417 -0
  172. package/dist/landing.mjs +31 -0
  173. package/dist/landing.mjs.map +1 -0
  174. package/dist/lib/icon-providers.d.ts +9 -25
  175. package/dist/lib/icon-providers.d.ts.map +1 -1
  176. package/dist/lib/icons.d.ts +10 -1
  177. package/dist/lib/icons.d.ts.map +1 -1
  178. package/dist/lib/utils.d.ts.map +1 -1
  179. package/dist/navigation.d.mts +1 -1
  180. package/dist/navigation.mjs +1 -1
  181. package/dist/navigation.mjs.map +1 -1
  182. package/dist/overlay.d.mts +2 -50
  183. package/dist/overlay.mjs +1 -1
  184. package/dist/overlay.mjs.map +1 -1
  185. package/dist/sdui.mjs +1 -1
  186. package/dist/sdui.mjs.map +1 -1
  187. package/dist/theme.d.mts +85 -0
  188. package/dist/theme.d.ts +14 -0
  189. package/dist/theme.d.ts.map +1 -0
  190. package/dist/theme.mjs +3 -0
  191. package/dist/theme.mjs.map +1 -0
  192. package/package.json +30 -20
  193. package/src/styles/landing.css +107 -0
  194. package/src/styles/utilities.css +58 -0
  195. package/dist/advanced-dashboard.js +0 -39
  196. package/dist/advanced-dashboard.js.map +0 -1
  197. package/dist/advanced-emotion.js +0 -2
  198. package/dist/advanced-emotion.js.map +0 -1
  199. package/dist/advanced-motion.js +0 -82
  200. package/dist/advanced-motion.js.map +0 -1
  201. package/dist/advanced.js +0 -112
  202. package/dist/advanced.js.map +0 -1
  203. package/dist/chunk-BXX2TZUB.mjs +0 -3
  204. package/dist/chunk-BXX2TZUB.mjs.map +0 -1
  205. package/dist/chunk-COR6CDMA.mjs +0 -83
  206. package/dist/chunk-COR6CDMA.mjs.map +0 -1
  207. package/dist/chunk-FFH4ZFKS.mjs +0 -3
  208. package/dist/chunk-FFH4ZFKS.mjs.map +0 -1
  209. package/dist/chunk-HN5LSP6L.mjs +0 -3
  210. package/dist/chunk-HN5LSP6L.mjs.map +0 -1
  211. package/dist/chunk-LPAG7DCA.mjs +0 -3
  212. package/dist/chunk-LPAG7DCA.mjs.map +0 -1
  213. package/dist/chunk-QQCELXFD.mjs +0 -3
  214. package/dist/chunk-QQCELXFD.mjs.map +0 -1
  215. package/dist/chunk-RPUS7G7Q.mjs +0 -3
  216. package/dist/chunk-RPUS7G7Q.mjs.map +0 -1
  217. package/dist/chunk-SDFHJ4GB.mjs +0 -3
  218. package/dist/chunk-SDFHJ4GB.mjs.map +0 -1
  219. package/dist/chunk-UUHAXGMO.mjs +0 -3
  220. package/dist/chunk-UUHAXGMO.mjs.map +0 -1
  221. package/dist/data.js +0 -3
  222. package/dist/data.js.map +0 -1
  223. package/dist/feedback.js +0 -12
  224. package/dist/feedback.js.map +0 -1
  225. package/dist/form.js +0 -8
  226. package/dist/form.js.map +0 -1
  227. package/dist/iconsax-extended.js +0 -3
  228. package/dist/iconsax-extended.js.map +0 -1
  229. package/dist/iconsax.js +0 -3
  230. package/dist/iconsax.js.map +0 -1
  231. package/dist/index.js +0 -51
  232. package/dist/index.js.map +0 -1
  233. package/dist/interactive.js +0 -2
  234. package/dist/interactive.js.map +0 -1
  235. package/dist/lib/phosphor-icons.d.ts +0 -6
  236. package/dist/lib/phosphor-icons.d.ts.map +0 -1
  237. package/dist/navigation.js +0 -12
  238. package/dist/navigation.js.map +0 -1
  239. package/dist/overlay.js +0 -3
  240. package/dist/overlay.js.map +0 -1
  241. package/dist/sdui.js +0 -9
  242. package/dist/sdui.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Navigation.tsx","../src/components/Pagination.tsx","../src/components/PageNavigation.tsx","../src/components/PageTransition.tsx"],"names":["Navigation","React","className","value","defaultValue","onValueChange","variant","scale","children","props","ref","activeTab","setActiveTab","isControlled","currentValue","jsx","merge","child","NavigationList","_onValueChange","getStyleClasses","getScaleClasses","NavigationItem","active","handleClick","NavigationContent","NavigationComponent","Pagination","currentPage","totalPages","onPageChange","showFirstLast","showPrevNext","maxVisiblePages","size","shape","getVisiblePages","pages","halfVisible","start","end","i","getSizeClasses","getShapeClasses","getVariantClasses","isActive","handlePageClick","page","visiblePages","jsxs","index","PaginationOutlined","PaginationMinimal","PaginationWithInfo","totalItems","itemsPerPage","showInfo","startItem","endItem","Fragment","PageNavigation","prevPage","nextPage","showOnMobile","Icon","PageTransition","duration","loadingVariant","loadingText","showLoading","onTransitionStart","onTransitionEnd","isLoading","setIsLoading","useState","isVisible","setIsVisible","useEffect","timer","transitionClasses","LoadingSpinner","FadeTransition","SlideTransition","ScaleTransition","FlipTransition"],"mappings":"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","file":"navigation.mjs","sourcesContent":["\"use client\"\n\nimport React from \"react\"\nimport { merge } from \"../lib/utils\"\n\n/**\n * Navigation 컴포넌트의 props / Navigation component props\n * @typedef {Object} NavigationProps\n * @property {string} [value] - 제어 모드에서 활성 탭 값 / Active tab value in controlled mode\n * @property {string} [defaultValue] - 비제어 모드에서 기본 활성 탭 값 / Default active tab value in uncontrolled mode\n * @property {(value: string) => void} [onValueChange] - 탭 변경 콜백 / Tab change callback\n * @property {\"pills\" | \"underline\" | \"cards\"} [variant=\"pills\"] - Navigation 스타일 변형 / Navigation style variant\n * @property {\"small\" | \"medium\" | \"large\"} [scale=\"medium\"] - Navigation 크기 / Navigation size\n * @extends {Omit<React.HTMLAttributes<HTMLDivElement>, 'style'>}\n */\nexport interface NavigationProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'style'> {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n variant?: \"pills\" | \"underline\" | \"cards\"\n scale?: \"small\" | \"medium\" | \"large\"\n}\n\n/**\n * Navigation 컴포넌트 / Navigation component\n * \n * 탭 네비게이션 컴포넌트입니다.\n * NavigationList, NavigationItem, NavigationContent와 함께 사용합니다.\n * \n * Tab navigation component.\n * Used with NavigationList, NavigationItem, and NavigationContent.\n * \n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <Navigation>\n * <Navigation.List>\n * <Navigation.Item value=\"tab1\">탭 1</Navigation.Item>\n * <Navigation.Item value=\"tab2\">탭 2</Navigation.Item>\n * </Navigation.List>\n * <Navigation.Content value=\"tab1\">내용 1</Navigation.Content>\n * </Navigation>\n * \n * @param {NavigationProps} props - Navigation 컴포넌트의 props / Navigation component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} Navigation 컴포넌트 / Navigation component\n */\nconst Navigation = React.forwardRef<HTMLDivElement, NavigationProps>(\n ({ \n className, \n value,\n defaultValue,\n onValueChange,\n variant = \"pills\",\n scale = \"medium\",\n children,\n ...props \n }, ref) => {\n const [activeTab, setActiveTab] = React.useState(value || defaultValue || \"\")\n const isControlled = value !== undefined\n const currentValue = isControlled ? value : activeTab\n\n const _handleTabChange = (newValue: string) => {\n if (!isControlled) {\n setActiveTab(newValue)\n }\n onValueChange?.(newValue)\n }\n\n React.useEffect(() => {\n if (value !== undefined) {\n setActiveTab(value)\n }\n }, [value])\n\n return (\n <div\n ref={ref}\n className={merge(\n \"w-full\",\n className\n )}\n {...props}\n >\n {React.Children.map(children, (child) => {\n if (React.isValidElement(child)) {\n return React.cloneElement(child, {\n value: currentValue,\n variant,\n scale\n } as Partial<NavigationListProps | NavigationItemProps>)\n }\n return child\n })}\n </div>\n )\n }\n)\nNavigation.displayName = \"Navigation\"\n\n/**\n * NavigationList 컴포넌트의 props / NavigationList component props\n * @typedef {Object} NavigationListProps\n * @property {string} [value] - 활성 탭 값 / Active tab value\n * @property {(value: string) => void} [onValueChange] - 탭 변경 콜백 / Tab change callback\n * @property {\"pills\" | \"underline\" | \"cards\"} [variant=\"pills\"] - Navigation 스타일 변형 / Navigation style variant\n * @property {\"small\" | \"medium\" | \"large\"} [scale=\"medium\"] - Navigation 크기 / Navigation size\n * @extends {Omit<React.HTMLAttributes<HTMLDivElement>, 'style'>}\n */\nexport interface NavigationListProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'style'> {\n value?: string\n onValueChange?: (value: string) => void\n variant?: \"pills\" | \"underline\" | \"cards\"\n scale?: \"small\" | \"medium\" | \"large\"\n}\n\nconst NavigationList = React.forwardRef<HTMLDivElement, NavigationListProps>(\n ({\n className,\n value,\n onValueChange: _onValueChange,\n variant = \"pills\",\n scale = \"medium\",\n children,\n ...props\n }, ref) => {\n const getStyleClasses = () => {\n switch (variant) {\n case \"pills\":\n return \"bg-muted p-1 rounded-xl\"\n case \"underline\":\n return \"border-b border-border\"\n case \"cards\":\n return \"bg-muted/50 p-1 rounded-xl\"\n default:\n return \"bg-muted p-1 rounded-xl\"\n }\n }\n\n const getScaleClasses = () => {\n switch (scale) {\n case \"small\":\n return \"gap-1\"\n case \"large\":\n return \"gap-3\"\n default:\n return \"gap-2\"\n }\n }\n\n return (\n <div\n ref={ref}\n className={merge(\n \"flex\",\n getStyleClasses(),\n getScaleClasses(),\n className\n )}\n {...props}\n >\n {React.Children.map(children, (child) => {\n if (React.isValidElement(child)) {\n return React.cloneElement(child, {\n value,\n variant,\n scale\n } as Partial<NavigationItemProps>)\n }\n return child\n })}\n </div>\n )\n }\n)\nNavigationList.displayName = \"NavigationList\"\n\n/**\n * NavigationItem 컴포넌트의 props / NavigationItem component props\n * @typedef {Object} NavigationItemProps\n * @property {string} value - 탭 값 / Tab value\n * @property {(value: string) => void} [onValueChange] - 탭 변경 콜백 / Tab change callback\n * @property {\"pills\" | \"underline\" | \"cards\"} [variant] - Navigation 스타일 변형 (자동으로 설정됨) / Navigation style variant (auto-set)\n * @property {\"small\" | \"medium\" | \"large\"} [scale] - Navigation 크기 (자동으로 설정됨) / Navigation size (auto-set)\n * @property {boolean} [active] - 활성 상태 (자동으로 설정됨) / Active state (auto-set)\n * @extends {Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'style'>}\n */\nexport interface NavigationItemProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'style'> {\n value: string\n onValueChange?: (value: string) => void\n variant?: \"pills\" | \"underline\" | \"cards\"\n scale?: \"small\" | \"medium\" | \"large\"\n active?: boolean\n}\n\nconst NavigationItem = React.forwardRef<HTMLButtonElement, NavigationItemProps>(\n ({ \n className, \n value,\n onValueChange,\n variant = \"pills\",\n scale = \"medium\",\n active = false,\n children,\n ...props \n }, ref) => {\n const getStyleClasses = () => {\n switch (variant) {\n case \"pills\":\n return merge(\n \"rounded-lg px-3 py-2 text-sm font-medium transition-all\",\n active\n ? \"bg-background text-foreground shadow-sm\"\n : \"text-muted-foreground hover:text-foreground\"\n )\n case \"underline\":\n return merge(\n \"border-b-2 px-3 py-2 text-sm font-medium transition-all\",\n active\n ? \"border-primary text-primary\"\n : \"border-transparent text-muted-foreground hover:text-foreground\"\n )\n case \"cards\":\n return merge(\n \"rounded-lg px-3 py-2 text-sm font-medium transition-all\",\n active\n ? \"bg-background text-foreground shadow-sm border border-border\"\n : \"text-muted-foreground hover:text-foreground\"\n )\n default:\n return merge(\n \"rounded-lg px-3 py-2 text-sm font-medium transition-all\",\n active\n ? \"bg-background text-foreground shadow-sm\"\n : \"text-muted-foreground hover:text-foreground\"\n )\n }\n }\n\n const getScaleClasses = () => {\n switch (scale) {\n case \"small\":\n return \"text-xs px-2 py-1\"\n case \"large\":\n return \"text-base px-4 py-3\"\n default:\n return \"text-sm px-3 py-2\"\n }\n }\n\n const handleClick = () => {\n onValueChange?.(value)\n }\n\n return (\n <button\n ref={ref}\n className={merge(\n getStyleClasses(),\n getScaleClasses(),\n \"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2\",\n className\n )}\n onClick={handleClick}\n {...props}\n >\n {children}\n </button>\n )\n }\n)\nNavigationItem.displayName = \"NavigationItem\"\n\n/**\n * NavigationContent 컴포넌트의 props / NavigationContent component props\n * @typedef {Object} NavigationContentProps\n * @property {string} value - 탭 값 / Tab value\n * @property {boolean} [active] - 활성 상태 (자동으로 설정됨) / Active state (auto-set)\n * @extends {React.HTMLAttributes<HTMLDivElement>}\n */\nexport interface NavigationContentProps extends React.HTMLAttributes<HTMLDivElement> {\n value: string\n active?: boolean\n}\n\nconst NavigationContent = React.forwardRef<HTMLDivElement, NavigationContentProps>(\n ({ className, active = false, ...props }, ref) => {\n if (!active) return null\n\n return (\n <div\n ref={ref}\n className={merge(\"mt-4\", className)}\n {...props}\n />\n )\n }\n)\nNavigationContent.displayName = \"NavigationContent\"\n\n// 서브컴포넌트 타입 정의\nexport interface NavigationComponent extends React.ForwardRefExoticComponent<NavigationProps & React.RefAttributes<HTMLDivElement>> {\n List: typeof NavigationList\n Item: typeof NavigationItem\n Content: typeof NavigationContent\n}\n\nconst NavigationComponent = Navigation as NavigationComponent\nNavigationComponent.List = NavigationList\nNavigationComponent.Item = NavigationItem\nNavigationComponent.Content = NavigationContent\n\nexport { NavigationComponent as Navigation, NavigationList, NavigationItem, NavigationContent } ","\"use client\"\n\nimport React from \"react\"\nimport { merge } from \"../lib/utils\"\n\n/**\n * Pagination 컴포넌트의 props / Pagination component props\n * @typedef {Object} PaginationProps\n * @property {number} currentPage - 현재 페이지 번호 / Current page number\n * @property {number} totalPages - 전체 페이지 수 / Total number of pages\n * @property {(page: number) => void} onPageChange - 페이지 변경 콜백 / Page change callback\n * @property {boolean} [showFirstLast=true] - 첫/마지막 페이지 버튼 표시 여부 / Show first/last page buttons\n * @property {boolean} [showPrevNext=true] - 이전/다음 페이지 버튼 표시 여부 / Show previous/next page buttons\n * @property {number} [maxVisiblePages=5] - 최대 표시 페이지 수 / Maximum visible page numbers\n * @property {\"sm\" | \"md\" | \"lg\"} [size=\"md\"] - Pagination 크기 / Pagination size\n * @property {\"default\" | \"outlined\" | \"minimal\"} [variant=\"default\"] - Pagination 스타일 변형 / Pagination style variant\n * @property {\"square\" | \"circle\"} [shape=\"square\"] - 버튼 모양 / Button shape\n * @extends {React.HTMLAttributes<HTMLDivElement>}\n */\nexport interface PaginationProps extends React.HTMLAttributes<HTMLDivElement> {\n currentPage: number\n totalPages: number\n onPageChange: (page: number) => void\n showFirstLast?: boolean\n showPrevNext?: boolean\n maxVisiblePages?: number\n size?: \"sm\" | \"md\" | \"lg\"\n variant?: \"default\" | \"outlined\" | \"minimal\"\n shape?: \"square\" | \"circle\"\n}\n\n/**\n * Pagination 컴포넌트 / Pagination component\n * \n * 페이지네이션 컨트롤을 제공하는 컴포넌트입니다.\n * 첫/마지막 페이지, 이전/다음 페이지 버튼을 지원하며,\n * 많은 페이지가 있을 경우 자동으로 생략 표시(...)를 합니다.\n * \n * Component that provides pagination controls.\n * Supports first/last page and previous/next page buttons,\n * and automatically shows ellipsis (...) when there are many pages.\n * \n * @component\n * @example\n * // 기본 사용 / Basic usage\n * const [page, setPage] = useState(1)\n * \n * <Pagination\n * currentPage={page}\n * totalPages={10}\n * onPageChange={setPage}\n * />\n * \n * @example\n * // Outlined 스타일, 원형 버튼 / Outlined style, circular buttons\n * <Pagination\n * currentPage={page}\n * totalPages={20}\n * onPageChange={setPage}\n * variant=\"outlined\"\n * shape=\"circle\"\n * />\n * \n * @param {PaginationProps} props - Pagination 컴포넌트의 props / Pagination component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} Pagination 컴포넌트 / Pagination component\n */\nconst Pagination = React.forwardRef<HTMLDivElement, PaginationProps>(\n ({ \n className, \n currentPage,\n totalPages,\n onPageChange,\n showFirstLast = true,\n showPrevNext = true,\n maxVisiblePages = 5,\n size = \"md\",\n variant = \"default\",\n shape = \"square\",\n ...props \n }, ref) => {\n const getVisiblePages = () => {\n const pages: (number | string)[] = []\n const halfVisible = Math.floor(maxVisiblePages / 2)\n \n let start = Math.max(1, currentPage - halfVisible)\n let end = Math.min(totalPages, currentPage + halfVisible)\n \n // 조정\n if (end - start + 1 < maxVisiblePages) {\n if (start === 1) {\n end = Math.min(totalPages, start + maxVisiblePages - 1)\n } else {\n start = Math.max(1, end - maxVisiblePages + 1)\n }\n }\n \n // 첫 페이지\n if (start > 1) {\n pages.push(1)\n if (start > 2) {\n pages.push(\"...\")\n }\n }\n \n // 중간 페이지들\n for (let i = start; i <= end; i++) {\n pages.push(i)\n }\n \n // 마지막 페이지\n if (end < totalPages) {\n if (end < totalPages - 1) {\n pages.push(\"...\")\n }\n pages.push(totalPages)\n }\n \n return pages\n }\n\n const getSizeClasses = () => {\n switch (size) {\n case \"sm\":\n return \"h-8 px-2 text-sm\" // 32px 높이, 8px 패딩\n case \"lg\":\n return \"h-12 px-4 text-base\" // 48px 높이, 16px 패딩\n default:\n return \"h-10 px-3 text-sm\" // 40px 높이, 12px 패딩\n }\n }\n\n const getShapeClasses = () => {\n switch (shape) {\n case \"circle\":\n return \"rounded-full aspect-square flex items-center justify-center\"\n default:\n return \"rounded-md\"\n }\n }\n\n const getVariantClasses = (isActive: boolean = false) => {\n switch (variant) {\n case \"outlined\":\n return merge(\n \"border border-border\",\n isActive\n ? \"bg-primary border-primary text-primary-foreground\"\n : \"bg-background text-foreground hover:bg-muted\"\n )\n case \"minimal\":\n return merge(\n \"border-0\",\n isActive\n ? \"bg-primary/10 text-primary\"\n : \"bg-transparent text-foreground hover:bg-muted\"\n )\n default:\n return merge(\n \"border-0\",\n isActive\n ? \"bg-primary text-primary-foreground\"\n : \"bg-background text-foreground hover:bg-muted\"\n )\n }\n }\n\n const handlePageClick = (page: number) => {\n if (page >= 1 && page <= totalPages && page !== currentPage) {\n onPageChange(page)\n }\n }\n\n const visiblePages = getVisiblePages()\n\n return (\n <div\n ref={ref}\n className={merge(\n \"flex items-center justify-center gap-1\",\n className\n )}\n {...props}\n >\n {/* 첫 페이지 버튼 */}\n {showFirstLast && currentPage > 1 && (\n <button\n onClick={() => handlePageClick(1)}\n className={merge(\n \"inline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n getSizeClasses(),\n getShapeClasses(),\n getVariantClasses()\n )}\n aria-label=\"첫 페이지로 이동\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M11 19l-7-7 7-7M19 19l-7-7 7-7\" />\n </svg>\n </button>\n )}\n\n {/* 이전 페이지 버튼 */}\n {showPrevNext && currentPage > 1 && (\n <button\n onClick={() => handlePageClick(currentPage - 1)}\n className={merge(\n \"inline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n getSizeClasses(),\n getShapeClasses(),\n getVariantClasses()\n )}\n aria-label=\"이전 페이지로 이동\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n )}\n\n {/* 페이지 번호들 */}\n {visiblePages.map((page, index) => (\n <React.Fragment key={index}>\n {page === \"...\" ? (\n <span className={merge(\n \"inline-flex items-center justify-center px-3 py-2 text-sm font-medium text-muted-foreground\",\n getSizeClasses()\n )}>\n ...\n </span>\n ) : (\n <button\n onClick={() => handlePageClick(page as number)}\n className={merge(\n \"inline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n getSizeClasses(),\n getShapeClasses(),\n getVariantClasses(page === currentPage)\n )}\n aria-label={`${page}페이지로 이동`}\n aria-current={page === currentPage ? \"page\" : undefined}\n >\n {page}\n </button>\n )}\n </React.Fragment>\n ))}\n\n {/* 다음 페이지 버튼 */}\n {showPrevNext && currentPage < totalPages && (\n <button\n onClick={() => handlePageClick(currentPage + 1)}\n className={merge(\n \"inline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n getSizeClasses(),\n getShapeClasses(),\n getVariantClasses()\n )}\n aria-label=\"다음 페이지로 이동\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n )}\n\n {/* 마지막 페이지 버튼 */}\n {showFirstLast && currentPage < totalPages && (\n <button\n onClick={() => handlePageClick(totalPages)}\n className={merge(\n \"inline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n getSizeClasses(),\n getShapeClasses(),\n getVariantClasses()\n )}\n aria-label=\"마지막 페이지로 이동\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M13 5l7 7-7 7M5 5l7 7-7 7\" />\n </svg>\n </button>\n )}\n </div>\n )\n }\n)\nPagination.displayName = \"Pagination\"\n\n// 편의 컴포넌트들\nexport const PaginationOutlined = React.forwardRef<HTMLDivElement, Omit<PaginationProps, \"variant\">>(\n ({ className, ...props }, ref) => (\n <Pagination ref={ref} variant=\"outlined\" className={className} {...props} />\n )\n)\nPaginationOutlined.displayName = \"PaginationOutlined\"\n\nexport const PaginationMinimal = React.forwardRef<HTMLDivElement, Omit<PaginationProps, \"variant\">>(\n ({ className, ...props }, ref) => (\n <Pagination ref={ref} variant=\"minimal\" className={className} {...props} />\n )\n)\nPaginationMinimal.displayName = \"PaginationMinimal\"\n\n// 복합 컴포넌트들\nexport const PaginationWithInfo = React.forwardRef<HTMLDivElement, PaginationProps & { \n totalItems?: number\n itemsPerPage?: number\n showInfo?: boolean\n}>(\n ({ \n totalItems = 0, \n itemsPerPage = 10, \n showInfo = true, \n className, \n ...props \n }, ref) => {\n const startItem = (props.currentPage - 1) * itemsPerPage + 1\n const endItem = Math.min(props.currentPage * itemsPerPage, totalItems)\n \n return (\n <div className={merge(\"flex flex-col sm:flex-row items-center justify-between gap-4\", className)}>\n {showInfo && (\n <div className=\"text-sm text-foreground\">\n {totalItems > 0 ? (\n <>\n <span className=\"font-medium\">{startItem}</span>\n {\" - \"}\n <span className=\"font-medium\">{endItem}</span>\n {\" of \"}\n <span className=\"font-medium\">{totalItems}</span>\n {\" results\"}\n </>\n ) : (\n \"No results\"\n )}\n </div>\n )}\n <Pagination ref={ref} {...props} />\n </div>\n )\n }\n)\nPaginationWithInfo.displayName = \"PaginationWithInfo\"\n\nexport { Pagination } ","\"use client\"\n\nimport React from \"react\"\nimport { merge } from \"../lib/utils\"\nimport { Icon } from \"./Icon\"\n\n/**\n * PageNavigation 컴포넌트의 props / PageNavigation component props\n * @typedef {Object} PageNavigationProps\n * @property {Object} [prevPage] - 이전 페이지 정보 / Previous page information\n * @property {string} prevPage.title - 이전 페이지 제목 / Previous page title\n * @property {string} prevPage.href - 이전 페이지 링크 / Previous page link\n * @property {Object} [nextPage] - 다음 페이지 정보 / Next page information\n * @property {string} nextPage.title - 다음 페이지 제목 / Next page title\n * @property {string} nextPage.href - 다음 페이지 링크 / Next page link\n * @property {boolean} [showOnMobile=false] - 모바일에서 표시 여부 / Show on mobile\n * @extends {React.HTMLAttributes<HTMLDivElement>}\n */\nexport interface PageNavigationProps extends React.HTMLAttributes<HTMLDivElement> {\n prevPage?: {\n title: string\n href: string\n }\n nextPage?: {\n title: string\n href: string\n }\n showOnMobile?: boolean\n}\n\n/**\n * PageNavigation 컴포넌트 / PageNavigation component\n * \n * 이전/다음 페이지로 이동하는 네비게이션 컴포넌트입니다.\n * 문서 페이지나 가이드 페이지에서 사용하기 적합합니다.\n * \n * Navigation component for moving to previous/next pages.\n * Suitable for documentation or guide pages.\n * \n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <PageNavigation\n * prevPage={{ title: \"이전 페이지\", href: \"/prev\" }}\n * nextPage={{ title: \"다음 페이지\", href: \"/next\" }}\n * />\n * \n * @param {PageNavigationProps} props - PageNavigation 컴포넌트의 props / PageNavigation component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} PageNavigation 컴포넌트 / PageNavigation component\n */\nconst PageNavigation = React.forwardRef<HTMLDivElement, PageNavigationProps>(\n ({ \n className, \n prevPage, \n nextPage, \n showOnMobile = false,\n ...props \n }, ref) => {\n if (!prevPage && !nextPage) {\n return null\n }\n\n return (\n <div\n ref={ref}\n className={merge(\n \"flex items-center justify-between py-4\",\n !showOnMobile && \"hidden md:flex\",\n className\n )}\n {...props}\n >\n {/* 이전 페이지 */}\n <div className=\"flex-1\">\n {prevPage && (\n <a\n href={prevPage.href}\n className=\"group inline-flex items-center text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n <Icon \n name=\"chevronLeft\" \n className=\"w-4 h-4 mr-2 transition-transform group-hover:-translate-x-1\" \n />\n <span className=\"hidden sm:inline\">{prevPage.title}</span>\n </a>\n )}\n </div>\n\n {/* 다음 페이지 */}\n <div className=\"flex-1 flex justify-end\">\n {nextPage && (\n <a\n href={nextPage.href}\n className=\"group inline-flex items-center text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n <span className=\"hidden sm:inline mr-2\">{nextPage.title}</span>\n <Icon \n name=\"chevronRight\" \n className=\"w-4 h-4 transition-transform group-hover:translate-x-1\" \n />\n </a>\n )}\n </div>\n </div>\n )\n }\n)\nPageNavigation.displayName = \"PageNavigation\"\n\nexport { PageNavigation } ","'use client'\n\nimport React, { useState, useEffect } from 'react'\nimport { merge } from '../lib/utils'\nimport { LoadingSpinner } from './LoadingSpinner'\n\n/**\n * PageTransition 컴포넌트의 props / PageTransition component props\n * @typedef {Object} PageTransitionProps\n * @property {React.ReactNode} children - 페이지 내용 / Page content\n * @property {string} [className] - 추가 CSS 클래스 / Additional CSS class\n * @property {number} [duration=300] - 전환 지속 시간 (ms) / Transition duration (ms)\n * @property {'fade' | 'slide' | 'scale' | 'flip'} [variant='fade'] - 전환 애니메이션 타입 / Transition animation type\n * @property {'default' | 'dots' | 'bars' | 'ring' | 'ripple'} [loadingVariant='ripple'] - 로딩 스피너 타입 / Loading spinner type\n * @property {string} [loadingText='페이지 로딩 중...'] - 로딩 텍스트 / Loading text\n * @property {boolean} [showLoading=true] - 로딩 표시 여부 / Show loading\n * @property {() => void} [onTransitionStart] - 전환 시작 콜백 / Transition start callback\n * @property {() => void} [onTransitionEnd] - 전환 종료 콜백 / Transition end callback\n */\nexport interface PageTransitionProps {\n children: React.ReactNode\n className?: string\n duration?: number\n variant?: 'fade' | 'slide' | 'scale' | 'flip'\n loadingVariant?: 'default' | 'dots' | 'bars' | 'ring' | 'ripple'\n loadingText?: string\n showLoading?: boolean\n onTransitionStart?: () => void\n onTransitionEnd?: () => void\n}\n\n/**\n * PageTransition 컴포넌트 / PageTransition component\n * \n * 페이지 전환 애니메이션을 제공하는 컴포넌트입니다.\n * 다양한 전환 효과와 로딩 스피너를 지원합니다.\n * \n * Component that provides page transition animations.\n * Supports various transition effects and loading spinners.\n * \n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <PageTransition>\n * <div>페이지 내용</div>\n * </PageTransition>\n * \n * @example\n * // Slide 전환 / Slide transition\n * <PageTransition\n * variant=\"slide\"\n * duration={500}\n * loadingVariant=\"dots\"\n * >\n * <div>페이지 내용</div>\n * </PageTransition>\n * \n * @param {PageTransitionProps} props - PageTransition 컴포넌트의 props / PageTransition component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} PageTransition 컴포넌트 / PageTransition component\n */\nexport const PageTransition = React.forwardRef<HTMLDivElement, PageTransitionProps>(({\n children,\n className,\n duration = 300,\n variant = 'fade',\n loadingVariant = 'ripple',\n loadingText = '페이지 로딩 중...',\n showLoading = true,\n onTransitionStart,\n onTransitionEnd\n}, ref) => {\n const [isLoading, setIsLoading] = useState(true)\n const [isVisible, setIsVisible] = useState(false)\n\n useEffect(() => {\n const timer = setTimeout(() => {\n setIsLoading(false)\n setIsVisible(true)\n onTransitionEnd?.()\n }, duration)\n\n onTransitionStart?.()\n\n return () => clearTimeout(timer)\n }, [duration, onTransitionStart, onTransitionEnd])\n\n const transitionClasses = {\n fade: merge(\n 'transition-opacity duration-300 ease-in-out',\n isVisible ? 'opacity-100' : 'opacity-0'\n ),\n slide: merge(\n 'transition-transform duration-300 ease-in-out',\n isVisible ? 'translate-x-0' : 'translate-x-full'\n ),\n scale: merge(\n 'transition-all duration-300 ease-in-out',\n isVisible ? 'scale-100 opacity-100' : 'scale-95 opacity-0'\n ),\n flip: merge(\n 'transition-all duration-500 ease-in-out',\n isVisible ? 'rotate-y-0 opacity-100' : 'rotate-y-90 opacity-0'\n )\n }\n\n if (isLoading && showLoading) {\n return (\n <div className={merge('flex flex-col items-center justify-center min-h-screen bg-gradient-to-br from-indigo-50 to-purple-50 dark:from-slate-900 dark:to-slate-800', className)}>\n <LoadingSpinner\n size=\"lg\"\n variant={loadingVariant}\n text={loadingText}\n />\n </div>\n )\n }\n\n return (\n <div\n ref={ref}\n className={merge(\n 'w-full',\n transitionClasses[variant],\n className\n )}\n style={{ transitionDuration: `${duration}ms` }}\n >\n {children}\n </div>\n )\n})\n\nPageTransition.displayName = 'PageTransition'\n\n// Convenience components for different transition types\nexport const FadeTransition = React.forwardRef<HTMLDivElement, Omit<PageTransitionProps, 'variant'>>((props, ref) => (\n <PageTransition ref={ref} variant=\"fade\" {...props} />\n))\n\nexport const SlideTransition = React.forwardRef<HTMLDivElement, Omit<PageTransitionProps, 'variant'>>((props, ref) => (\n <PageTransition ref={ref} variant=\"slide\" {...props} />\n))\n\nexport const ScaleTransition = React.forwardRef<HTMLDivElement, Omit<PageTransitionProps, 'variant'>>((props, ref) => (\n <PageTransition ref={ref} variant=\"scale\" {...props} />\n))\n\nexport const FlipTransition = React.forwardRef<HTMLDivElement, Omit<PageTransitionProps, 'variant'>>((props, ref) => (\n <PageTransition ref={ref} variant=\"flip\" {...props} />\n))\n\n// Add displayName for convenience components\nFadeTransition.displayName = 'FadeTransition'\nSlideTransition.displayName = 'SlideTransition'\nScaleTransition.displayName = 'ScaleTransition'\nFlipTransition.displayName = 'FlipTransition' "]}
1
+ {"version":3,"sources":["../src/components/Navigation.tsx","../src/components/Pagination.tsx","../src/components/PageNavigation.tsx","../src/components/PageTransition.tsx"],"names":["Navigation","React","className","value","defaultValue","onValueChange","variant","scale","children","props","ref","activeTab","setActiveTab","isControlled","currentValue","jsx","merge","child","NavigationList","_onValueChange","getStyleClasses","getScaleClasses","NavigationItem","active","handleClick","NavigationContent","NavigationComponent","Pagination","currentPage","totalPages","onPageChange","showFirstLast","showPrevNext","maxVisiblePages","size","shape","getVisiblePages","pages","halfVisible","start","end","i","getSizeClasses","getShapeClasses","getVariantClasses","isActive","handlePageClick","page","visiblePages","jsxs","index","PaginationOutlined","PaginationMinimal","PaginationWithInfo","totalItems","itemsPerPage","showInfo","startItem","endItem","Fragment","PageNavigation","prevPage","nextPage","showOnMobile","Icon","PageTransition","duration","loadingVariant","loadingText","showLoading","onTransitionStart","onTransitionEnd","isLoading","setIsLoading","useState","isVisible","setIsVisible","useEffect","timer","transitionClasses","LoadingSpinner","FadeTransition","SlideTransition","ScaleTransition","FlipTransition"],"mappings":"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","file":"navigation.mjs","sourcesContent":["\"use client\"\n\nimport React from \"react\"\nimport { merge } from \"../lib/utils\"\n\n/**\n * Navigation 컴포넌트의 props / Navigation component props\n * @typedef {Object} NavigationProps\n * @property {string} [value] - 제어 모드에서 활성 탭 값 / Active tab value in controlled mode\n * @property {string} [defaultValue] - 비제어 모드에서 기본 활성 탭 값 / Default active tab value in uncontrolled mode\n * @property {(value: string) => void} [onValueChange] - 탭 변경 콜백 / Tab change callback\n * @property {\"pills\" | \"underline\" | \"cards\"} [variant=\"pills\"] - Navigation 스타일 변형 / Navigation style variant\n * @property {\"small\" | \"medium\" | \"large\"} [scale=\"medium\"] - Navigation 크기 / Navigation size\n * @extends {Omit<React.HTMLAttributes<HTMLDivElement>, 'style'>}\n */\nexport interface NavigationProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'style'> {\n value?: string\n defaultValue?: string\n onValueChange?: (value: string) => void\n variant?: \"pills\" | \"underline\" | \"cards\"\n scale?: \"small\" | \"medium\" | \"large\"\n}\n\n/**\n * Navigation 컴포넌트 / Navigation component\n * \n * 탭 네비게이션 컴포넌트입니다.\n * NavigationList, NavigationItem, NavigationContent와 함께 사용합니다.\n * \n * Tab navigation component.\n * Used with NavigationList, NavigationItem, and NavigationContent.\n * \n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <Navigation>\n * <Navigation.List>\n * <Navigation.Item value=\"tab1\">탭 1</Navigation.Item>\n * <Navigation.Item value=\"tab2\">탭 2</Navigation.Item>\n * </Navigation.List>\n * <Navigation.Content value=\"tab1\">내용 1</Navigation.Content>\n * </Navigation>\n * \n * @param {NavigationProps} props - Navigation 컴포넌트의 props / Navigation component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} Navigation 컴포넌트 / Navigation component\n */\nconst Navigation = React.forwardRef<HTMLDivElement, NavigationProps>(\n ({ \n className, \n value,\n defaultValue,\n onValueChange,\n variant = \"pills\",\n scale = \"medium\",\n children,\n ...props \n }, ref) => {\n const [activeTab, setActiveTab] = React.useState(value || defaultValue || \"\")\n const isControlled = value !== undefined\n const currentValue = isControlled ? value : activeTab\n\n const _handleTabChange = (newValue: string) => {\n if (!isControlled) {\n setActiveTab(newValue)\n }\n onValueChange?.(newValue)\n }\n\n React.useEffect(() => {\n if (value !== undefined) {\n setActiveTab(value)\n }\n }, [value])\n\n return (\n <div\n ref={ref}\n className={merge(\n \"w-full\",\n className\n )}\n {...props}\n >\n {React.Children.map(children, (child) => {\n if (React.isValidElement(child)) {\n return React.cloneElement(child, {\n value: currentValue,\n variant,\n scale\n } as Partial<NavigationListProps | NavigationItemProps>)\n }\n return child\n })}\n </div>\n )\n }\n)\nNavigation.displayName = \"Navigation\"\n\n/**\n * NavigationList 컴포넌트의 props / NavigationList component props\n * @typedef {Object} NavigationListProps\n * @property {string} [value] - 활성 탭 값 / Active tab value\n * @property {(value: string) => void} [onValueChange] - 탭 변경 콜백 / Tab change callback\n * @property {\"pills\" | \"underline\" | \"cards\"} [variant=\"pills\"] - Navigation 스타일 변형 / Navigation style variant\n * @property {\"small\" | \"medium\" | \"large\"} [scale=\"medium\"] - Navigation 크기 / Navigation size\n * @extends {Omit<React.HTMLAttributes<HTMLDivElement>, 'style'>}\n */\nexport interface NavigationListProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'style'> {\n value?: string\n onValueChange?: (value: string) => void\n variant?: \"pills\" | \"underline\" | \"cards\"\n scale?: \"small\" | \"medium\" | \"large\"\n}\n\nconst NavigationList = React.forwardRef<HTMLDivElement, NavigationListProps>(\n ({\n className,\n value,\n onValueChange: _onValueChange,\n variant = \"pills\",\n scale = \"medium\",\n children,\n ...props\n }, ref) => {\n const getStyleClasses = () => {\n switch (variant) {\n case \"pills\":\n return \"bg-muted p-1 rounded-xl\"\n case \"underline\":\n return \"border-b border-border\"\n case \"cards\":\n return \"bg-muted/50 p-1 rounded-xl\"\n default:\n return \"bg-muted p-1 rounded-xl\"\n }\n }\n\n const getScaleClasses = () => {\n switch (scale) {\n case \"small\":\n return \"gap-1\"\n case \"large\":\n return \"gap-3\"\n default:\n return \"gap-2\"\n }\n }\n\n return (\n <div\n ref={ref}\n className={merge(\n \"flex\",\n getStyleClasses(),\n getScaleClasses(),\n className\n )}\n {...props}\n >\n {React.Children.map(children, (child) => {\n if (React.isValidElement(child)) {\n return React.cloneElement(child, {\n value,\n variant,\n scale\n } as Partial<NavigationItemProps>)\n }\n return child\n })}\n </div>\n )\n }\n)\nNavigationList.displayName = \"NavigationList\"\n\n/**\n * NavigationItem 컴포넌트의 props / NavigationItem component props\n * @typedef {Object} NavigationItemProps\n * @property {string} value - 탭 값 / Tab value\n * @property {(value: string) => void} [onValueChange] - 탭 변경 콜백 / Tab change callback\n * @property {\"pills\" | \"underline\" | \"cards\"} [variant] - Navigation 스타일 변형 (자동으로 설정됨) / Navigation style variant (auto-set)\n * @property {\"small\" | \"medium\" | \"large\"} [scale] - Navigation 크기 (자동으로 설정됨) / Navigation size (auto-set)\n * @property {boolean} [active] - 활성 상태 (자동으로 설정됨) / Active state (auto-set)\n * @extends {Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'style'>}\n */\nexport interface NavigationItemProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'style'> {\n value: string\n onValueChange?: (value: string) => void\n variant?: \"pills\" | \"underline\" | \"cards\"\n scale?: \"small\" | \"medium\" | \"large\"\n active?: boolean\n}\n\nconst NavigationItem = React.forwardRef<HTMLButtonElement, NavigationItemProps>(\n ({ \n className, \n value,\n onValueChange,\n variant = \"pills\",\n scale = \"medium\",\n active = false,\n children,\n ...props \n }, ref) => {\n const getStyleClasses = () => {\n switch (variant) {\n case \"pills\":\n return merge(\n \"rounded-lg px-3 py-2 text-sm font-medium transition-all\",\n active\n ? \"bg-background text-foreground shadow-sm\"\n : \"text-muted-foreground hover:text-foreground\"\n )\n case \"underline\":\n return merge(\n \"border-b-2 px-3 py-2 text-sm font-medium transition-all\",\n active\n ? \"border-primary text-primary\"\n : \"border-transparent text-muted-foreground hover:text-foreground\"\n )\n case \"cards\":\n return merge(\n \"rounded-lg px-3 py-2 text-sm font-medium transition-all\",\n active\n ? \"bg-background text-foreground shadow-sm border border-border\"\n : \"text-muted-foreground hover:text-foreground\"\n )\n default:\n return merge(\n \"rounded-lg px-3 py-2 text-sm font-medium transition-all\",\n active\n ? \"bg-background text-foreground shadow-sm\"\n : \"text-muted-foreground hover:text-foreground\"\n )\n }\n }\n\n const getScaleClasses = () => {\n switch (scale) {\n case \"small\":\n return \"text-xs px-2 py-1\"\n case \"large\":\n return \"text-base px-4 py-3\"\n default:\n return \"text-sm px-3 py-2\"\n }\n }\n\n const handleClick = () => {\n onValueChange?.(value)\n }\n\n return (\n <button\n ref={ref}\n className={merge(\n getStyleClasses(),\n getScaleClasses(),\n \"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2\",\n className\n )}\n onClick={handleClick}\n {...props}\n >\n {children}\n </button>\n )\n }\n)\nNavigationItem.displayName = \"NavigationItem\"\n\n/**\n * NavigationContent 컴포넌트의 props / NavigationContent component props\n * @typedef {Object} NavigationContentProps\n * @property {string} value - 탭 값 / Tab value\n * @property {boolean} [active] - 활성 상태 (자동으로 설정됨) / Active state (auto-set)\n * @extends {React.HTMLAttributes<HTMLDivElement>}\n */\nexport interface NavigationContentProps extends React.HTMLAttributes<HTMLDivElement> {\n value: string\n active?: boolean\n}\n\nconst NavigationContent = React.forwardRef<HTMLDivElement, NavigationContentProps>(\n ({ className, active = false, ...props }, ref) => {\n if (!active) return null\n\n return (\n <div\n ref={ref}\n className={merge(\"mt-4\", className)}\n {...props}\n />\n )\n }\n)\nNavigationContent.displayName = \"NavigationContent\"\n\n// 서브컴포넌트 타입 정의\nexport interface NavigationComponent extends React.ForwardRefExoticComponent<NavigationProps & React.RefAttributes<HTMLDivElement>> {\n List: typeof NavigationList\n Item: typeof NavigationItem\n Content: typeof NavigationContent\n}\n\nconst NavigationComponent = Navigation as NavigationComponent\nNavigationComponent.List = NavigationList\nNavigationComponent.Item = NavigationItem\nNavigationComponent.Content = NavigationContent\n\nexport { NavigationComponent as Navigation, NavigationList, NavigationItem, NavigationContent } ","\"use client\"\n\nimport React from \"react\"\nimport { merge } from \"../lib/utils\"\n\n/**\n * Pagination 컴포넌트의 props / Pagination component props\n * @typedef {Object} PaginationProps\n * @property {number} currentPage - 현재 페이지 번호 / Current page number\n * @property {number} totalPages - 전체 페이지 수 / Total number of pages\n * @property {(page: number) => void} onPageChange - 페이지 변경 콜백 / Page change callback\n * @property {boolean} [showFirstLast=true] - 첫/마지막 페이지 버튼 표시 여부 / Show first/last page buttons\n * @property {boolean} [showPrevNext=true] - 이전/다음 페이지 버튼 표시 여부 / Show previous/next page buttons\n * @property {number} [maxVisiblePages=5] - 최대 표시 페이지 수 / Maximum visible page numbers\n * @property {\"sm\" | \"md\" | \"lg\"} [size=\"md\"] - Pagination 크기 / Pagination size\n * @property {\"default\" | \"outlined\" | \"minimal\"} [variant=\"default\"] - Pagination 스타일 변형 / Pagination style variant\n * @property {\"square\" | \"circle\"} [shape=\"square\"] - 버튼 모양 / Button shape\n * @extends {React.HTMLAttributes<HTMLDivElement>}\n */\nexport interface PaginationProps extends React.HTMLAttributes<HTMLDivElement> {\n currentPage: number\n totalPages: number\n onPageChange: (page: number) => void\n showFirstLast?: boolean\n showPrevNext?: boolean\n maxVisiblePages?: number\n size?: \"sm\" | \"md\" | \"lg\"\n variant?: \"default\" | \"outlined\" | \"minimal\"\n shape?: \"square\" | \"circle\"\n}\n\n/**\n * Pagination 컴포넌트 / Pagination component\n * \n * 페이지네이션 컨트롤을 제공하는 컴포넌트입니다.\n * 첫/마지막 페이지, 이전/다음 페이지 버튼을 지원하며,\n * 많은 페이지가 있을 경우 자동으로 생략 표시(...)를 합니다.\n * \n * Component that provides pagination controls.\n * Supports first/last page and previous/next page buttons,\n * and automatically shows ellipsis (...) when there are many pages.\n * \n * @component\n * @example\n * // 기본 사용 / Basic usage\n * const [page, setPage] = useState(1)\n * \n * <Pagination\n * currentPage={page}\n * totalPages={10}\n * onPageChange={setPage}\n * />\n * \n * @example\n * // Outlined 스타일, 원형 버튼 / Outlined style, circular buttons\n * <Pagination\n * currentPage={page}\n * totalPages={20}\n * onPageChange={setPage}\n * variant=\"outlined\"\n * shape=\"circle\"\n * />\n * \n * @param {PaginationProps} props - Pagination 컴포넌트의 props / Pagination component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} Pagination 컴포넌트 / Pagination component\n */\nconst Pagination = React.forwardRef<HTMLDivElement, PaginationProps>(\n ({ \n className, \n currentPage,\n totalPages,\n onPageChange,\n showFirstLast = true,\n showPrevNext = true,\n maxVisiblePages = 5,\n size = \"md\",\n variant = \"default\",\n shape = \"square\",\n ...props \n }, ref) => {\n const getVisiblePages = () => {\n const pages: (number | string)[] = []\n const halfVisible = Math.floor(maxVisiblePages / 2)\n \n let start = Math.max(1, currentPage - halfVisible)\n let end = Math.min(totalPages, currentPage + halfVisible)\n \n // 조정\n if (end - start + 1 < maxVisiblePages) {\n if (start === 1) {\n end = Math.min(totalPages, start + maxVisiblePages - 1)\n } else {\n start = Math.max(1, end - maxVisiblePages + 1)\n }\n }\n \n // 첫 페이지\n if (start > 1) {\n pages.push(1)\n if (start > 2) {\n pages.push(\"...\")\n }\n }\n \n // 중간 페이지들\n for (let i = start; i <= end; i++) {\n pages.push(i)\n }\n \n // 마지막 페이지\n if (end < totalPages) {\n if (end < totalPages - 1) {\n pages.push(\"...\")\n }\n pages.push(totalPages)\n }\n \n return pages\n }\n\n const getSizeClasses = () => {\n switch (size) {\n case \"sm\":\n return \"h-8 px-2 text-sm\" // 32px 높이, 8px 패딩\n case \"lg\":\n return \"h-12 px-4 text-base\" // 48px 높이, 16px 패딩\n default:\n return \"h-10 px-3 text-sm\" // 40px 높이, 12px 패딩\n }\n }\n\n const getShapeClasses = () => {\n switch (shape) {\n case \"circle\":\n return \"rounded-full aspect-square flex items-center justify-center\"\n default:\n return \"rounded-md\"\n }\n }\n\n const getVariantClasses = (isActive: boolean = false) => {\n switch (variant) {\n case \"outlined\":\n return merge(\n \"border border-border\",\n isActive\n ? \"bg-primary border-primary text-primary-foreground\"\n : \"bg-background text-foreground hover:bg-muted\"\n )\n case \"minimal\":\n return merge(\n \"border-0\",\n isActive\n ? \"bg-primary/10 text-primary\"\n : \"bg-transparent text-foreground hover:bg-muted\"\n )\n default:\n return merge(\n \"border-0\",\n isActive\n ? \"bg-primary text-primary-foreground\"\n : \"bg-background text-foreground hover:bg-muted\"\n )\n }\n }\n\n const handlePageClick = (page: number) => {\n if (page >= 1 && page <= totalPages && page !== currentPage) {\n onPageChange(page)\n }\n }\n\n const visiblePages = getVisiblePages()\n\n return (\n <div\n ref={ref}\n className={merge(\n \"flex items-center justify-center gap-1\",\n className\n )}\n {...props}\n >\n {/* 첫 페이지 버튼 */}\n {showFirstLast && currentPage > 1 && (\n <button\n onClick={() => handlePageClick(1)}\n className={merge(\n \"inline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n getSizeClasses(),\n getShapeClasses(),\n getVariantClasses()\n )}\n aria-label=\"첫 페이지로 이동\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M11 19l-7-7 7-7M19 19l-7-7 7-7\" />\n </svg>\n </button>\n )}\n\n {/* 이전 페이지 버튼 */}\n {showPrevNext && currentPage > 1 && (\n <button\n onClick={() => handlePageClick(currentPage - 1)}\n className={merge(\n \"inline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n getSizeClasses(),\n getShapeClasses(),\n getVariantClasses()\n )}\n aria-label=\"이전 페이지로 이동\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M15 19l-7-7 7-7\" />\n </svg>\n </button>\n )}\n\n {/* 페이지 번호들 */}\n {visiblePages.map((page, index) => (\n <React.Fragment key={index}>\n {page === \"...\" ? (\n <span className={merge(\n \"inline-flex items-center justify-center px-3 py-2 text-sm font-medium text-muted-foreground\",\n getSizeClasses()\n )}>\n ...\n </span>\n ) : (\n <button\n onClick={() => handlePageClick(page as number)}\n className={merge(\n \"inline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n getSizeClasses(),\n getShapeClasses(),\n getVariantClasses(page === currentPage)\n )}\n aria-label={`${page}페이지로 이동`}\n aria-current={page === currentPage ? \"page\" : undefined}\n >\n {page}\n </button>\n )}\n </React.Fragment>\n ))}\n\n {/* 다음 페이지 버튼 */}\n {showPrevNext && currentPage < totalPages && (\n <button\n onClick={() => handlePageClick(currentPage + 1)}\n className={merge(\n \"inline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n getSizeClasses(),\n getShapeClasses(),\n getVariantClasses()\n )}\n aria-label=\"다음 페이지로 이동\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n )}\n\n {/* 마지막 페이지 버튼 */}\n {showFirstLast && currentPage < totalPages && (\n <button\n onClick={() => handlePageClick(totalPages)}\n className={merge(\n \"inline-flex items-center justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50\",\n getSizeClasses(),\n getShapeClasses(),\n getVariantClasses()\n )}\n aria-label=\"마지막 페이지로 이동\"\n >\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M13 5l7 7-7 7M5 5l7 7-7 7\" />\n </svg>\n </button>\n )}\n </div>\n )\n }\n)\nPagination.displayName = \"Pagination\"\n\n// 편의 컴포넌트들\nexport const PaginationOutlined = React.forwardRef<HTMLDivElement, Omit<PaginationProps, \"variant\">>(\n ({ className, ...props }, ref) => (\n <Pagination ref={ref} variant=\"outlined\" className={className} {...props} />\n )\n)\nPaginationOutlined.displayName = \"PaginationOutlined\"\n\nexport const PaginationMinimal = React.forwardRef<HTMLDivElement, Omit<PaginationProps, \"variant\">>(\n ({ className, ...props }, ref) => (\n <Pagination ref={ref} variant=\"minimal\" className={className} {...props} />\n )\n)\nPaginationMinimal.displayName = \"PaginationMinimal\"\n\n// 복합 컴포넌트들\nexport const PaginationWithInfo = React.forwardRef<HTMLDivElement, PaginationProps & { \n totalItems?: number\n itemsPerPage?: number\n showInfo?: boolean\n}>(\n ({ \n totalItems = 0, \n itemsPerPage = 10, \n showInfo = true, \n className, \n ...props \n }, ref) => {\n const startItem = (props.currentPage - 1) * itemsPerPage + 1\n const endItem = Math.min(props.currentPage * itemsPerPage, totalItems)\n \n return (\n <div className={merge(\"flex flex-col sm:flex-row items-center justify-between gap-4\", className)}>\n {showInfo && (\n <div className=\"text-sm text-foreground\">\n {totalItems > 0 ? (\n <>\n <span className=\"font-medium\">{startItem}</span>\n {\" - \"}\n <span className=\"font-medium\">{endItem}</span>\n {\" of \"}\n <span className=\"font-medium\">{totalItems}</span>\n {\" results\"}\n </>\n ) : (\n \"No results\"\n )}\n </div>\n )}\n <Pagination ref={ref} {...props} />\n </div>\n )\n }\n)\nPaginationWithInfo.displayName = \"PaginationWithInfo\"\n\nexport { Pagination } ","\"use client\"\n\nimport React from \"react\"\nimport { merge } from \"../lib/utils\"\nimport { Icon } from \"./Icon\"\n\n/**\n * PageNavigation 컴포넌트의 props / PageNavigation component props\n * @typedef {Object} PageNavigationProps\n * @property {Object} [prevPage] - 이전 페이지 정보 / Previous page information\n * @property {string} prevPage.title - 이전 페이지 제목 / Previous page title\n * @property {string} prevPage.href - 이전 페이지 링크 / Previous page link\n * @property {Object} [nextPage] - 다음 페이지 정보 / Next page information\n * @property {string} nextPage.title - 다음 페이지 제목 / Next page title\n * @property {string} nextPage.href - 다음 페이지 링크 / Next page link\n * @property {boolean} [showOnMobile=false] - 모바일에서 표시 여부 / Show on mobile\n * @extends {React.HTMLAttributes<HTMLDivElement>}\n */\nexport interface PageNavigationProps extends React.HTMLAttributes<HTMLDivElement> {\n prevPage?: {\n title: string\n href: string\n }\n nextPage?: {\n title: string\n href: string\n }\n showOnMobile?: boolean\n}\n\n/**\n * PageNavigation 컴포넌트 / PageNavigation component\n * \n * 이전/다음 페이지로 이동하는 네비게이션 컴포넌트입니다.\n * 문서 페이지나 가이드 페이지에서 사용하기 적합합니다.\n * \n * Navigation component for moving to previous/next pages.\n * Suitable for documentation or guide pages.\n * \n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <PageNavigation\n * prevPage={{ title: \"이전 페이지\", href: \"/prev\" }}\n * nextPage={{ title: \"다음 페이지\", href: \"/next\" }}\n * />\n * \n * @param {PageNavigationProps} props - PageNavigation 컴포넌트의 props / PageNavigation component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} PageNavigation 컴포넌트 / PageNavigation component\n */\nconst PageNavigation = React.forwardRef<HTMLDivElement, PageNavigationProps>(\n ({ \n className, \n prevPage, \n nextPage, \n showOnMobile = false,\n ...props \n }, ref) => {\n if (!prevPage && !nextPage) {\n return null\n }\n\n return (\n <div\n ref={ref}\n className={merge(\n \"flex items-center justify-between py-4\",\n !showOnMobile && \"hidden md:flex\",\n className\n )}\n {...props}\n >\n {/* 이전 페이지 */}\n <div className=\"flex-1\">\n {prevPage && (\n <a\n href={prevPage.href}\n className=\"group inline-flex items-center text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n <Icon \n name=\"chevronLeft\" \n className=\"w-4 h-4 mr-2 transition-transform group-hover:-translate-x-1\" \n />\n <span className=\"hidden sm:inline\">{prevPage.title}</span>\n </a>\n )}\n </div>\n\n {/* 다음 페이지 */}\n <div className=\"flex-1 flex justify-end\">\n {nextPage && (\n <a\n href={nextPage.href}\n className=\"group inline-flex items-center text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n <span className=\"hidden sm:inline mr-2\">{nextPage.title}</span>\n <Icon \n name=\"chevronRight\" \n className=\"w-4 h-4 transition-transform group-hover:translate-x-1\" \n />\n </a>\n )}\n </div>\n </div>\n )\n }\n)\nPageNavigation.displayName = \"PageNavigation\"\n\nexport { PageNavigation } ","'use client'\n\nimport React, { useState, useEffect } from 'react'\nimport { merge } from '../lib/utils'\nimport { LoadingSpinner } from './LoadingSpinner'\n\n/**\n * PageTransition 컴포넌트의 props / PageTransition component props\n * @typedef {Object} PageTransitionProps\n * @property {React.ReactNode} children - 페이지 내용 / Page content\n * @property {string} [className] - 추가 CSS 클래스 / Additional CSS class\n * @property {number} [duration=300] - 전환 지속 시간 (ms) / Transition duration (ms)\n * @property {'fade' | 'slide' | 'scale' | 'flip'} [variant='fade'] - 전환 애니메이션 타입 / Transition animation type\n * @property {'default' | 'dots' | 'bars' | 'ring' | 'ripple'} [loadingVariant='ripple'] - 로딩 스피너 타입 / Loading spinner type\n * @property {string} [loadingText='페이지 로딩 중...'] - 로딩 텍스트 / Loading text\n * @property {boolean} [showLoading=true] - 로딩 표시 여부 / Show loading\n * @property {() => void} [onTransitionStart] - 전환 시작 콜백 / Transition start callback\n * @property {() => void} [onTransitionEnd] - 전환 종료 콜백 / Transition end callback\n */\nexport interface PageTransitionProps {\n children: React.ReactNode\n className?: string\n duration?: number\n variant?: 'fade' | 'slide' | 'scale' | 'flip'\n loadingVariant?: 'default' | 'dots' | 'bars' | 'ring' | 'ripple'\n loadingText?: string\n showLoading?: boolean\n onTransitionStart?: () => void\n onTransitionEnd?: () => void\n}\n\n/**\n * PageTransition 컴포넌트 / PageTransition component\n * \n * 페이지 전환 애니메이션을 제공하는 컴포넌트입니다.\n * 다양한 전환 효과와 로딩 스피너를 지원합니다.\n * \n * Component that provides page transition animations.\n * Supports various transition effects and loading spinners.\n * \n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <PageTransition>\n * <div>페이지 내용</div>\n * </PageTransition>\n * \n * @example\n * // Slide 전환 / Slide transition\n * <PageTransition\n * variant=\"slide\"\n * duration={500}\n * loadingVariant=\"dots\"\n * >\n * <div>페이지 내용</div>\n * </PageTransition>\n * \n * @param {PageTransitionProps} props - PageTransition 컴포넌트의 props / PageTransition component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} PageTransition 컴포넌트 / PageTransition component\n */\nexport const PageTransition = React.forwardRef<HTMLDivElement, PageTransitionProps>(({\n children,\n className,\n duration = 300,\n variant = 'fade',\n loadingVariant = 'ripple',\n loadingText = '페이지 로딩 중...',\n showLoading = true,\n onTransitionStart,\n onTransitionEnd\n}, ref) => {\n const [isLoading, setIsLoading] = useState(true)\n const [isVisible, setIsVisible] = useState(false)\n\n useEffect(() => {\n const timer = setTimeout(() => {\n setIsLoading(false)\n setIsVisible(true)\n onTransitionEnd?.()\n }, duration)\n\n onTransitionStart?.()\n\n return () => clearTimeout(timer)\n }, [duration, onTransitionStart, onTransitionEnd])\n\n const transitionClasses = {\n fade: merge(\n 'transition-opacity duration-300 ease-in-out',\n isVisible ? 'opacity-100' : 'opacity-0'\n ),\n slide: merge(\n 'transition-transform duration-300 ease-in-out',\n isVisible ? 'translate-x-0' : 'translate-x-full'\n ),\n scale: merge(\n 'transition-all duration-300 ease-in-out',\n isVisible ? 'scale-100 opacity-100' : 'scale-95 opacity-0'\n ),\n flip: merge(\n 'transition-all duration-500 ease-in-out',\n isVisible ? 'rotate-y-0 opacity-100' : 'rotate-y-90 opacity-0'\n )\n }\n\n if (isLoading && showLoading) {\n return (\n <div className={merge('flex flex-col items-center justify-center min-h-screen bg-gradient-to-br from-indigo-50 to-purple-50 dark:from-slate-900 dark:to-slate-800', className)}>\n <LoadingSpinner\n size=\"lg\"\n variant={loadingVariant}\n text={loadingText}\n />\n </div>\n )\n }\n\n return (\n <div\n ref={ref}\n className={merge(\n 'w-full',\n transitionClasses[variant],\n className\n )}\n style={{ transitionDuration: `${duration}ms` }}\n >\n {children}\n </div>\n )\n})\n\nPageTransition.displayName = 'PageTransition'\n\n// Convenience components for different transition types\nexport const FadeTransition = React.forwardRef<HTMLDivElement, Omit<PageTransitionProps, 'variant'>>((props, ref) => (\n <PageTransition ref={ref} variant=\"fade\" {...props} />\n))\n\nexport const SlideTransition = React.forwardRef<HTMLDivElement, Omit<PageTransitionProps, 'variant'>>((props, ref) => (\n <PageTransition ref={ref} variant=\"slide\" {...props} />\n))\n\nexport const ScaleTransition = React.forwardRef<HTMLDivElement, Omit<PageTransitionProps, 'variant'>>((props, ref) => (\n <PageTransition ref={ref} variant=\"scale\" {...props} />\n))\n\nexport const FlipTransition = React.forwardRef<HTMLDivElement, Omit<PageTransitionProps, 'variant'>>((props, ref) => (\n <PageTransition ref={ref} variant=\"flip\" {...props} />\n))\n\n// Add displayName for convenience components\nFadeTransition.displayName = 'FadeTransition'\nSlideTransition.displayName = 'SlideTransition'\nScaleTransition.displayName = 'ScaleTransition'\nFlipTransition.displayName = 'FlipTransition' "]}
@@ -114,6 +114,8 @@ interface PopoverProps extends React.HTMLAttributes<HTMLDivElement> {
114
114
  disabled?: boolean;
115
115
  /** Popover 콘텐츠 영역 추가 클래스 / Additional class for popover content area */
116
116
  contentClassName?: string;
117
+ /** 트리거를 full-width로 렌더링 (DatePicker 등) / Render trigger as full-width */
118
+ fullWidth?: boolean;
117
119
  }
118
120
  /**
119
121
  * Popover 컴포넌트 / Popover component
@@ -151,20 +153,6 @@ declare const Popover: React.ForwardRefExoticComponent<PopoverProps & React.RefA
151
153
  declare const PopoverTrigger: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
152
154
  declare const PopoverContent: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
153
155
 
154
- /**
155
- * Dropdown 컴포넌트의 props / Dropdown component props
156
- * @typedef {Object} DropdownProps
157
- * @property {React.ReactNode} trigger - Dropdown을 열기 위한 트리거 요소 / Trigger element to open dropdown
158
- * @property {React.ReactNode} children - Dropdown 내용 / Dropdown content
159
- * @property {boolean} [open] - 제어 모드에서 열림/닫힘 상태 / Open/close state in controlled mode
160
- * @property {(open: boolean) => void} [onOpenChange] - 상태 변경 콜백 / State change callback
161
- * @property {"top" | "bottom" | "left" | "right"} [placement="bottom"] - Dropdown 표시 위치 / Dropdown display position
162
- * @property {"start" | "center" | "end"} [align="start"] - Dropdown 정렬 / Dropdown alignment
163
- * @property {number} [offset=8] - 트리거와 Dropdown 사이 간격 (px) / Spacing between trigger and dropdown (px)
164
- * @property {boolean} [disabled=false] - Dropdown 비활성화 여부 / Disable dropdown
165
- * @property {boolean} [showArrow=true] - 화살표 표시 여부 / Show arrow
166
- * @extends {React.HTMLAttributes<HTMLDivElement>}
167
- */
168
156
  interface DropdownProps extends React.HTMLAttributes<HTMLDivElement> {
169
157
  trigger: React.ReactNode;
170
158
  children: React.ReactNode;
@@ -176,42 +164,6 @@ interface DropdownProps extends React.HTMLAttributes<HTMLDivElement> {
176
164
  disabled?: boolean;
177
165
  showArrow?: boolean;
178
166
  }
179
- /**
180
- * Dropdown 컴포넌트 / Dropdown component
181
- *
182
- * 트리거 요소를 클릭하면 표시되는 드롭다운 메뉴 컴포넌트입니다.
183
- * 외부 클릭 시 자동으로 닫히며, 뷰포트 경계를 자동으로 감지하여 위치를 조정합니다.
184
- *
185
- * Dropdown menu component that appears when the trigger element is clicked.
186
- * Automatically closes on outside click and adjusts position by detecting viewport boundaries.
187
- *
188
- * @component
189
- * @example
190
- * // 기본 사용 / Basic usage
191
- * <Dropdown trigger={<Button>메뉴</Button>}>
192
- * <Menu>
193
- * <MenuItem>항목 1</MenuItem>
194
- * <MenuItem>항목 2</MenuItem>
195
- * </Menu>
196
- * </Dropdown>
197
- *
198
- * @example
199
- * // 제어 모드, 화살표 없음 / Controlled mode, no arrow
200
- * const [open, setOpen] = useState(false)
201
- * <Dropdown
202
- * open={open}
203
- * onOpenChange={setOpen}
204
- * trigger={<Button>제어 모드</Button>}
205
- * placement="top"
206
- * showArrow={false}
207
- * >
208
- * <div className="p-4">내용</div>
209
- * </Dropdown>
210
- *
211
- * @param {DropdownProps} props - Dropdown 컴포넌트의 props / Dropdown component props
212
- * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref
213
- * @returns {JSX.Element} Dropdown 컴포넌트 / Dropdown component
214
- */
215
167
  declare const Dropdown: React.ForwardRefExoticComponent<DropdownProps & React.RefAttributes<HTMLDivElement>>;
216
168
  interface DropdownItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
217
169
  icon?: React.ReactNode;
package/dist/overlay.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
  "use client";
2
- import {a}from'./chunk-SDFHJ4GB.mjs';export{a as Modal}from'./chunk-SDFHJ4GB.mjs';export{g as Drawer,i as DrawerContent,j as DrawerFooter,h as DrawerHeader,a as Dropdown,f as DropdownGroup,b as DropdownItem,d as DropdownLabel,e as DropdownMenu,c as DropdownSeparator}from'./chunk-QQCELXFD.mjs';export{a as Popover,c as PopoverContent,b as PopoverTrigger}from'./chunk-LPAG7DCA.mjs';import {d}from'./chunk-FFH4ZFKS.mjs';import {l}from'./chunk-HN5LSP6L.mjs';import {a as a$1}from'./chunk-UUHAXGMO.mjs';import o from'react';import {jsx,jsxs}from'react/jsx-runtime';var W=o.forwardRef(({isOpen:s,onClose:r,onConfirm:c,title:d$1,message:a$2,warning:m,confirmText:T="\uD655\uC778",cancelText:D="\uCDE8\uC18C",confirmButtonText:x,type:E="danger",loading:w=false,disabled:g=false,showInput:y=false,inputValue:C="",onInputChange:p,inputPlaceholder:l,inputLabel:v,requiredInputValue:k,showCancel:b=true,size:N="md"},h)=>{let f={danger:{icon:jsx("svg",{className:"h-6 w-6 text-destructive",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"})}),bgColor:"bg-destructive/10",buttonColor:"bg-destructive hover:bg-destructive/90 focus:ring-destructive",textColor:"text-destructive"},warning:{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"})}),bgColor:"bg-yellow-100 dark:bg-yellow-900/20",buttonColor:"bg-yellow-600 hover:bg-yellow-700 focus:ring-yellow-500",textColor:"text-yellow-600 dark:text-yellow-400"},info:{icon:jsx("svg",{className:"h-6 w-6 text-primary",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"})}),bgColor:"bg-primary/10",buttonColor:"bg-primary hover:bg-primary/80 focus:ring-ring",textColor:"text-primary"},success:{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"})}),bgColor:"bg-green-100 dark:bg-green-900/20",buttonColor:"bg-green-600 hover:bg-green-700 focus:ring-green-500",textColor:"text-green-600 dark:text-green-400"},error:{icon:jsx("svg",{className:"h-6 w-6 text-destructive",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})}),bgColor:"bg-destructive/10",buttonColor:"bg-destructive hover:bg-destructive/90 focus:ring-destructive",textColor:"text-destructive"}}[E],M=g||w||!(!y||!k||C===k);return jsx(a,{isOpen:s,onClose:r,closable:false,size:N,children:jsxs("div",{className:"text-center",children:[jsx("div",{className:a$1("mx-auto flex items-center justify-center h-16 w-16 rounded-full mb-6",f.bgColor),children:f.icon}),jsxs("h3",{className:"text-xl font-semibold text-foreground mb-4",children:[" ",d$1]}),jsxs("div",{className:"mb-6",children:[" ",jsx("p",{className:"text-sm text-muted-foreground",children:a$2}),m&&jsx("p",{className:a$1("text-sm mt-3 font-medium",f.textColor),children:m})]}),y&&jsxs("div",{className:"mb-6",children:[" ",jsxs("label",{htmlFor:"confirmInput",className:"block text-sm font-medium text-foreground mb-3 text-left",children:[" ",v]}),jsx("input",{type:"text",id:"confirmInput",value:C,onChange:S=>p==null?void 0:p(S.target.value),placeholder:l,className:"w-full px-4 py-3 border border-input rounded-lg focus:outline-none focus:ring-1 focus:ring-destructive focus:border-transparent bg-background text-foreground transition-colors"})]}),jsxs("div",{className:a$1("flex gap-3","justify-center"),children:[b&&jsx(d,{variant:"outline",onClick:r,disabled:w,className:"px-6 py-3",children:D}),jsx(d,{variant:"default",onClick:c,disabled:M,className:a$1("px-6 py-3",f.buttonColor),children:w?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..."]}):x||T})]})]})})});W.displayName="ConfirmModal";var V=o.forwardRef(({isOpen:s,onClose:r,children:c,className:d,height:a="md",showBackdrop:m=true,backdropClassName:T,closeOnBackdropClick:D=true,closeOnEscape:x=true,showDragHandle:E=true,closable:w=true,snapPoints:g=[25,50,75,100],defaultSnap:y=50,...C},p)=>{let l=s!=null?s:false,v=()=>{r==null||r();},[k,b]=o.useState(false),[N,h]=o.useState(false),[H,f]=o.useState(y),[B,M]=o.useState(false),[S,K]=o.useState(0),[Y,j]=o.useState(0),O={sm:"h-64",md:"h-96",lg:"h-[32rem]",xl:"h-[40rem]",full:"h-full"};o.useEffect(()=>{if(l){b(true),h(true);let t=setTimeout(()=>h(false),50);return ()=>clearTimeout(t)}else {h(true);let t=setTimeout(()=>{b(false),h(false);},300);return ()=>clearTimeout(t)}},[l]),o.useEffect(()=>{if(!x)return;let t=L=>{L.key==="Escape"&&l&&v();};return l&&(document.addEventListener("keydown",t),document.body.style.overflow="hidden"),()=>{document.removeEventListener("keydown",t),document.body.style.overflow="";}},[l,x]);let _=t=>{M(true),K(t.touches[0].clientY),j(t.touches[0].clientY);},$=t=>{B&&j(t.touches[0].clientY);},G=()=>{if(!B)return;M(false);let t=Y-S,L=100;if(t>L)v();else if(t<-L){let q=g.indexOf(H),J=Math.min(q+1,g.length-1);f(g[J]);}};return k?jsxs("div",{className:"fixed inset-0 z-50",children:[m&&jsx("div",{className:a$1("absolute inset-0 bg-black/60 backdrop-blur-md transition-opacity duration-300",N?l?"opacity-100":"opacity-0":"",T),onClick:D?v:void 0}),jsxs("div",{ref:p,className:a$1("absolute bottom-0 left-0 right-0 bg-background/95 backdrop-blur-xl border-t border-border/50 shadow-2xl rounded-t-lg transition-transform duration-300 ease-out pb-safe",a!=="full"?O[a]:"",N?l?"translate-y-0":"translate-y-full":"",d),style:{height:a==="full"?`${H}%`:void 0,maxHeight:a!=="full"?void 0:"100%",transform:B?`translateY(${Y-S}px)`:void 0},onTouchStart:_,onTouchMove:$,onTouchEnd:G,...C,children:[E&&jsx("div",{className:"flex justify-center pt-3 pb-2",children:jsx("div",{className:"w-12 h-1.5 bg-muted-foreground/30 rounded-full"})}),c]})]}):null});V.displayName="BottomSheet";var A=o.forwardRef(({children:s,className:r,showCloseButton:c=true,onClose:d,...a},m)=>jsxs("div",{ref:m,className:a$1("flex items-center justify-between px-6 py-4",r),...a,children:[jsx("div",{className:"flex-1",children:s}),c&&jsx("button",{onClick:d,className:"p-2 rounded-lg hover:bg-muted transition-colors",children:jsx(l,{name:"close",size:20})})]}));A.displayName="BottomSheetHeader";var F=o.forwardRef(({children:s,className:r,...c},d)=>jsx("div",{ref:d,className:a$1("flex-1 px-6 pb-6 overflow-y-auto",r),...c,children:s}));F.displayName="BottomSheetContent";
2
+ import {a}from'./chunk-HBIUCLFL.mjs';export{a as Modal}from'./chunk-HBIUCLFL.mjs';export{g as Drawer,i as DrawerContent,j as DrawerFooter,h as DrawerHeader,a as Dropdown,f as DropdownGroup,b as DropdownItem,d as DropdownLabel,e as DropdownMenu,c as DropdownSeparator}from'./chunk-OIWG3IJ7.mjs';export{a as Popover,c as PopoverContent,b as PopoverTrigger}from'./chunk-ZY23NOT4.mjs';import {d}from'./chunk-O24K56OS.mjs';import'./chunk-SD6XGDAC.mjs';import {l}from'./chunk-ZQUMJQYV.mjs';import {a as a$1}from'./chunk-QEMPERUK.mjs';import'./chunk-EAZEI74V.mjs';import o from'react';import {jsx,jsxs}from'react/jsx-runtime';var W=o.forwardRef(({isOpen:s,onClose:r,onConfirm:c,title:d$1,message:a$2,warning:m,confirmText:T="\uD655\uC778",cancelText:D="\uCDE8\uC18C",confirmButtonText:x,type:E="danger",loading:w=false,disabled:g=false,showInput:y=false,inputValue:C="",onInputChange:p,inputPlaceholder:l,inputLabel:v,requiredInputValue:k,showCancel:b=true,size:N="md"},h)=>{let f={danger:{icon:jsx("svg",{className:"h-6 w-6 text-destructive",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"})}),bgColor:"bg-destructive/10",buttonColor:"bg-destructive hover:bg-destructive/90 focus:ring-destructive",textColor:"text-destructive"},warning:{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"})}),bgColor:"bg-yellow-100 dark:bg-yellow-900/20",buttonColor:"bg-yellow-600 hover:bg-yellow-700 focus:ring-yellow-500",textColor:"text-yellow-600 dark:text-yellow-400"},info:{icon:jsx("svg",{className:"h-6 w-6 text-primary",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"})}),bgColor:"bg-primary/10",buttonColor:"bg-primary hover:bg-primary/80 focus:ring-ring",textColor:"text-primary"},success:{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"})}),bgColor:"bg-green-100 dark:bg-green-900/20",buttonColor:"bg-green-600 hover:bg-green-700 focus:ring-green-500",textColor:"text-green-600 dark:text-green-400"},error:{icon:jsx("svg",{className:"h-6 w-6 text-destructive",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M6 18L18 6M6 6l12 12"})}),bgColor:"bg-destructive/10",buttonColor:"bg-destructive hover:bg-destructive/90 focus:ring-destructive",textColor:"text-destructive"}}[E],M=g||w||!(!y||!k||C===k);return jsx(a,{isOpen:s,onClose:r,closable:false,size:N,children:jsxs("div",{className:"text-center",children:[jsx("div",{className:a$1("mx-auto flex items-center justify-center h-16 w-16 rounded-full mb-6",f.bgColor),children:f.icon}),jsxs("h3",{className:"text-xl font-semibold text-foreground mb-4",children:[" ",d$1]}),jsxs("div",{className:"mb-6",children:[" ",jsx("p",{className:"text-sm text-muted-foreground",children:a$2}),m&&jsx("p",{className:a$1("text-sm mt-3 font-medium",f.textColor),children:m})]}),y&&jsxs("div",{className:"mb-6",children:[" ",jsxs("label",{htmlFor:"confirmInput",className:"block text-sm font-medium text-foreground mb-3 text-left",children:[" ",v]}),jsx("input",{type:"text",id:"confirmInput",value:C,onChange:S=>p==null?void 0:p(S.target.value),placeholder:l,className:"w-full px-4 py-3 border border-input rounded-lg focus:outline-none focus:ring-1 focus:ring-destructive focus:border-transparent bg-background text-foreground transition-colors"})]}),jsxs("div",{className:a$1("flex gap-3","justify-center"),children:[b&&jsx(d,{variant:"outline",onClick:r,disabled:w,className:"px-6 py-3",children:D}),jsx(d,{variant:"default",onClick:c,disabled:M,className:a$1("px-6 py-3",f.buttonColor),children:w?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..."]}):x||T})]})]})})});W.displayName="ConfirmModal";var V=o.forwardRef(({isOpen:s,onClose:r,children:c,className:d,height:a="md",showBackdrop:m=true,backdropClassName:T,closeOnBackdropClick:D=true,closeOnEscape:x=true,showDragHandle:E=true,closable:w=true,snapPoints:g=[25,50,75,100],defaultSnap:y=50,...C},p)=>{let l=s!=null?s:false,v=()=>{r==null||r();},[k,b]=o.useState(false),[N,h]=o.useState(false),[H,f]=o.useState(y),[B,M]=o.useState(false),[S,K]=o.useState(0),[Y,j]=o.useState(0),O={sm:"h-64",md:"h-96",lg:"h-[32rem]",xl:"h-[40rem]",full:"h-full"};o.useEffect(()=>{if(l){b(true),h(true);let t=setTimeout(()=>h(false),50);return ()=>clearTimeout(t)}else {h(true);let t=setTimeout(()=>{b(false),h(false);},300);return ()=>clearTimeout(t)}},[l]),o.useEffect(()=>{if(!x)return;let t=L=>{L.key==="Escape"&&l&&v();};return l&&(document.addEventListener("keydown",t),document.body.style.overflow="hidden"),()=>{document.removeEventListener("keydown",t),document.body.style.overflow="";}},[l,x]);let _=t=>{M(true),K(t.touches[0].clientY),j(t.touches[0].clientY);},$=t=>{B&&j(t.touches[0].clientY);},G=()=>{if(!B)return;M(false);let t=Y-S,L=100;if(t>L)v();else if(t<-L){let q=g.indexOf(H),J=Math.min(q+1,g.length-1);f(g[J]);}};return k?jsxs("div",{className:"fixed inset-0 z-50",children:[m&&jsx("div",{className:a$1("absolute inset-0 bg-black/85 backdrop-blur-md transition-opacity duration-300",N?l?"opacity-100":"opacity-0":"",T),onClick:D?v:void 0}),jsxs("div",{ref:p,className:a$1("absolute bottom-0 left-0 right-0 bg-background/95 backdrop-blur-xl border-t border-border/50 shadow-2xl rounded-t-lg transition-transform duration-300 ease-out pb-safe",a!=="full"?O[a]:"",N?l?"translate-y-0":"translate-y-full":"",d),style:{height:a==="full"?`${H}%`:void 0,maxHeight:a!=="full"?void 0:"100%",transform:B?`translateY(${Y-S}px)`:void 0},onTouchStart:_,onTouchMove:$,onTouchEnd:G,...C,children:[E&&jsx("div",{className:"flex justify-center pt-3 pb-2",children:jsx("div",{className:"w-12 h-1.5 bg-muted-foreground/30 rounded-full"})}),c]})]}):null});V.displayName="BottomSheet";var A=o.forwardRef(({children:s,className:r,showCloseButton:c=true,onClose:d,...a},m)=>jsxs("div",{ref:m,className:a$1("flex items-center justify-between px-6 py-4",r),...a,children:[jsx("div",{className:"flex-1",children:s}),c&&jsx("button",{onClick:d,className:"p-2 rounded-lg hover:bg-muted transition-colors",children:jsx(l,{name:"close",size:20})})]}));A.displayName="BottomSheetHeader";var F=o.forwardRef(({children:s,className:r,...c},d)=>jsx("div",{ref:d,className:a$1("flex-1 px-6 pb-6 overflow-y-auto",r),...c,children:s}));F.displayName="BottomSheetContent";
3
3
  export{V as BottomSheet,F as BottomSheetContent,A as BottomSheetHeader,W as ConfirmModal};//# sourceMappingURL=overlay.mjs.map
4
4
  //# sourceMappingURL=overlay.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/ConfirmModal.tsx","../src/components/BottomSheet.tsx"],"names":["ConfirmModal","React","isOpen","onClose","onConfirm","title","message","warning","confirmText","cancelText","confirmButtonText","type","loading","disabled","showInput","inputValue","onInputChange","inputPlaceholder","inputLabel","requiredInputValue","showCancel","size","_ref","config","jsx","isDisabled","Modal","jsxs","merge","e","Button","BottomSheet","children","className","height","showBackdrop","backdropClassName","closeOnBackdropClick","closeOnEscape","showDragHandle","closable","snapPoints","defaultSnap","props","ref","_isOpen","handleClose","isVisible","setIsVisible","isAnimating","setIsAnimating","currentHeight","setCurrentHeight","isDragging","setIsDragging","startY","setStartY","currentY","setCurrentY","heightClasses","timer","handleEscapeKey","handleTouchStart","handleTouchMove","handleTouchEnd","deltaY","threshold","currentIndex","nextIndex","BottomSheetHeader","showCloseButton","Icon","BottomSheetContent"],"mappings":"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","file":"overlay.mjs","sourcesContent":["\"use client\"\n\nimport React from \"react\"\nimport { merge } from \"../lib/utils\"\nimport { Modal } from \"./Modal\"\nimport { Button } from \"./Button\"\n\n/**\n * ConfirmModal 컴포넌트의 props / ConfirmModal component props\n * @typedef {Object} ConfirmModalProps\n * @property {boolean} isOpen - 모달 열림/닫힘 상태 / Modal open/close state\n * @property {() => void} onClose - 닫기 콜백 / Close callback\n * @property {() => void} onConfirm - 확인 콜백 / Confirm callback\n * @property {string} title - 모달 제목 / Modal title\n * @property {string} message - 모달 메시지 / Modal message\n * @property {string} [warning] - 경고 메시지 / Warning message\n * @property {string} [confirmText=\"확인\"] - 확인 버튼 텍스트 / Confirm button text\n * @property {string} [cancelText=\"취소\"] - 취소 버튼 텍스트 / Cancel button text\n * @property {string} [confirmButtonText] - 확인 버튼 커스텀 텍스트 / Custom confirm button text\n * @property {\"danger\" | \"warning\" | \"info\" | \"success\" | \"error\"} [type=\"danger\"] - 모달 타입 / Modal type\n * @property {boolean} [loading=false] - 로딩 상태 / Loading state\n * @property {boolean} [disabled=false] - 비활성화 여부 / Disabled state\n * @property {boolean} [showInput=false] - 입력 필드 표시 여부 / Show input field\n * @property {string} [inputValue=\"\"] - 입력 필드 값 / Input field value\n * @property {(value: string) => void} [onInputChange] - 입력 값 변경 콜백 / Input value change callback\n * @property {string} [inputPlaceholder] - 입력 필드 플레이스홀더 / Input field placeholder\n * @property {string} [inputLabel] - 입력 필드 라벨 / Input field label\n * @property {string} [requiredInputValue] - 필수 입력 값 (확인 버튼 활성화 조건) / Required input value (confirm button activation condition)\n * @property {boolean} [showCancel=true] - 취소 버튼 표시 여부 / Show cancel button\n * @property {\"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\"} [size=\"md\"] - 모달 크기 / Modal size\n */\nexport interface ConfirmModalProps {\n isOpen: boolean\n onClose: () => void\n onConfirm: () => void\n title: string\n message: string\n warning?: string\n confirmText?: string\n cancelText?: string\n confirmButtonText?: string\n type?: \"danger\" | \"warning\" | \"info\" | \"success\" | \"error\"\n loading?: boolean\n disabled?: boolean\n showInput?: boolean\n inputValue?: string\n onInputChange?: (value: string) => void\n inputPlaceholder?: string\n inputLabel?: string\n requiredInputValue?: string\n showCancel?: boolean\n size?: \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\"\n}\n\n/**\n * ConfirmModal 컴포넌트 / ConfirmModal component\n * \n * 확인/취소가 필요한 모달 컴포넌트입니다.\n * 다양한 타입(danger, warning, info, success, error)을 지원하며,\n * 입력 필드와 필수 입력 값 검증을 지원합니다.\n * \n * Modal component that requires confirmation/cancellation.\n * Supports various types (danger, warning, info, success, error),\n * and supports input fields and required input value validation.\n * \n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <ConfirmModal\n * isOpen={isOpen}\n * onClose={() => setIsOpen(false)}\n * onConfirm={handleConfirm}\n * title=\"삭제 확인\"\n * message=\"정말 삭제하시겠습니까?\"\n * />\n * \n * @example\n * // 입력 필드와 함께 / With input field\n * <ConfirmModal\n * isOpen={isOpen}\n * onClose={() => setIsOpen(false)}\n * onConfirm={handleDelete}\n * title=\"삭제 확인\"\n * message=\"삭제하려면 'DELETE'를 입력하세요\"\n * showInput\n * inputLabel=\"확인 입력\"\n * requiredInputValue=\"DELETE\"\n * inputValue={inputValue}\n * onInputChange={setInputValue}\n * />\n * \n * @param {ConfirmModalProps} props - ConfirmModal 컴포넌트의 props / ConfirmModal component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} ConfirmModal 컴포넌트 / ConfirmModal component\n */\nconst ConfirmModal = React.forwardRef<HTMLDivElement, ConfirmModalProps>(\n ({\n isOpen,\n onClose,\n onConfirm,\n title,\n message,\n warning,\n confirmText = \"확인\",\n cancelText = \"취소\",\n confirmButtonText,\n type = \"danger\",\n loading = false,\n disabled = false,\n showInput = false,\n inputValue = \"\",\n onInputChange,\n inputPlaceholder,\n inputLabel,\n requiredInputValue,\n showCancel = true,\n size = \"md\"\n }, _ref) => {\n // 타입별 아이콘과 색상\n const typeConfig = {\n danger: {\n icon: (\n <svg className=\"h-6 w-6 text-destructive\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <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\" />\n </svg>\n ),\n bgColor: \"bg-destructive/10\",\n buttonColor: \"bg-destructive hover:bg-destructive/90 focus:ring-destructive\",\n textColor: \"text-destructive\"\n },\n warning: {\n icon: (\n <svg className=\"h-6 w-6 text-yellow-600 dark:text-yellow-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <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\" />\n </svg>\n ),\n bgColor: \"bg-yellow-100 dark:bg-yellow-900/20\",\n buttonColor: \"bg-yellow-600 hover:bg-yellow-700 focus:ring-yellow-500\",\n textColor: \"text-yellow-600 dark:text-yellow-400\"\n },\n info: {\n icon: (\n <svg className=\"h-6 w-6 text-primary\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <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\" />\n </svg>\n ),\n bgColor: \"bg-primary/10\",\n buttonColor: \"bg-primary hover:bg-primary/80 focus:ring-ring\",\n textColor: \"text-primary\"\n },\n success: {\n icon: (\n <svg className=\"h-6 w-6 text-green-600 dark:text-green-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n ),\n bgColor: \"bg-green-100 dark:bg-green-900/20\",\n buttonColor: \"bg-green-600 hover:bg-green-700 focus:ring-green-500\",\n textColor: \"text-green-600 dark:text-green-400\"\n },\n error: {\n icon: (\n <svg className=\"h-6 w-6 text-destructive\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n ),\n bgColor: \"bg-destructive/10\",\n buttonColor: \"bg-destructive hover:bg-destructive/90 focus:ring-destructive\",\n textColor: \"text-destructive\"\n }\n }\n\n const config = typeConfig[type]\n const isInputValid = !showInput || !requiredInputValue || inputValue === requiredInputValue\n const isDisabled = disabled || loading || !isInputValid\n\n return (\n <Modal \n isOpen={isOpen} \n onClose={onClose} \n closable={false}\n size={size}\n >\n <div className=\"text-center\">\n {/* 아이콘 */}\n <div className={merge(\n \"mx-auto flex items-center justify-center h-16 w-16 rounded-full mb-6\", // 64px 아이콘, 24px 여백\n config.bgColor\n )}>\n {config.icon}\n </div>\n\n {/* 제목 */}\n <h3 className=\"text-xl font-semibold text-foreground mb-4\"> {/* 16px 여백 */}\n {title}\n </h3>\n\n {/* 메시지 */}\n <div className=\"mb-6\"> {/* 24px 여백 */}\n <p className=\"text-sm text-muted-foreground\">\n {message}\n </p>\n \n {/* 경고 메시지 */}\n {warning && (\n <p className={merge(\n \"text-sm mt-3 font-medium\", // 12px 여백\n config.textColor\n )}>\n {warning}\n </p>\n )}\n </div>\n\n {/* 입력 필드 */}\n {showInput && (\n <div className=\"mb-6\"> {/* 24px 여백 */}\n <label htmlFor=\"confirmInput\" className=\"block text-sm font-medium text-foreground mb-3 text-left\"> {/* 12px 여백 */}\n {inputLabel}\n </label>\n <input\n type=\"text\"\n id=\"confirmInput\"\n value={inputValue}\n onChange={(e) => onInputChange?.(e.target.value)}\n placeholder={inputPlaceholder}\n className=\"w-full px-4 py-3 border border-input rounded-lg focus:outline-none focus:ring-1 focus:ring-destructive focus:border-transparent bg-background text-foreground transition-colors\" // 16px, 12px 패딩\n />\n </div>\n )}\n\n {/* 버튼 */}\n <div className={merge(\n \"flex gap-3\", // 12px 간격\n showCancel ? \"justify-center\" : \"justify-center\"\n )}>\n {showCancel && (\n <Button\n variant=\"outline\"\n onClick={onClose}\n disabled={loading}\n className=\"px-6 py-3\" // 24px, 12px 패딩\n >\n {cancelText}\n </Button>\n )}\n <Button\n variant=\"default\"\n onClick={onConfirm}\n disabled={isDisabled}\n className={merge(\n \"px-6 py-3\", // 24px, 12px 패딩\n config.buttonColor\n )}\n >\n {loading ? (\n <div className=\"flex items-center\">\n <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\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\"></circle>\n <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\"></path>\n </svg>\n 처리 중...\n </div>\n ) : (\n confirmButtonText || confirmText\n )}\n </Button>\n </div>\n </div>\n </Modal>\n )\n }\n)\nConfirmModal.displayName = \"ConfirmModal\"\n\nexport { ConfirmModal } ","\"use client\"\n\nimport React from \"react\"\nimport { merge } from \"../lib/utils\"\nimport { Icon } from \"./Icon\"\n\n/**\n * BottomSheet 컴포넌트의 props / BottomSheet component props\n * @typedef {Object} BottomSheetProps\n * @property {boolean} open - BottomSheet 열림/닫힘 상태 / BottomSheet open/close state\n * @property {(open: boolean) => void} onOpenChange - 상태 변경 콜백 / State change callback\n * @property {React.ReactNode} children - BottomSheet 내용 / BottomSheet content\n * @property {string} [className] - 추가 CSS 클래스 / Additional CSS class\n * @property {\"sm\" | \"md\" | \"lg\" | \"xl\" | \"full\"} [height=\"md\"] - BottomSheet 높이 / BottomSheet height\n * @property {boolean} [showBackdrop=true] - 배경 오버레이 표시 여부 / Show backdrop overlay\n * @property {string} [backdropClassName] - 배경 오버레이 추가 CSS 클래스 / Backdrop overlay additional CSS class\n * @property {boolean} [closeOnBackdropClick=true] - 배경 클릭 시 닫기 여부 / Close on backdrop click\n * @property {boolean} [closeOnEscape=true] - ESC 키로 닫기 여부 / Close on ESC key\n * @property {boolean} [showDragHandle=true] - 드래그 핸들 표시 여부 / Show drag handle\n * @property {number[]} [snapPoints=[25, 50, 75, 100]] - 스냅 포인트 (퍼센트) / Snap points (percentage)\n * @property {number} [defaultSnap=50] - 기본 스냅 포인트 (퍼센트) / Default snap point (percentage)\n */\ninterface BottomSheetProps {\n /** BottomSheet 열림/닫힘 상태 / BottomSheet open/close state */\n isOpen?: boolean\n /** BottomSheet 닫기 콜백 / BottomSheet close callback */\n onClose?: () => void\n /** BottomSheet 내용 / BottomSheet content */\n children: React.ReactNode\n /** 추가 CSS 클래스 / Additional CSS class */\n className?: string\n /** BottomSheet 높이 / BottomSheet height */\n height?: \"sm\" | \"md\" | \"lg\" | \"xl\" | \"full\"\n /** 배경 오버레이 표시 여부 / Show backdrop overlay */\n showBackdrop?: boolean\n /** 배경 오버레이 추가 CSS 클래스 / Backdrop overlay additional CSS class */\n backdropClassName?: string\n /** 배경 클릭 시 닫기 여부 / Close on backdrop click */\n closeOnBackdropClick?: boolean\n /** ESC 키로 닫기 여부 / Close on ESC key */\n closeOnEscape?: boolean\n /** 드래그 핸들 표시 여부 / Show drag handle */\n showDragHandle?: boolean\n /** 닫기 버튼 표시 여부 / Show close button */\n closable?: boolean\n /** 스냅 포인트 (퍼센트) / Snap points (percentage) */\n snapPoints?: number[]\n /** 기본 스냅 포인트 (퍼센트) / Default snap point (percentage) */\n defaultSnap?: number\n}\n\n/**\n * BottomSheet 컴포넌트 / BottomSheet component\n * \n * 화면 하단에서 올라오는 시트 컴포넌트입니다.\n * 모바일 친화적인 UI를 제공하며, 드래그로 높이를 조절할 수 있습니다.\n * 스냅 포인트를 지원하여 특정 높이에서 멈출 수 있습니다.\n * \n * Sheet component that slides up from the bottom of the screen.\n * Provides mobile-friendly UI and allows height adjustment by dragging.\n * Supports snap points to stop at specific heights.\n * \n * @component\n * @example\n * // 기본 사용 / Basic usage\n * const [open, setOpen] = useState(false)\n * \n * <BottomSheet open={open} onOpenChange={setOpen}>\n * <BottomSheetHeader>제목</BottomSheetHeader>\n * <BottomSheetContent>내용</BottomSheetContent>\n * </BottomSheet>\n * \n * @example\n * // 커스텀 스냅 포인트 / Custom snap points\n * <BottomSheet \n * open={open} \n * onOpenChange={setOpen}\n * snapPoints={[30, 60, 90]}\n * defaultSnap={30}\n * >\n * <BottomSheetContent>내용</BottomSheetContent>\n * </BottomSheet>\n * \n * @param {BottomSheetProps} props - BottomSheet 컴포넌트의 props / BottomSheet component props\n * @param {React.Ref<HTMLDivElement>} ref - BottomSheet 컨테이너 ref / BottomSheet container ref\n * @returns {JSX.Element} BottomSheet 컴포넌트 / BottomSheet component\n * \n * @todo 접근성 개선: role=\"dialog\", aria-modal=\"true\" 추가 필요 / Accessibility: Add role=\"dialog\", aria-modal=\"true\"\n * @todo 접근성 개선: aria-labelledby, aria-describedby 연결 필요 / Accessibility: Connect aria-labelledby, aria-describedby\n */\nconst BottomSheet = React.forwardRef<HTMLDivElement, BottomSheetProps>(\n ({\n isOpen,\n onClose,\n children,\n className,\n height = \"md\",\n showBackdrop = true,\n backdropClassName,\n closeOnBackdropClick = true,\n closeOnEscape = true,\n showDragHandle = true,\n closable = true,\n snapPoints = [25, 50, 75, 100],\n defaultSnap = 50,\n ...props\n }, ref) => {\n const _isOpen = isOpen ?? false\n const handleClose = () => {\n onClose?.()\n }\n\n const [isVisible, setIsVisible] = React.useState(false)\n const [isAnimating, setIsAnimating] = React.useState(false)\n const [currentHeight, setCurrentHeight] = React.useState(defaultSnap)\n const [isDragging, setIsDragging] = React.useState(false)\n const [startY, setStartY] = React.useState(0)\n const [currentY, setCurrentY] = React.useState(0)\n\n const heightClasses = {\n sm: \"h-64\",\n md: \"h-96\",\n lg: \"h-[32rem]\",\n xl: \"h-[40rem]\",\n full: \"h-full\"\n }\n\n React.useEffect(() => {\n if (_isOpen) {\n setIsVisible(true)\n setIsAnimating(true)\n const timer = setTimeout(() => setIsAnimating(false), 50)\n return () => clearTimeout(timer)\n } else {\n setIsAnimating(true)\n const timer = setTimeout(() => {\n setIsVisible(false)\n setIsAnimating(false)\n }, 300)\n return () => clearTimeout(timer)\n }\n }, [_isOpen])\n\n React.useEffect(() => {\n if (!closeOnEscape) return\n\n const handleEscapeKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && _isOpen) {\n handleClose()\n }\n }\n\n if (_isOpen) {\n document.addEventListener(\"keydown\", handleEscapeKey)\n document.body.style.overflow = \"hidden\"\n }\n\n return () => {\n document.removeEventListener(\"keydown\", handleEscapeKey)\n document.body.style.overflow = \"\"\n }\n }, [_isOpen, closeOnEscape])\n\n const handleTouchStart = (e: React.TouchEvent) => {\n setIsDragging(true)\n setStartY(e.touches[0].clientY)\n setCurrentY(e.touches[0].clientY)\n }\n\n const handleTouchMove = (e: React.TouchEvent) => {\n if (!isDragging) return\n setCurrentY(e.touches[0].clientY)\n }\n\n const handleTouchEnd = () => {\n if (!isDragging) return\n setIsDragging(false)\n\n const deltaY = currentY - startY\n const threshold = 100\n\n if (deltaY > threshold) {\n // 아래로 드래그 - 닫기\n handleClose()\n } else if (deltaY < -threshold) {\n // 위로 드래그 - 다음 스냅 포인트\n const currentIndex = snapPoints.indexOf(currentHeight)\n const nextIndex = Math.min(currentIndex + 1, snapPoints.length - 1)\n setCurrentHeight(snapPoints[nextIndex])\n }\n }\n\n if (!isVisible) return null\n\n return (\n <div className=\"fixed inset-0 z-50\">\n {/* Backdrop */}\n {showBackdrop && (\n <div\n className={merge(\n \"absolute inset-0 bg-black/60 backdrop-blur-md transition-opacity duration-300\",\n isAnimating ? (_isOpen ? \"opacity-100\" : \"opacity-0\") : \"\",\n backdropClassName\n )}\n onClick={closeOnBackdropClick ? handleClose : undefined}\n />\n )}\n\n {/* Bottom Sheet */}\n <div\n ref={ref}\n className={merge(\n \"absolute bottom-0 left-0 right-0 bg-background/95 backdrop-blur-xl border-t border-border/50 shadow-2xl rounded-t-lg transition-transform duration-300 ease-out pb-safe\",\n height !== \"full\" ? heightClasses[height] : \"\",\n isAnimating ? (_isOpen ? \"translate-y-0\" : \"translate-y-full\") : \"\",\n className\n )}\n style={{\n // height prop이 \"full\"일 때만 퍼센트 높이 사용 (스냅 포인트)\n // 그 외에는 heightClasses의 고정 높이 사용\n height: height === \"full\" ? `${currentHeight}%` : undefined,\n maxHeight: height !== \"full\" ? undefined : \"100%\",\n transform: isDragging ? `translateY(${currentY - startY}px)` : undefined\n }}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n {...props}\n >\n {/* Drag Handle */}\n {showDragHandle && (\n <div className=\"flex justify-center pt-3 pb-2\">\n <div className=\"w-12 h-1.5 bg-muted-foreground/30 rounded-full\" />\n </div>\n )}\n\n {children}\n </div>\n </div>\n )\n }\n)\nBottomSheet.displayName = \"BottomSheet\"\n\n/**\n * BottomSheetHeader 컴포넌트의 props / BottomSheetHeader component props\n * @typedef {Object} BottomSheetHeaderProps\n * @property {React.ReactNode} children - 헤더 내용 / Header content\n * @property {string} [className] - 추가 CSS 클래스 / Additional CSS class\n * @property {boolean} [showCloseButton=true] - 닫기 버튼 표시 여부 / Show close button\n * @property {() => void} [onClose] - 닫기 버튼 클릭 콜백 / Close button click callback\n */\ninterface BottomSheetHeaderProps {\n children: React.ReactNode\n className?: string\n showCloseButton?: boolean\n onClose?: () => void\n}\n\n/**\n * BottomSheetHeader 컴포넌트 / BottomSheetHeader component\n * BottomSheet의 헤더 영역을 표시합니다.\n * Displays the header area of a BottomSheet.\n * \n * @component\n * @param {BottomSheetHeaderProps} props - BottomSheetHeader 컴포넌트의 props / BottomSheetHeader component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} BottomSheetHeader 컴포넌트 / BottomSheetHeader component\n */\nconst BottomSheetHeader = React.forwardRef<HTMLDivElement, BottomSheetHeaderProps>(\n ({ children, className, showCloseButton = true, onClose, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={merge(\"flex items-center justify-between px-6 py-4\", className)}\n {...props}\n >\n <div className=\"flex-1\">{children}</div>\n {showCloseButton && (\n <button\n onClick={onClose}\n className=\"p-2 rounded-lg hover:bg-muted transition-colors\"\n >\n <Icon name=\"close\" size={20} />\n </button>\n )}\n </div>\n )\n }\n)\nBottomSheetHeader.displayName = \"BottomSheetHeader\"\n\n/**\n * BottomSheetContent 컴포넌트의 props / BottomSheetContent component props\n * @typedef {Object} BottomSheetContentProps\n * @property {React.ReactNode} children - 콘텐츠 / Content\n * @property {string} [className] - 추가 CSS 클래스 / Additional CSS class\n */\ninterface BottomSheetContentProps {\n children: React.ReactNode\n className?: string\n}\n\n/**\n * BottomSheetContent 컴포넌트 / BottomSheetContent component\n * BottomSheet의 메인 콘텐츠 영역을 표시합니다.\n * Displays the main content area of a BottomSheet.\n * \n * @component\n * @param {BottomSheetContentProps} props - BottomSheetContent 컴포넌트의 props / BottomSheetContent component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} BottomSheetContent 컴포넌트 / BottomSheetContent component\n */\nconst BottomSheetContent = React.forwardRef<HTMLDivElement, BottomSheetContentProps>(\n ({ children, className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={merge(\"flex-1 px-6 pb-6 overflow-y-auto\", className)}\n {...props}\n >\n {children}\n </div>\n )\n }\n)\nBottomSheetContent.displayName = \"BottomSheetContent\"\n\nexport { BottomSheet, BottomSheetHeader, BottomSheetContent } "]}
1
+ {"version":3,"sources":["../src/components/ConfirmModal.tsx","../src/components/BottomSheet.tsx"],"names":["ConfirmModal","React","isOpen","onClose","onConfirm","title","message","warning","confirmText","cancelText","confirmButtonText","type","loading","disabled","showInput","inputValue","onInputChange","inputPlaceholder","inputLabel","requiredInputValue","showCancel","size","_ref","config","jsx","isDisabled","Modal","jsxs","merge","e","Button","BottomSheet","children","className","height","showBackdrop","backdropClassName","closeOnBackdropClick","closeOnEscape","showDragHandle","closable","snapPoints","defaultSnap","props","ref","_isOpen","handleClose","isVisible","setIsVisible","isAnimating","setIsAnimating","currentHeight","setCurrentHeight","isDragging","setIsDragging","startY","setStartY","currentY","setCurrentY","heightClasses","timer","handleEscapeKey","handleTouchStart","handleTouchMove","handleTouchEnd","deltaY","threshold","currentIndex","nextIndex","BottomSheetHeader","showCloseButton","Icon","BottomSheetContent"],"mappings":"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","file":"overlay.mjs","sourcesContent":["\"use client\"\n\nimport React from \"react\"\nimport { merge } from \"../lib/utils\"\nimport { Modal } from \"./Modal\"\nimport { Button } from \"./Button\"\n\n/**\n * ConfirmModal 컴포넌트의 props / ConfirmModal component props\n * @typedef {Object} ConfirmModalProps\n * @property {boolean} isOpen - 모달 열림/닫힘 상태 / Modal open/close state\n * @property {() => void} onClose - 닫기 콜백 / Close callback\n * @property {() => void} onConfirm - 확인 콜백 / Confirm callback\n * @property {string} title - 모달 제목 / Modal title\n * @property {string} message - 모달 메시지 / Modal message\n * @property {string} [warning] - 경고 메시지 / Warning message\n * @property {string} [confirmText=\"확인\"] - 확인 버튼 텍스트 / Confirm button text\n * @property {string} [cancelText=\"취소\"] - 취소 버튼 텍스트 / Cancel button text\n * @property {string} [confirmButtonText] - 확인 버튼 커스텀 텍스트 / Custom confirm button text\n * @property {\"danger\" | \"warning\" | \"info\" | \"success\" | \"error\"} [type=\"danger\"] - 모달 타입 / Modal type\n * @property {boolean} [loading=false] - 로딩 상태 / Loading state\n * @property {boolean} [disabled=false] - 비활성화 여부 / Disabled state\n * @property {boolean} [showInput=false] - 입력 필드 표시 여부 / Show input field\n * @property {string} [inputValue=\"\"] - 입력 필드 값 / Input field value\n * @property {(value: string) => void} [onInputChange] - 입력 값 변경 콜백 / Input value change callback\n * @property {string} [inputPlaceholder] - 입력 필드 플레이스홀더 / Input field placeholder\n * @property {string} [inputLabel] - 입력 필드 라벨 / Input field label\n * @property {string} [requiredInputValue] - 필수 입력 값 (확인 버튼 활성화 조건) / Required input value (confirm button activation condition)\n * @property {boolean} [showCancel=true] - 취소 버튼 표시 여부 / Show cancel button\n * @property {\"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\"} [size=\"md\"] - 모달 크기 / Modal size\n */\nexport interface ConfirmModalProps {\n isOpen: boolean\n onClose: () => void\n onConfirm: () => void\n title: string\n message: string\n warning?: string\n confirmText?: string\n cancelText?: string\n confirmButtonText?: string\n type?: \"danger\" | \"warning\" | \"info\" | \"success\" | \"error\"\n loading?: boolean\n disabled?: boolean\n showInput?: boolean\n inputValue?: string\n onInputChange?: (value: string) => void\n inputPlaceholder?: string\n inputLabel?: string\n requiredInputValue?: string\n showCancel?: boolean\n size?: \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\"\n}\n\n/**\n * ConfirmModal 컴포넌트 / ConfirmModal component\n * \n * 확인/취소가 필요한 모달 컴포넌트입니다.\n * 다양한 타입(danger, warning, info, success, error)을 지원하며,\n * 입력 필드와 필수 입력 값 검증을 지원합니다.\n * \n * Modal component that requires confirmation/cancellation.\n * Supports various types (danger, warning, info, success, error),\n * and supports input fields and required input value validation.\n * \n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <ConfirmModal\n * isOpen={isOpen}\n * onClose={() => setIsOpen(false)}\n * onConfirm={handleConfirm}\n * title=\"삭제 확인\"\n * message=\"정말 삭제하시겠습니까?\"\n * />\n * \n * @example\n * // 입력 필드와 함께 / With input field\n * <ConfirmModal\n * isOpen={isOpen}\n * onClose={() => setIsOpen(false)}\n * onConfirm={handleDelete}\n * title=\"삭제 확인\"\n * message=\"삭제하려면 'DELETE'를 입력하세요\"\n * showInput\n * inputLabel=\"확인 입력\"\n * requiredInputValue=\"DELETE\"\n * inputValue={inputValue}\n * onInputChange={setInputValue}\n * />\n * \n * @param {ConfirmModalProps} props - ConfirmModal 컴포넌트의 props / ConfirmModal component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} ConfirmModal 컴포넌트 / ConfirmModal component\n */\nconst ConfirmModal = React.forwardRef<HTMLDivElement, ConfirmModalProps>(\n ({\n isOpen,\n onClose,\n onConfirm,\n title,\n message,\n warning,\n confirmText = \"확인\",\n cancelText = \"취소\",\n confirmButtonText,\n type = \"danger\",\n loading = false,\n disabled = false,\n showInput = false,\n inputValue = \"\",\n onInputChange,\n inputPlaceholder,\n inputLabel,\n requiredInputValue,\n showCancel = true,\n size = \"md\"\n }, _ref) => {\n // 타입별 아이콘과 색상\n const typeConfig = {\n danger: {\n icon: (\n <svg className=\"h-6 w-6 text-destructive\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <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\" />\n </svg>\n ),\n bgColor: \"bg-destructive/10\",\n buttonColor: \"bg-destructive hover:bg-destructive/90 focus:ring-destructive\",\n textColor: \"text-destructive\"\n },\n warning: {\n icon: (\n <svg className=\"h-6 w-6 text-yellow-600 dark:text-yellow-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <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\" />\n </svg>\n ),\n bgColor: \"bg-yellow-100 dark:bg-yellow-900/20\",\n buttonColor: \"bg-yellow-600 hover:bg-yellow-700 focus:ring-yellow-500\",\n textColor: \"text-yellow-600 dark:text-yellow-400\"\n },\n info: {\n icon: (\n <svg className=\"h-6 w-6 text-primary\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <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\" />\n </svg>\n ),\n bgColor: \"bg-primary/10\",\n buttonColor: \"bg-primary hover:bg-primary/80 focus:ring-ring\",\n textColor: \"text-primary\"\n },\n success: {\n icon: (\n <svg className=\"h-6 w-6 text-green-600 dark:text-green-400\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n ),\n bgColor: \"bg-green-100 dark:bg-green-900/20\",\n buttonColor: \"bg-green-600 hover:bg-green-700 focus:ring-green-500\",\n textColor: \"text-green-600 dark:text-green-400\"\n },\n error: {\n icon: (\n <svg className=\"h-6 w-6 text-destructive\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n ),\n bgColor: \"bg-destructive/10\",\n buttonColor: \"bg-destructive hover:bg-destructive/90 focus:ring-destructive\",\n textColor: \"text-destructive\"\n }\n }\n\n const config = typeConfig[type]\n const isInputValid = !showInput || !requiredInputValue || inputValue === requiredInputValue\n const isDisabled = disabled || loading || !isInputValid\n\n return (\n <Modal \n isOpen={isOpen} \n onClose={onClose} \n closable={false}\n size={size}\n >\n <div className=\"text-center\">\n {/* 아이콘 */}\n <div className={merge(\n \"mx-auto flex items-center justify-center h-16 w-16 rounded-full mb-6\", // 64px 아이콘, 24px 여백\n config.bgColor\n )}>\n {config.icon}\n </div>\n\n {/* 제목 */}\n <h3 className=\"text-xl font-semibold text-foreground mb-4\"> {/* 16px 여백 */}\n {title}\n </h3>\n\n {/* 메시지 */}\n <div className=\"mb-6\"> {/* 24px 여백 */}\n <p className=\"text-sm text-muted-foreground\">\n {message}\n </p>\n \n {/* 경고 메시지 */}\n {warning && (\n <p className={merge(\n \"text-sm mt-3 font-medium\", // 12px 여백\n config.textColor\n )}>\n {warning}\n </p>\n )}\n </div>\n\n {/* 입력 필드 */}\n {showInput && (\n <div className=\"mb-6\"> {/* 24px 여백 */}\n <label htmlFor=\"confirmInput\" className=\"block text-sm font-medium text-foreground mb-3 text-left\"> {/* 12px 여백 */}\n {inputLabel}\n </label>\n <input\n type=\"text\"\n id=\"confirmInput\"\n value={inputValue}\n onChange={(e) => onInputChange?.(e.target.value)}\n placeholder={inputPlaceholder}\n className=\"w-full px-4 py-3 border border-input rounded-lg focus:outline-none focus:ring-1 focus:ring-destructive focus:border-transparent bg-background text-foreground transition-colors\" // 16px, 12px 패딩\n />\n </div>\n )}\n\n {/* 버튼 */}\n <div className={merge(\n \"flex gap-3\", // 12px 간격\n showCancel ? \"justify-center\" : \"justify-center\"\n )}>\n {showCancel && (\n <Button\n variant=\"outline\"\n onClick={onClose}\n disabled={loading}\n className=\"px-6 py-3\" // 24px, 12px 패딩\n >\n {cancelText}\n </Button>\n )}\n <Button\n variant=\"default\"\n onClick={onConfirm}\n disabled={isDisabled}\n className={merge(\n \"px-6 py-3\", // 24px, 12px 패딩\n config.buttonColor\n )}\n >\n {loading ? (\n <div className=\"flex items-center\">\n <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\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\"></circle>\n <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\"></path>\n </svg>\n 처리 중...\n </div>\n ) : (\n confirmButtonText || confirmText\n )}\n </Button>\n </div>\n </div>\n </Modal>\n )\n }\n)\nConfirmModal.displayName = \"ConfirmModal\"\n\nexport { ConfirmModal } ","\"use client\"\n\nimport React from \"react\"\nimport { merge } from \"../lib/utils\"\nimport { Icon } from \"./Icon\"\n\n/**\n * BottomSheet 컴포넌트의 props / BottomSheet component props\n * @typedef {Object} BottomSheetProps\n * @property {boolean} open - BottomSheet 열림/닫힘 상태 / BottomSheet open/close state\n * @property {(open: boolean) => void} onOpenChange - 상태 변경 콜백 / State change callback\n * @property {React.ReactNode} children - BottomSheet 내용 / BottomSheet content\n * @property {string} [className] - 추가 CSS 클래스 / Additional CSS class\n * @property {\"sm\" | \"md\" | \"lg\" | \"xl\" | \"full\"} [height=\"md\"] - BottomSheet 높이 / BottomSheet height\n * @property {boolean} [showBackdrop=true] - 배경 오버레이 표시 여부 / Show backdrop overlay\n * @property {string} [backdropClassName] - 배경 오버레이 추가 CSS 클래스 / Backdrop overlay additional CSS class\n * @property {boolean} [closeOnBackdropClick=true] - 배경 클릭 시 닫기 여부 / Close on backdrop click\n * @property {boolean} [closeOnEscape=true] - ESC 키로 닫기 여부 / Close on ESC key\n * @property {boolean} [showDragHandle=true] - 드래그 핸들 표시 여부 / Show drag handle\n * @property {number[]} [snapPoints=[25, 50, 75, 100]] - 스냅 포인트 (퍼센트) / Snap points (percentage)\n * @property {number} [defaultSnap=50] - 기본 스냅 포인트 (퍼센트) / Default snap point (percentage)\n */\ninterface BottomSheetProps {\n /** BottomSheet 열림/닫힘 상태 / BottomSheet open/close state */\n isOpen?: boolean\n /** BottomSheet 닫기 콜백 / BottomSheet close callback */\n onClose?: () => void\n /** BottomSheet 내용 / BottomSheet content */\n children: React.ReactNode\n /** 추가 CSS 클래스 / Additional CSS class */\n className?: string\n /** BottomSheet 높이 / BottomSheet height */\n height?: \"sm\" | \"md\" | \"lg\" | \"xl\" | \"full\"\n /** 배경 오버레이 표시 여부 / Show backdrop overlay */\n showBackdrop?: boolean\n /** 배경 오버레이 추가 CSS 클래스 / Backdrop overlay additional CSS class */\n backdropClassName?: string\n /** 배경 클릭 시 닫기 여부 / Close on backdrop click */\n closeOnBackdropClick?: boolean\n /** ESC 키로 닫기 여부 / Close on ESC key */\n closeOnEscape?: boolean\n /** 드래그 핸들 표시 여부 / Show drag handle */\n showDragHandle?: boolean\n /** 닫기 버튼 표시 여부 / Show close button */\n closable?: boolean\n /** 스냅 포인트 (퍼센트) / Snap points (percentage) */\n snapPoints?: number[]\n /** 기본 스냅 포인트 (퍼센트) / Default snap point (percentage) */\n defaultSnap?: number\n}\n\n/**\n * BottomSheet 컴포넌트 / BottomSheet component\n * \n * 화면 하단에서 올라오는 시트 컴포넌트입니다.\n * 모바일 친화적인 UI를 제공하며, 드래그로 높이를 조절할 수 있습니다.\n * 스냅 포인트를 지원하여 특정 높이에서 멈출 수 있습니다.\n * \n * Sheet component that slides up from the bottom of the screen.\n * Provides mobile-friendly UI and allows height adjustment by dragging.\n * Supports snap points to stop at specific heights.\n * \n * @component\n * @example\n * // 기본 사용 / Basic usage\n * const [open, setOpen] = useState(false)\n * \n * <BottomSheet open={open} onOpenChange={setOpen}>\n * <BottomSheetHeader>제목</BottomSheetHeader>\n * <BottomSheetContent>내용</BottomSheetContent>\n * </BottomSheet>\n * \n * @example\n * // 커스텀 스냅 포인트 / Custom snap points\n * <BottomSheet \n * open={open} \n * onOpenChange={setOpen}\n * snapPoints={[30, 60, 90]}\n * defaultSnap={30}\n * >\n * <BottomSheetContent>내용</BottomSheetContent>\n * </BottomSheet>\n * \n * @param {BottomSheetProps} props - BottomSheet 컴포넌트의 props / BottomSheet component props\n * @param {React.Ref<HTMLDivElement>} ref - BottomSheet 컨테이너 ref / BottomSheet container ref\n * @returns {JSX.Element} BottomSheet 컴포넌트 / BottomSheet component\n * \n * @todo 접근성 개선: role=\"dialog\", aria-modal=\"true\" 추가 필요 / Accessibility: Add role=\"dialog\", aria-modal=\"true\"\n * @todo 접근성 개선: aria-labelledby, aria-describedby 연결 필요 / Accessibility: Connect aria-labelledby, aria-describedby\n */\nconst BottomSheet = React.forwardRef<HTMLDivElement, BottomSheetProps>(\n ({\n isOpen,\n onClose,\n children,\n className,\n height = \"md\",\n showBackdrop = true,\n backdropClassName,\n closeOnBackdropClick = true,\n closeOnEscape = true,\n showDragHandle = true,\n closable = true,\n snapPoints = [25, 50, 75, 100],\n defaultSnap = 50,\n ...props\n }, ref) => {\n const _isOpen = isOpen ?? false\n const handleClose = () => {\n onClose?.()\n }\n\n const [isVisible, setIsVisible] = React.useState(false)\n const [isAnimating, setIsAnimating] = React.useState(false)\n const [currentHeight, setCurrentHeight] = React.useState(defaultSnap)\n const [isDragging, setIsDragging] = React.useState(false)\n const [startY, setStartY] = React.useState(0)\n const [currentY, setCurrentY] = React.useState(0)\n\n const heightClasses = {\n sm: \"h-64\",\n md: \"h-96\",\n lg: \"h-[32rem]\",\n xl: \"h-[40rem]\",\n full: \"h-full\"\n }\n\n React.useEffect(() => {\n if (_isOpen) {\n setIsVisible(true)\n setIsAnimating(true)\n const timer = setTimeout(() => setIsAnimating(false), 50)\n return () => clearTimeout(timer)\n } else {\n setIsAnimating(true)\n const timer = setTimeout(() => {\n setIsVisible(false)\n setIsAnimating(false)\n }, 300)\n return () => clearTimeout(timer)\n }\n }, [_isOpen])\n\n React.useEffect(() => {\n if (!closeOnEscape) return\n\n const handleEscapeKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && _isOpen) {\n handleClose()\n }\n }\n\n if (_isOpen) {\n document.addEventListener(\"keydown\", handleEscapeKey)\n document.body.style.overflow = \"hidden\"\n }\n\n return () => {\n document.removeEventListener(\"keydown\", handleEscapeKey)\n document.body.style.overflow = \"\"\n }\n }, [_isOpen, closeOnEscape])\n\n const handleTouchStart = (e: React.TouchEvent) => {\n setIsDragging(true)\n setStartY(e.touches[0].clientY)\n setCurrentY(e.touches[0].clientY)\n }\n\n const handleTouchMove = (e: React.TouchEvent) => {\n if (!isDragging) return\n setCurrentY(e.touches[0].clientY)\n }\n\n const handleTouchEnd = () => {\n if (!isDragging) return\n setIsDragging(false)\n\n const deltaY = currentY - startY\n const threshold = 100\n\n if (deltaY > threshold) {\n // 아래로 드래그 - 닫기\n handleClose()\n } else if (deltaY < -threshold) {\n // 위로 드래그 - 다음 스냅 포인트\n const currentIndex = snapPoints.indexOf(currentHeight)\n const nextIndex = Math.min(currentIndex + 1, snapPoints.length - 1)\n setCurrentHeight(snapPoints[nextIndex])\n }\n }\n\n if (!isVisible) return null\n\n return (\n <div className=\"fixed inset-0 z-50\">\n {/* Backdrop */}\n {showBackdrop && (\n <div\n className={merge(\n \"absolute inset-0 bg-black/85 backdrop-blur-md transition-opacity duration-300\",\n isAnimating ? (_isOpen ? \"opacity-100\" : \"opacity-0\") : \"\",\n backdropClassName\n )}\n onClick={closeOnBackdropClick ? handleClose : undefined}\n />\n )}\n\n {/* Bottom Sheet */}\n <div\n ref={ref}\n className={merge(\n \"absolute bottom-0 left-0 right-0 bg-background/95 backdrop-blur-xl border-t border-border/50 shadow-2xl rounded-t-lg transition-transform duration-300 ease-out pb-safe\",\n height !== \"full\" ? heightClasses[height] : \"\",\n isAnimating ? (_isOpen ? \"translate-y-0\" : \"translate-y-full\") : \"\",\n className\n )}\n style={{\n // height prop이 \"full\"일 때만 퍼센트 높이 사용 (스냅 포인트)\n // 그 외에는 heightClasses의 고정 높이 사용\n height: height === \"full\" ? `${currentHeight}%` : undefined,\n maxHeight: height !== \"full\" ? undefined : \"100%\",\n transform: isDragging ? `translateY(${currentY - startY}px)` : undefined\n }}\n onTouchStart={handleTouchStart}\n onTouchMove={handleTouchMove}\n onTouchEnd={handleTouchEnd}\n {...props}\n >\n {/* Drag Handle */}\n {showDragHandle && (\n <div className=\"flex justify-center pt-3 pb-2\">\n <div className=\"w-12 h-1.5 bg-muted-foreground/30 rounded-full\" />\n </div>\n )}\n\n {children}\n </div>\n </div>\n )\n }\n)\nBottomSheet.displayName = \"BottomSheet\"\n\n/**\n * BottomSheetHeader 컴포넌트의 props / BottomSheetHeader component props\n * @typedef {Object} BottomSheetHeaderProps\n * @property {React.ReactNode} children - 헤더 내용 / Header content\n * @property {string} [className] - 추가 CSS 클래스 / Additional CSS class\n * @property {boolean} [showCloseButton=true] - 닫기 버튼 표시 여부 / Show close button\n * @property {() => void} [onClose] - 닫기 버튼 클릭 콜백 / Close button click callback\n */\ninterface BottomSheetHeaderProps {\n children: React.ReactNode\n className?: string\n showCloseButton?: boolean\n onClose?: () => void\n}\n\n/**\n * BottomSheetHeader 컴포넌트 / BottomSheetHeader component\n * BottomSheet의 헤더 영역을 표시합니다.\n * Displays the header area of a BottomSheet.\n * \n * @component\n * @param {BottomSheetHeaderProps} props - BottomSheetHeader 컴포넌트의 props / BottomSheetHeader component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} BottomSheetHeader 컴포넌트 / BottomSheetHeader component\n */\nconst BottomSheetHeader = React.forwardRef<HTMLDivElement, BottomSheetHeaderProps>(\n ({ children, className, showCloseButton = true, onClose, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={merge(\"flex items-center justify-between px-6 py-4\", className)}\n {...props}\n >\n <div className=\"flex-1\">{children}</div>\n {showCloseButton && (\n <button\n onClick={onClose}\n className=\"p-2 rounded-lg hover:bg-muted transition-colors\"\n >\n <Icon name=\"close\" size={20} />\n </button>\n )}\n </div>\n )\n }\n)\nBottomSheetHeader.displayName = \"BottomSheetHeader\"\n\n/**\n * BottomSheetContent 컴포넌트의 props / BottomSheetContent component props\n * @typedef {Object} BottomSheetContentProps\n * @property {React.ReactNode} children - 콘텐츠 / Content\n * @property {string} [className] - 추가 CSS 클래스 / Additional CSS class\n */\ninterface BottomSheetContentProps {\n children: React.ReactNode\n className?: string\n}\n\n/**\n * BottomSheetContent 컴포넌트 / BottomSheetContent component\n * BottomSheet의 메인 콘텐츠 영역을 표시합니다.\n * Displays the main content area of a BottomSheet.\n * \n * @component\n * @param {BottomSheetContentProps} props - BottomSheetContent 컴포넌트의 props / BottomSheetContent component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} BottomSheetContent 컴포넌트 / BottomSheetContent component\n */\nconst BottomSheetContent = React.forwardRef<HTMLDivElement, BottomSheetContentProps>(\n ({ children, className, ...props }, ref) => {\n return (\n <div\n ref={ref}\n className={merge(\"flex-1 px-6 pb-6 overflow-y-auto\", className)}\n {...props}\n >\n {children}\n </div>\n )\n }\n)\nBottomSheetContent.displayName = \"BottomSheetContent\"\n\nexport { BottomSheet, BottomSheetHeader, BottomSheetContent } "]}