@hua-labs/ui 2.0.2 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/README.md +34 -161
  2. package/dist/{ComponentLayout-btJq4TjA.d.mts → ComponentLayout-DrZpz0yv.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.js +4 -4
  7. package/dist/advanced-dashboard.js.map +1 -1
  8. package/dist/advanced-dashboard.mjs +3 -3
  9. package/dist/advanced-dashboard.mjs.map +1 -1
  10. package/dist/advanced-emotion.mjs +1 -1
  11. package/dist/advanced-motion.d.mts +65 -1
  12. package/dist/advanced-motion.js +14 -14
  13. package/dist/advanced-motion.js.map +1 -1
  14. package/dist/advanced-motion.mjs +1 -1
  15. package/dist/advanced.d.mts +4 -4
  16. package/dist/advanced.js +16 -16
  17. package/dist/advanced.js.map +1 -1
  18. package/dist/advanced.mjs +3 -3
  19. package/dist/advanced.mjs.map +1 -1
  20. package/dist/chunk-3CCF7U3P.mjs +3 -0
  21. package/dist/{chunk-IFSEJVOR.mjs.map → chunk-3CCF7U3P.mjs.map} +1 -1
  22. package/dist/chunk-3GAUTZXQ.mjs +3 -0
  23. package/dist/{chunk-X7ZIWYRC.mjs.map → chunk-3GAUTZXQ.mjs.map} +1 -1
  24. package/dist/chunk-42RGFEL2.mjs +3 -0
  25. package/dist/chunk-42RGFEL2.mjs.map +1 -0
  26. package/dist/chunk-4NJE7D6X.mjs +3 -0
  27. package/dist/chunk-4NJE7D6X.mjs.map +1 -0
  28. package/dist/chunk-6HVJFEDA.mjs +3 -0
  29. package/dist/{chunk-FSL373O6.mjs.map → chunk-6HVJFEDA.mjs.map} +1 -1
  30. package/dist/chunk-7OYT3QSY.mjs +3 -0
  31. package/dist/chunk-7OYT3QSY.mjs.map +1 -0
  32. package/dist/chunk-ANYZ56VB.mjs +3 -0
  33. package/dist/{chunk-QQCELXFD.mjs.map → chunk-ANYZ56VB.mjs.map} +1 -1
  34. package/dist/chunk-AOSXB5JJ.mjs +4 -0
  35. package/dist/{chunk-GLZKT7JN.mjs.map → chunk-AOSXB5JJ.mjs.map} +1 -1
  36. package/dist/chunk-B544MRF7.mjs +3 -0
  37. package/dist/{chunk-SDFHJ4GB.mjs.map → chunk-B544MRF7.mjs.map} +1 -1
  38. package/dist/chunk-CVWWS25A.mjs +3 -0
  39. package/dist/chunk-CVWWS25A.mjs.map +1 -0
  40. package/dist/chunk-DYNBM24D.mjs +3 -0
  41. package/dist/{chunk-OSCMSA2Q.mjs.map → chunk-DYNBM24D.mjs.map} +1 -1
  42. package/dist/{chunk-NBJUE7NR.mjs → chunk-FX57OSYG.mjs} +2 -2
  43. package/dist/{chunk-NBJUE7NR.mjs.map → chunk-FX57OSYG.mjs.map} +1 -1
  44. package/dist/chunk-IJSYSNM5.mjs +3 -0
  45. package/dist/{chunk-IN7RWQCJ.mjs.map → chunk-IJSYSNM5.mjs.map} +1 -1
  46. package/dist/chunk-KJZGOL2Z.mjs +3 -0
  47. package/dist/{chunk-LOYAJIWO.mjs.map → chunk-KJZGOL2Z.mjs.map} +1 -1
  48. package/dist/chunk-KYRIUUQP.mjs +3 -0
  49. package/dist/{chunk-PAEKNQWW.mjs.map → chunk-KYRIUUQP.mjs.map} +1 -1
  50. package/dist/chunk-LSA7DU3N.mjs +73 -0
  51. package/dist/chunk-LSA7DU3N.mjs.map +1 -0
  52. package/dist/chunk-MDLCJASB.mjs +3 -0
  53. package/dist/{chunk-LH77I6HO.mjs.map → chunk-MDLCJASB.mjs.map} +1 -1
  54. package/dist/chunk-N56BUOCD.mjs +3 -0
  55. package/dist/{chunk-XV3Y7QVU.mjs.map → chunk-N56BUOCD.mjs.map} +1 -1
  56. package/dist/chunk-OFYITQXI.mjs +13 -0
  57. package/dist/chunk-OFYITQXI.mjs.map +1 -0
  58. package/dist/chunk-OZNST3EZ.mjs +3 -0
  59. package/dist/{chunk-SGEP3CQE.mjs.map → chunk-OZNST3EZ.mjs.map} +1 -1
  60. package/dist/chunk-RS6RKW5U.mjs +13 -0
  61. package/dist/{chunk-6KTHJ3EL.mjs.map → chunk-RS6RKW5U.mjs.map} +1 -1
  62. package/dist/{chunk-C4OACMTB.mjs → chunk-TXBZZJNR.mjs} +2 -2
  63. package/dist/{chunk-C4OACMTB.mjs.map → chunk-TXBZZJNR.mjs.map} +1 -1
  64. package/dist/chunk-TZ4YSHMC.mjs +3 -0
  65. package/dist/{chunk-UWHCM3S6.mjs.map → chunk-TZ4YSHMC.mjs.map} +1 -1
  66. package/dist/chunk-U6CTBZ2U.mjs +3 -0
  67. package/dist/chunk-U6CTBZ2U.mjs.map +1 -0
  68. package/dist/{chunk-5BMH7223.mjs → chunk-WP7VFE77.mjs} +2 -2
  69. package/dist/{chunk-5BMH7223.mjs.map → chunk-WP7VFE77.mjs.map} +1 -1
  70. package/dist/{chunk-FFH4ZFKS.mjs → chunk-XCZMLKPK.mjs} +2 -2
  71. package/dist/{chunk-FFH4ZFKS.mjs.map → chunk-XCZMLKPK.mjs.map} +1 -1
  72. package/dist/chunk-XGHT7WMO.mjs +3 -0
  73. package/dist/chunk-XGHT7WMO.mjs.map +1 -0
  74. package/dist/chunk-XL4KTJ4L.mjs +3 -0
  75. package/dist/{chunk-VWSBJUNI.mjs.map → chunk-XL4KTJ4L.mjs.map} +1 -1
  76. package/dist/chunk-Z74YUUVT.mjs +3 -0
  77. package/dist/chunk-Z74YUUVT.mjs.map +1 -0
  78. package/dist/chunk-ZXZIHU7J.mjs +8 -0
  79. package/dist/{chunk-N7M6RIN4.mjs.map → chunk-ZXZIHU7J.mjs.map} +1 -1
  80. package/dist/components/DatePicker.d.ts.map +1 -1
  81. package/dist/components/Modal.d.ts.map +1 -1
  82. package/dist/components/Popover.d.ts +2 -0
  83. package/dist/components/Popover.d.ts.map +1 -1
  84. package/dist/components/Progress.d.ts +1 -0
  85. package/dist/components/Progress.d.ts.map +1 -1
  86. package/dist/components/Section.d.ts +44 -0
  87. package/dist/components/Section.d.ts.map +1 -0
  88. package/dist/components/advanced/AnimatedGradient.d.ts.map +1 -1
  89. package/dist/components/advanced/DotNav.d.ts +26 -0
  90. package/dist/components/advanced/DotNav.d.ts.map +1 -0
  91. package/dist/components/advanced/HorizontalScroll.d.ts +20 -0
  92. package/dist/components/advanced/HorizontalScroll.d.ts.map +1 -0
  93. package/dist/components/advanced/ImageReveal.d.ts +24 -0
  94. package/dist/components/advanced/ImageReveal.d.ts.map +1 -0
  95. package/dist/components/advanced/index.d.ts +6 -0
  96. package/dist/components/advanced/index.d.ts.map +1 -1
  97. package/dist/data.mjs +2 -2
  98. package/dist/data.mjs.map +1 -1
  99. package/dist/feedback.mjs +1 -1
  100. package/dist/form.js +3 -3
  101. package/dist/form.js.map +1 -1
  102. package/dist/form.mjs +4 -4
  103. package/dist/form.mjs.map +1 -1
  104. package/dist/{icons-Bj_nr8Ba.d.mts → icons-DmhQEH_E.d.mts} +6 -1
  105. package/dist/index.d.mts +9 -27
  106. package/dist/index.d.ts +4 -0
  107. package/dist/index.d.ts.map +1 -1
  108. package/dist/index.js +6 -6
  109. package/dist/index.js.map +1 -1
  110. package/dist/index.mjs +2 -2
  111. package/dist/index.mjs.map +1 -1
  112. package/dist/interactive.js +1 -1
  113. package/dist/interactive.js.map +1 -1
  114. package/dist/interactive.mjs +1 -1
  115. package/dist/interactive.mjs.map +1 -1
  116. package/dist/landing/LandingAbout.d.ts +3 -0
  117. package/dist/landing/LandingAbout.d.ts.map +1 -0
  118. package/dist/landing/LandingCTA.d.ts +3 -0
  119. package/dist/landing/LandingCTA.d.ts.map +1 -0
  120. package/dist/landing/LandingContact.d.ts +3 -0
  121. package/dist/landing/LandingContact.d.ts.map +1 -0
  122. package/dist/landing/LandingExperience.d.ts +3 -0
  123. package/dist/landing/LandingExperience.d.ts.map +1 -0
  124. package/dist/landing/LandingFeatures.d.ts +3 -0
  125. package/dist/landing/LandingFeatures.d.ts.map +1 -0
  126. package/dist/landing/LandingHero.d.ts +3 -0
  127. package/dist/landing/LandingHero.d.ts.map +1 -0
  128. package/dist/landing/LandingLogoCloud.d.ts +3 -0
  129. package/dist/landing/LandingLogoCloud.d.ts.map +1 -0
  130. package/dist/landing/LandingMetrics.d.ts +3 -0
  131. package/dist/landing/LandingMetrics.d.ts.map +1 -0
  132. package/dist/landing/LandingProjects.d.ts +3 -0
  133. package/dist/landing/LandingProjects.d.ts.map +1 -0
  134. package/dist/landing/LandingProvider.d.ts +4 -0
  135. package/dist/landing/LandingProvider.d.ts.map +1 -0
  136. package/dist/landing/LandingShowcase.d.ts +3 -0
  137. package/dist/landing/LandingShowcase.d.ts.map +1 -0
  138. package/dist/landing/LandingSkills.d.ts +3 -0
  139. package/dist/landing/LandingSkills.d.ts.map +1 -0
  140. package/dist/landing/LandingStats.d.ts +3 -0
  141. package/dist/landing/LandingStats.d.ts.map +1 -0
  142. package/dist/landing/LandingTestimonials.d.ts +3 -0
  143. package/dist/landing/LandingTestimonials.d.ts.map +1 -0
  144. package/dist/landing/index.d.ts +47 -0
  145. package/dist/landing/index.d.ts.map +1 -0
  146. package/dist/landing/themes/app.d.ts +3 -0
  147. package/dist/landing/themes/app.d.ts.map +1 -0
  148. package/dist/landing/themes/corporate.d.ts +3 -0
  149. package/dist/landing/themes/corporate.d.ts.map +1 -0
  150. package/dist/landing/themes/dashboard.d.ts +3 -0
  151. package/dist/landing/themes/dashboard.d.ts.map +1 -0
  152. package/dist/landing/themes/immersive.d.ts +3 -0
  153. package/dist/landing/themes/immersive.d.ts.map +1 -0
  154. package/dist/landing/themes/index.d.ts +15 -0
  155. package/dist/landing/themes/index.d.ts.map +1 -0
  156. package/dist/landing/themes/marketing.d.ts +3 -0
  157. package/dist/landing/themes/marketing.d.ts.map +1 -0
  158. package/dist/landing/themes/portfolio.d.ts +3 -0
  159. package/dist/landing/themes/portfolio.d.ts.map +1 -0
  160. package/dist/landing/themes/product.d.ts +3 -0
  161. package/dist/landing/themes/product.d.ts.map +1 -0
  162. package/dist/landing/types.d.ts +346 -0
  163. package/dist/landing/types.d.ts.map +1 -0
  164. package/dist/landing.d.mts +417 -0
  165. package/dist/landing.js +100 -0
  166. package/dist/landing.js.map +1 -0
  167. package/dist/landing.mjs +31 -0
  168. package/dist/landing.mjs.map +1 -0
  169. package/dist/lib/icons.d.ts +6 -1
  170. package/dist/lib/icons.d.ts.map +1 -1
  171. package/dist/navigation.d.mts +1 -1
  172. package/dist/navigation.js +2 -2
  173. package/dist/navigation.js.map +1 -1
  174. package/dist/navigation.mjs +1 -1
  175. package/dist/navigation.mjs.map +1 -1
  176. package/dist/overlay.d.mts +2 -0
  177. package/dist/overlay.js +1 -1
  178. package/dist/overlay.js.map +1 -1
  179. package/dist/overlay.mjs +1 -1
  180. package/dist/overlay.mjs.map +1 -1
  181. package/dist/sdui.js +4 -4
  182. package/dist/sdui.js.map +1 -1
  183. package/dist/sdui.mjs +1 -1
  184. package/dist/sdui.mjs.map +1 -1
  185. package/package.json +18 -7
  186. package/src/styles/landing.css +107 -0
  187. package/src/styles/utilities.css +58 -0
  188. package/dist/chunk-6KTHJ3EL.mjs +0 -13
  189. package/dist/chunk-COR6CDMA.mjs +0 -83
  190. package/dist/chunk-COR6CDMA.mjs.map +0 -1
  191. package/dist/chunk-FSL373O6.mjs +0 -3
  192. package/dist/chunk-GLZKT7JN.mjs +0 -4
  193. package/dist/chunk-HN5LSP6L.mjs +0 -3
  194. package/dist/chunk-HN5LSP6L.mjs.map +0 -1
  195. package/dist/chunk-IFSEJVOR.mjs +0 -3
  196. package/dist/chunk-IN7RWQCJ.mjs +0 -3
  197. package/dist/chunk-LH77I6HO.mjs +0 -3
  198. package/dist/chunk-LOYAJIWO.mjs +0 -3
  199. package/dist/chunk-LPAG7DCA.mjs +0 -3
  200. package/dist/chunk-LPAG7DCA.mjs.map +0 -1
  201. package/dist/chunk-N7M6RIN4.mjs +0 -8
  202. package/dist/chunk-OSCMSA2Q.mjs +0 -3
  203. package/dist/chunk-PAEKNQWW.mjs +0 -3
  204. package/dist/chunk-QQCELXFD.mjs +0 -3
  205. package/dist/chunk-RPUS7G7Q.mjs +0 -3
  206. package/dist/chunk-RPUS7G7Q.mjs.map +0 -1
  207. package/dist/chunk-SDFHJ4GB.mjs +0 -3
  208. package/dist/chunk-SGEP3CQE.mjs +0 -3
  209. package/dist/chunk-UUHAXGMO.mjs +0 -3
  210. package/dist/chunk-UUHAXGMO.mjs.map +0 -1
  211. package/dist/chunk-UWHCM3S6.mjs +0 -3
  212. package/dist/chunk-VWSBJUNI.mjs +0 -3
  213. package/dist/chunk-X7ZIWYRC.mjs +0 -3
  214. package/dist/chunk-XV3Y7QVU.mjs +0 -3
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-B544MRF7.mjs';export{a as Modal}from'./chunk-B544MRF7.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-ANYZ56VB.mjs';export{a as Popover,c as PopoverContent,b as PopoverTrigger}from'./chunk-XGHT7WMO.mjs';import {d}from'./chunk-XCZMLKPK.mjs';import {l}from'./chunk-7OYT3QSY.mjs';import {b}from'./chunk-U6CTBZ2U.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$1,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$1=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:b("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$1}),m&&jsx("p",{className:b("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:b("flex gap-3","justify-center"),children:[b$1&&jsx(d,{variant:"outline",onClick:r,disabled:w,className:"px-6 py-3",children:D}),jsx(d,{variant:"default",onClick:c,disabled:M,className:b("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$1]=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$1(true),h(true);let t=setTimeout(()=>h(false),50);return ()=>clearTimeout(t)}else {h(true);let t=setTimeout(()=>{b$1(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:b("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:b("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:b("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:b("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 } "]}