@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
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/advanced/emotion/EmotionMeter.tsx","../src/components/advanced/emotion/EmotionButton.tsx","../src/components/advanced/emotion/EmotionSelector.tsx","../src/components/advanced/emotion/EmotionAnalysis.tsx"],"names":["EmotionMeter","React","className","value","max","size","color","props","ref","sizeClasses","emotionColors","percentage","jsx","merge","EmotionButton","emotion","isSelected","defaultEmotions","EmotionSelector","selectedEmotion","onEmotionSelect","layout","showIntensity","intensity","onIntensityChange","emotions","variant","handleEmotionClick","emotionKey","renderEmotionItem","jsxs","layoutClasses","e","EmotionAnalysis","primaryEmotion","emotionDistribution","keywords","positivity","energy","showMeter","showDistribution","showKeywords","showMetrics","getIntensityLabel","getPositivityLabel","getEnergyLabel","Fragment","keyword","Badge","Card","CardHeader","CardTitle","CardDescription","CardContent","item","index"],"mappings":"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","file":"chunk-5BMH7223.mjs","sourcesContent":["\"use client\"\n\nimport React from \"react\"\nimport { merge } from '../../../lib/utils';\nimport type { Color } from '../../../lib/types/common';\n\n/**\n * EmotionMeter 컴포넌트의 props / EmotionMeter component props\n * @typedef {Object} EmotionMeterProps\n * @property {number} value - 감정 강도 값 (0-max) / Emotion intensity value (0-max)\n * @property {number} [max=100] - 최대값 / Maximum value\n * @property {\"sm\" | \"md\" | \"lg\"} [size=\"md\"] - 미터 크기 / Meter size\n * @property {\"blue\" | \"green\" | \"yellow\" | \"red\"} [color=\"blue\"] - 미터 색상 / Meter color\n * @extends {React.HTMLAttributes<HTMLDivElement>}\n */\nexport interface EmotionMeterProps extends React.HTMLAttributes<HTMLDivElement> {\n value: number\n max?: number\n size?: \"sm\" | \"md\" | \"lg\"\n color?: \"blue\" | \"green\" | \"yellow\" | \"red\" | Color\n}\n\n/**\n * EmotionMeter 컴포넌트 / EmotionMeter component\n *\n * 감정 강도를 표시하는 미터 컴포넌트입니다.\n * Progress 컴포넌트와 유사하지만 감정 분석에 특화되어 있습니다.\n *\n * Meter component that displays emotion intensity.\n * Similar to Progress component but specialized for emotion analysis.\n *\n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <EmotionMeter value={75} />\n *\n * @example\n * // 다양한 색상 / Various colors\n * <EmotionMeter\n * value={80}\n * color=\"green\"\n * size=\"lg\"\n * />\n *\n * @param {EmotionMeterProps} props - EmotionMeter 컴포넌트의 props / EmotionMeter component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} EmotionMeter 컴포넌트 / EmotionMeter component\n */\nconst EmotionMeter = React.forwardRef<HTMLDivElement, EmotionMeterProps>(\n ({ className, value, max = 100, size = \"md\", color = \"blue\", ...props }, ref) => {\n const sizeClasses = {\n sm: \"h-2\",\n md: \"h-3\",\n lg: \"h-4\"\n }\n\n // EmotionMeter는 특정 색상만 사용 (감정 분석 특화)\n const emotionColors: Record<string, string> = {\n blue: \"bg-indigo-500\",\n green: \"bg-green-500\",\n yellow: \"bg-yellow-500\",\n red: \"bg-red-500\",\n // 추가 색상 지원\n purple: \"bg-purple-500\",\n orange: \"bg-orange-500\",\n indigo: \"bg-indigo-500\",\n pink: \"bg-pink-500\",\n gray: \"bg-gray-500\",\n }\n\n const percentage = Math.min(Math.max((value / max) * 100, 0), 100)\n\n return (\n <div\n ref={ref}\n className={merge(\n \"w-full bg-muted rounded-full\",\n sizeClasses[size],\n className\n )}\n {...props}\n >\n <div\n className={merge(\n \"h-full rounded-full transition-all duration-300\",\n emotionColors[color] || emotionColors.blue\n )}\n style={{ width: `${percentage}%` }}\n />\n </div>\n )\n }\n)\nEmotionMeter.displayName = \"EmotionMeter\"\n\nexport { EmotionMeter }\n","\"use client\"\n\nimport React from \"react\"\nimport { merge } from '../../../lib/utils';\n\n/**\n * EmotionButton 컴포넌트의 props / EmotionButton component props\n * @typedef {Object} EmotionButtonProps\n * @property {string} emotion - 감정 이모지 또는 텍스트 / Emotion emoji or text\n * @property {boolean} [isSelected=false] - 선택 상태 / Selected state\n * @property {\"sm\" | \"md\" | \"lg\"} [size=\"md\"] - 버튼 크기 / Button size\n * @extends {React.ButtonHTMLAttributes<HTMLButtonElement>}\n */\nexport interface EmotionButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n emotion: string\n isSelected?: boolean\n size?: \"sm\" | \"md\" | \"lg\"\n}\n\n/**\n * EmotionButton 컴포넌트 / EmotionButton component\n *\n * 감정을 선택하는 버튼 컴포넌트입니다.\n * 이모지나 텍스트로 감정을 표시하며, 선택 상태를 지원합니다.\n *\n * Button component for selecting emotions.\n * Displays emotion as emoji or text and supports selected state.\n *\n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <EmotionButton emotion=\"😊\" />\n *\n * @example\n * // 선택 상태 / Selected state\n * <EmotionButton\n * emotion=\"😊\"\n * isSelected\n * size=\"lg\"\n * />\n *\n * @param {EmotionButtonProps} props - EmotionButton 컴포넌트의 props / EmotionButton component props\n * @param {React.Ref<HTMLButtonElement>} ref - button 요소 ref / button element ref\n * @returns {JSX.Element} EmotionButton 컴포넌트 / EmotionButton component\n */\nconst EmotionButton = React.forwardRef<HTMLButtonElement, EmotionButtonProps>(\n ({ className, emotion, isSelected = false, size = \"md\", ...props }, ref) => {\n const sizeClasses = {\n sm: \"w-8 h-8 text-sm\",\n md: \"w-12 h-12 text-lg\",\n lg: \"w-16 h-16 text-xl\"\n }\n\n return (\n <button\n ref={ref}\n className={merge(\n \"rounded-full border-2 transition-all duration-200 hover:scale-105 focus:outline-none focus:ring-1 focus:ring-ring\",\n sizeClasses[size],\n isSelected\n ? \"border-indigo-500 bg-indigo-50 dark:bg-indigo-900/20\"\n : \"border-border bg-background\",\n className\n )}\n {...props}\n >\n {emotion}\n </button>\n )\n }\n)\nEmotionButton.displayName = \"EmotionButton\"\n\nexport { EmotionButton }\n","'use client'\n\nimport React from \"react\"\nimport { EmotionButton } from \"./EmotionButton\"\nimport { EmotionMeter } from \"./EmotionMeter\"\nimport { merge } from '../../../lib/utils';\n\n/**\n * EmotionSelector 컴포넌트의 props / EmotionSelector component props\n * @typedef {Object} EmotionSelectorProps\n * @property {string} [selectedEmotion] - 선택된 감정 키 / Selected emotion key\n * @property {(emotion: string) => void} [onEmotionSelect] - 감정 선택 콜백 / Emotion selection callback\n * @property {\"grid\" | \"list\" | \"compact\"} [layout=\"grid\"] - 레이아웃 타입 / Layout type\n * @property {boolean} [showIntensity=false] - 강도 조절 표시 여부 / Show intensity control\n * @property {number} [intensity=50] - 감정 강도 (0-100) / Emotion intensity (0-100)\n * @property {(intensity: number) => void} [onIntensityChange] - 강도 변경 콜백 / Intensity change callback\n * @property {Array<Object>} [emotions] - 감정 목록 / Emotions list\n * @property {string} emotions[].key - 감정 키 / Emotion key\n * @property {string} emotions[].label - 감정 라벨 / Emotion label\n * @property {string} [emotions[].icon] - 감정 아이콘 / Emotion icon\n * @property {string} [emotions[].color] - 감정 색상 / Emotion color\n * @property {\"sm\" | \"md\" | \"lg\"} [size=\"md\"] - 감정 버튼 크기 / Emotion button size\n * @property {\"button\" | \"card\" | \"chip\"} [variant=\"button\"] - 감정 표시 스타일 / Emotion display style\n * @extends {React.HTMLAttributes<HTMLDivElement>}\n */\ninterface EmotionSelectorProps extends React.HTMLAttributes<HTMLDivElement> {\n selectedEmotion?: string\n onEmotionSelect?: (emotion: string) => void\n layout?: \"grid\" | \"list\" | \"compact\"\n showIntensity?: boolean\n intensity?: number\n onIntensityChange?: (intensity: number) => void\n emotions?: Array<{\n key: string\n label: string\n icon?: string\n color?: string\n }>\n size?: \"sm\" | \"md\" | \"lg\"\n variant?: \"button\" | \"card\" | \"chip\"\n}\n\nconst defaultEmotions = [\n { key: \"joy\", label: \"기쁨\", icon: \"smile\", color: \"yellow\" },\n { key: \"sadness\", label: \"슬픔\", icon: \"frown\", color: \"blue\" },\n { key: \"anger\", label: \"화남\", icon: \"angry\", color: \"red\" },\n { key: \"calm\", label: \"평온\", icon: \"heart\", color: \"green\" },\n { key: \"excitement\", label: \"설렘\", icon: \"star\", color: \"pink\" },\n { key: \"worry\", label: \"걱정\", icon: \"meh\", color: \"gray\" },\n { key: \"gratitude\", label: \"감사\", icon: \"heart\", color: \"purple\" },\n { key: \"loneliness\", label: \"외로움\", icon: \"user\", color: \"indigo\" }\n]\n\n/**\n * EmotionSelector 컴포넌트 / EmotionSelector component\n *\n * 감정을 선택하는 컴포넌트입니다.\n * 여러 감정 옵션을 제공하며, 강도 조절 기능을 포함할 수 있습니다.\n *\n * Component for selecting emotions.\n * Provides multiple emotion options and can include intensity control.\n *\n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <EmotionSelector\n * selectedEmotion=\"joy\"\n * onEmotionSelect={(emotion) => console.log(emotion)}\n * />\n *\n * @example\n * // 강도 조절 포함 / With intensity control\n * <EmotionSelector\n * selectedEmotion=\"calm\"\n * onEmotionSelect={handleEmotionSelect}\n * showIntensity\n * intensity={intensity}\n * onIntensityChange={setIntensity}\n * variant=\"card\"\n * />\n *\n * @param {EmotionSelectorProps} props - EmotionSelector 컴포넌트의 props / EmotionSelector component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} EmotionSelector 컴포넌트 / EmotionSelector component\n */\nconst EmotionSelector = React.forwardRef<HTMLDivElement, EmotionSelectorProps>(\n ({\n className,\n selectedEmotion,\n onEmotionSelect,\n layout = \"grid\",\n showIntensity = false,\n intensity = 50,\n onIntensityChange,\n emotions = defaultEmotions,\n size = \"md\",\n variant = \"button\",\n ...props\n }, ref) => {\n const handleEmotionClick = (emotionKey: string) => {\n onEmotionSelect?.(emotionKey)\n }\n\n const renderEmotionItem = (emotion: typeof emotions[0]) => {\n const isSelected = selectedEmotion === emotion.key\n\n if (variant === \"button\") {\n return (\n <EmotionButton\n key={emotion.key}\n emotion={emotion.key}\n isSelected={isSelected}\n size={size}\n onClick={() => handleEmotionClick(emotion.key)}\n className={merge(\n \"transition-all duration-200\",\n isSelected && \"ring-1 ring-offset-2 ring-primary\"\n )}\n >\n {emotion.label}\n </EmotionButton>\n )\n }\n\n if (variant === \"card\") {\n return (\n <div\n key={emotion.key}\n className={merge(\n \"p-4 rounded-lg border-2 cursor-pointer transition-all duration-200 hover:shadow-md\",\n isSelected\n ? \"border-primary bg-primary/5\"\n : \"border-border hover:border-primary/50\"\n )}\n onClick={() => handleEmotionClick(emotion.key)}\n >\n <div className=\"flex items-center space-x-3\">\n <div className={merge(\n \"w-8 h-8 rounded-full flex items-center justify-center\",\n isSelected ? \"bg-primary text-primary-foreground\" : \"bg-muted\"\n )}>\n {emotion.icon && (\n <span className=\"text-lg\">\n {emotion.icon === \"smile\" && \"😊\"}\n {emotion.icon === \"frown\" && \"😢\"}\n {emotion.icon === \"angry\" && \"😠\"}\n {emotion.icon === \"heart\" && \"❤️\"}\n {emotion.icon === \"star\" && \"⭐\"}\n {emotion.icon === \"meh\" && \"😐\"}\n {emotion.icon === \"user\" && \"👤\"}\n </span>\n )}\n </div>\n <span className=\"font-medium truncate max-w-[120px]\">{emotion.label}</span>\n </div>\n </div>\n )\n }\n\n if (variant === \"chip\") {\n return (\n <div\n key={emotion.key}\n className={merge(\n \"px-3 py-1 rounded-full cursor-pointer transition-all duration-200 text-sm font-medium\",\n isSelected\n ? \"bg-primary text-primary-foreground\"\n : \"bg-muted hover:bg-muted/80\"\n )}\n onClick={() => handleEmotionClick(emotion.key)}\n >\n <span className=\"truncate max-w-[100px]\">{emotion.label}</span>\n </div>\n )\n }\n\n return null\n }\n\n const layoutClasses = {\n grid: \"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2 md:gap-3\",\n list: \"space-y-2\",\n compact: \"flex flex-wrap gap-1\"\n }\n\n return (\n <div\n ref={ref}\n className={merge(\"space-y-4\", className)}\n {...props}\n >\n <div className={layoutClasses[layout]}>\n {emotions.map(renderEmotionItem)}\n </div>\n\n {showIntensity && selectedEmotion && (\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium\">감정 강도</span>\n <span className=\"text-sm text-muted-foreground\">{intensity}%</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n value={intensity}\n onChange={(e) => onIntensityChange?.(Number(e.target.value))}\n className=\"w-full h-2 bg-muted rounded-lg appearance-none cursor-pointer slider\"\n />\n <div className=\"flex justify-between text-xs text-muted-foreground\">\n <span>약함</span>\n <span>보통</span>\n <span>강함</span>\n </div>\n </div>\n )}\n\n {selectedEmotion && showIntensity && (\n <div className=\"flex justify-center\">\n <EmotionMeter\n value={intensity}\n size=\"md\"\n color=\"blue\"\n />\n </div>\n )}\n </div>\n )\n }\n)\n\nEmotionSelector.displayName = \"EmotionSelector\"\n\nexport { EmotionSelector }\nexport type { EmotionSelectorProps }\n","'use client'\n\nimport React from \"react\"\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../../Card';\nimport { Badge } from '../../Badge';\nimport { merge } from '../../../lib/utils';\nimport { EmotionMeter } from \"./EmotionMeter\"\n\n/**\n * EmotionAnalysis 컴포넌트의 props / EmotionAnalysis component props\n * @typedef {Object} EmotionAnalysisProps\n * @property {Object} [primaryEmotion] - 주요 감정 정보 / Primary emotion information\n * @property {string} primaryEmotion.name - 감정 이름 / Emotion name\n * @property {number} primaryEmotion.intensity - 감정 강도 (0-100) / Emotion intensity (0-100)\n * @property {string} [primaryEmotion.color] - 감정 색상 / Emotion color\n * @property {Array<Object>} [emotionDistribution] - 감정 분포 배열 / Emotion distribution array\n * @property {string} emotionDistribution[].emotion - 감정 이름 / Emotion name\n * @property {number} emotionDistribution[].percentage - 감정 비율 (0-100) / Emotion percentage (0-100)\n * @property {string} emotionDistribution[].color - 감정 색상 / Emotion color\n * @property {string[]} [keywords] - 키워드 배열 / Keywords array\n * @property {number} [intensity=50] - 전체 강도 (0-100) / Overall intensity (0-100)\n * @property {number} [positivity=70] - 긍정성 (0-100) / Positivity (0-100)\n * @property {number} [energy=60] - 에너지 (0-100) / Energy (0-100)\n * @property {boolean} [showMeter=true] - 강도 미터 표시 여부 / Show intensity meter\n * @property {boolean} [showDistribution=true] - 분포 표시 여부 / Show distribution\n * @property {boolean} [showKeywords=true] - 키워드 표시 여부 / Show keywords\n * @property {boolean} [showMetrics=true] - 메트릭 표시 여부 / Show metrics\n * @property {\"compact\" | \"detailed\" | \"card\"} [layout=\"detailed\"] - 레이아웃 타입 / Layout type\n * @extends {React.HTMLAttributes<HTMLDivElement>}\n */\ninterface EmotionAnalysisProps extends React.HTMLAttributes<HTMLDivElement> {\n primaryEmotion?: {\n name: string\n intensity: number\n color?: string\n }\n emotionDistribution?: Array<{\n emotion: string\n percentage: number\n color: string\n }>\n keywords?: string[]\n intensity?: number\n positivity?: number\n energy?: number\n showMeter?: boolean\n showDistribution?: boolean\n showKeywords?: boolean\n showMetrics?: boolean\n layout?: \"compact\" | \"detailed\" | \"card\"\n}\n\n/**\n * EmotionAnalysis 컴포넌트 / EmotionAnalysis component\n *\n * 감정 분석 결과를 표시하는 컴포넌트입니다.\n * 주요 감정, 감정 분포, 키워드, 메트릭(강도, 긍정성, 에너지)을 표시할 수 있습니다.\n *\n * Component that displays emotion analysis results.\n * Can display primary emotion, emotion distribution, keywords, and metrics (intensity, positivity, energy).\n *\n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <EmotionAnalysis\n * primaryEmotion={{ name: \"기쁨\", intensity: 80 }}\n * keywords={[\"행복\", \"만족\"]}\n * />\n *\n * @example\n * // 상세 레이아웃 / Detailed layout\n * <EmotionAnalysis\n * primaryEmotion={{ name: \"평온\", intensity: 65, color: \"green\" }}\n * emotionDistribution={[\n * { emotion: \"기쁨\", percentage: 40, color: \"yellow\" },\n * { emotion: \"평온\", percentage: 60, color: \"green\" }\n * ]}\n * keywords={[\"안정\", \"편안\"]}\n * intensity={65}\n * positivity={75}\n * energy={50}\n * layout=\"detailed\"\n * />\n *\n * @param {EmotionAnalysisProps} props - EmotionAnalysis 컴포넌트의 props / EmotionAnalysis component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} EmotionAnalysis 컴포넌트 / EmotionAnalysis component\n */\nconst EmotionAnalysis = React.forwardRef<HTMLDivElement, EmotionAnalysisProps>(\n ({\n className,\n primaryEmotion,\n emotionDistribution = [],\n keywords = [],\n intensity = 50,\n positivity = 70,\n energy = 60,\n showMeter = true,\n showDistribution = true,\n showKeywords = true,\n showMetrics = true,\n layout = \"detailed\",\n ...props\n }, ref) => {\n const getIntensityLabel = (value: number) => {\n if (value < 30) return \"약함\"\n if (value < 70) return \"보통\"\n return \"강함\"\n }\n\n const getPositivityLabel = (value: number) => {\n if (value < 30) return \"부정적\"\n if (value < 70) return \"중립적\"\n return \"긍정적\"\n }\n\n const getEnergyLabel = (value: number) => {\n if (value < 30) return \"낮음\"\n if (value < 70) return \"보통\"\n return \"높음\"\n }\n\n if (layout === \"compact\") {\n return (\n <div\n ref={ref}\n className={merge(\"space-y-3\", className)}\n {...props}\n >\n {primaryEmotion && (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium\">주요 감정:</span>\n <div className=\"flex items-center space-x-2\">\n <span className=\"text-sm text-muted-foreground\">\n {primaryEmotion.name} ({primaryEmotion.intensity}%)\n </span>\n {showMeter && (\n <EmotionMeter\n value={primaryEmotion.intensity}\n size=\"sm\"\n color=\"blue\"\n />\n )}\n </div>\n </div>\n )}\n\n {showMetrics && (\n <>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium\">감정 강도:</span>\n <span className=\"text-sm text-muted-foreground\">\n {getIntensityLabel(intensity)}\n </span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium\">긍정성:</span>\n <span className=\"text-sm text-muted-foreground\">\n {getPositivityLabel(positivity)}\n </span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium\">에너지:</span>\n <span className=\"text-sm text-muted-foreground\">\n {getEnergyLabel(energy)}\n </span>\n </div>\n </>\n )}\n\n {showKeywords && keywords.length > 0 && (\n <div>\n <span className=\"text-sm font-medium\">키워드:</span>\n <div className=\"flex flex-wrap gap-1 mt-1\">\n {keywords.map((keyword) => (\n <Badge key={keyword} variant=\"secondary\" className=\"text-xs\">\n {keyword}\n </Badge>\n ))}\n </div>\n </div>\n )}\n </div>\n )\n }\n\n if (layout === \"card\") {\n return (\n <Card\n ref={ref}\n className={merge(\"\", className)}\n {...props}\n >\n <CardHeader>\n <CardTitle className=\"flex items-center\">\n <span className=\"text-2xl mr-2\">✨</span>\n AI 분석\n </CardTitle>\n <CardDescription>\n 감정 분석 결과\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {primaryEmotion && (\n <div className=\"space-y-3\">\n <div className=\"text-sm\">\n <span className=\"font-medium\">주요 감정:</span>\n <span className=\"ml-2 text-muted-foreground\">\n {primaryEmotion.name} ({primaryEmotion.intensity}%)\n </span>\n </div>\n {showMeter && (\n <div className=\"flex justify-center\">\n <EmotionMeter\n value={primaryEmotion.intensity}\n size=\"md\"\n color=\"blue\"\n />\n </div>\n )}\n </div>\n )}\n\n {showMetrics && (\n <>\n <div className=\"text-sm\">\n <span className=\"font-medium\">감정 강도:</span>\n <span className=\"ml-2 text-muted-foreground\">\n {getIntensityLabel(intensity)}\n </span>\n </div>\n <div className=\"text-sm\">\n <span className=\"font-medium\">긍정성:</span>\n <span className=\"ml-2 text-muted-foreground\">\n {getPositivityLabel(positivity)}\n </span>\n </div>\n <div className=\"text-sm\">\n <span className=\"font-medium\">에너지:</span>\n <span className=\"ml-2 text-muted-foreground\">\n {getEnergyLabel(energy)}\n </span>\n </div>\n </>\n )}\n\n {showKeywords && keywords.length > 0 && (\n <div className=\"text-sm\">\n <span className=\"font-medium\">키워드:</span>\n <div className=\"flex flex-wrap gap-1 mt-1\">\n {keywords.map((keyword) => (\n <Badge key={keyword} variant=\"secondary\" className=\"text-xs\">\n {keyword}\n </Badge>\n ))}\n </div>\n </div>\n )}\n </CardContent>\n </Card>\n )\n }\n\n // detailed layout (default)\n return (\n <div\n ref={ref}\n className={merge(\"space-y-6\", className)}\n {...props}\n >\n {primaryEmotion && (\n <div className=\"space-y-4\">\n <h3 className=\"text-lg font-semibold\">주요 감정</h3>\n <div className=\"flex items-center space-x-4\">\n <div className=\"text-center\">\n <div className=\"text-2xl font-bold text-primary\">\n {primaryEmotion.name}\n </div>\n <div className=\"text-sm text-muted-foreground\">\n {primaryEmotion.intensity}% 강도\n </div>\n </div>\n {showMeter && (\n <EmotionMeter\n value={primaryEmotion.intensity}\n size=\"lg\"\n color=\"blue\"\n />\n )}\n </div>\n </div>\n )}\n\n {showDistribution && emotionDistribution.length > 0 && (\n <div className=\"space-y-4\">\n <h3 className=\"text-lg font-semibold\">감정 분포</h3>\n <div className=\"space-y-3\">\n {emotionDistribution.map((item, index) => (\n <div key={index} className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium\">{item.emotion}</span>\n <span className=\"text-sm text-muted-foreground\">\n {item.percentage}%\n </span>\n </div>\n <div className=\"w-full bg-muted rounded-full h-2\">\n <div\n className={`${item.color} h-2 rounded-full transition-all duration-300`}\n style={{ width: `${item.percentage}%` }}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {showMetrics && (\n <div className=\"space-y-4\">\n <h3 className=\"text-lg font-semibold\">분석 지표</h3>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n <div className=\"space-y-2\">\n <div className=\"text-sm font-medium\">감정 강도</div>\n <div className=\"text-2xl font-bold text-primary\">\n {getIntensityLabel(intensity)}\n </div>\n <div className=\"w-full bg-muted rounded-full h-2\">\n <div\n className=\"bg-primary h-2 rounded-full transition-all duration-300\"\n style={{ width: `${intensity}%` }}\n />\n </div>\n </div>\n <div className=\"space-y-2\">\n <div className=\"text-sm font-medium\">긍정성</div>\n <div className=\"text-2xl font-bold text-green-600\">\n {getPositivityLabel(positivity)}\n </div>\n <div className=\"w-full bg-muted rounded-full h-2\">\n <div\n className=\"bg-green-500 h-2 rounded-full transition-all duration-300\"\n style={{ width: `${positivity}%` }}\n />\n </div>\n </div>\n <div className=\"space-y-2\">\n <div className=\"text-sm font-medium\">에너지</div>\n <div className=\"text-2xl font-bold text-orange-600\">\n {getEnergyLabel(energy)}\n </div>\n <div className=\"w-full bg-muted rounded-full h-2\">\n <div\n className=\"bg-orange-500 h-2 rounded-full transition-all duration-300\"\n style={{ width: `${energy}%` }}\n />\n </div>\n </div>\n </div>\n </div>\n )}\n\n {showKeywords && keywords.length > 0 && (\n <div className=\"space-y-4\">\n <h3 className=\"text-lg font-semibold\">감정 키워드</h3>\n <div className=\"flex flex-wrap gap-2\">\n {keywords.map((keyword) => (\n <Badge key={keyword} variant=\"outline\" className=\"text-sm\">\n {keyword}\n </Badge>\n ))}\n </div>\n </div>\n )}\n </div>\n )\n }\n)\n\nEmotionAnalysis.displayName = \"EmotionAnalysis\"\n\nexport { EmotionAnalysis }\nexport type { EmotionAnalysisProps }\n"]}
1
+ {"version":3,"sources":["../src/components/advanced/emotion/EmotionMeter.tsx","../src/components/advanced/emotion/EmotionButton.tsx","../src/components/advanced/emotion/EmotionSelector.tsx","../src/components/advanced/emotion/EmotionAnalysis.tsx"],"names":["EmotionMeter","React","className","value","max","size","color","props","ref","sizeClasses","emotionColors","percentage","jsx","merge","EmotionButton","emotion","isSelected","defaultEmotions","EmotionSelector","selectedEmotion","onEmotionSelect","layout","showIntensity","intensity","onIntensityChange","emotions","variant","handleEmotionClick","emotionKey","renderEmotionItem","jsxs","layoutClasses","e","EmotionAnalysis","primaryEmotion","emotionDistribution","keywords","positivity","energy","showMeter","showDistribution","showKeywords","showMetrics","getIntensityLabel","getPositivityLabel","getEnergyLabel","Fragment","keyword","Badge","Card","CardHeader","CardTitle","CardDescription","CardContent","item","index"],"mappings":"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","file":"chunk-WP7VFE77.mjs","sourcesContent":["\"use client\"\n\nimport React from \"react\"\nimport { merge } from '../../../lib/utils';\nimport type { Color } from '../../../lib/types/common';\n\n/**\n * EmotionMeter 컴포넌트의 props / EmotionMeter component props\n * @typedef {Object} EmotionMeterProps\n * @property {number} value - 감정 강도 값 (0-max) / Emotion intensity value (0-max)\n * @property {number} [max=100] - 최대값 / Maximum value\n * @property {\"sm\" | \"md\" | \"lg\"} [size=\"md\"] - 미터 크기 / Meter size\n * @property {\"blue\" | \"green\" | \"yellow\" | \"red\"} [color=\"blue\"] - 미터 색상 / Meter color\n * @extends {React.HTMLAttributes<HTMLDivElement>}\n */\nexport interface EmotionMeterProps extends React.HTMLAttributes<HTMLDivElement> {\n value: number\n max?: number\n size?: \"sm\" | \"md\" | \"lg\"\n color?: \"blue\" | \"green\" | \"yellow\" | \"red\" | Color\n}\n\n/**\n * EmotionMeter 컴포넌트 / EmotionMeter component\n *\n * 감정 강도를 표시하는 미터 컴포넌트입니다.\n * Progress 컴포넌트와 유사하지만 감정 분석에 특화되어 있습니다.\n *\n * Meter component that displays emotion intensity.\n * Similar to Progress component but specialized for emotion analysis.\n *\n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <EmotionMeter value={75} />\n *\n * @example\n * // 다양한 색상 / Various colors\n * <EmotionMeter\n * value={80}\n * color=\"green\"\n * size=\"lg\"\n * />\n *\n * @param {EmotionMeterProps} props - EmotionMeter 컴포넌트의 props / EmotionMeter component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} EmotionMeter 컴포넌트 / EmotionMeter component\n */\nconst EmotionMeter = React.forwardRef<HTMLDivElement, EmotionMeterProps>(\n ({ className, value, max = 100, size = \"md\", color = \"blue\", ...props }, ref) => {\n const sizeClasses = {\n sm: \"h-2\",\n md: \"h-3\",\n lg: \"h-4\"\n }\n\n // EmotionMeter는 특정 색상만 사용 (감정 분석 특화)\n const emotionColors: Record<string, string> = {\n blue: \"bg-indigo-500\",\n green: \"bg-green-500\",\n yellow: \"bg-yellow-500\",\n red: \"bg-red-500\",\n // 추가 색상 지원\n purple: \"bg-purple-500\",\n orange: \"bg-orange-500\",\n indigo: \"bg-indigo-500\",\n pink: \"bg-pink-500\",\n gray: \"bg-gray-500\",\n }\n\n const percentage = Math.min(Math.max((value / max) * 100, 0), 100)\n\n return (\n <div\n ref={ref}\n className={merge(\n \"w-full bg-muted rounded-full\",\n sizeClasses[size],\n className\n )}\n {...props}\n >\n <div\n className={merge(\n \"h-full rounded-full transition-all duration-300\",\n emotionColors[color] || emotionColors.blue\n )}\n style={{ width: `${percentage}%` }}\n />\n </div>\n )\n }\n)\nEmotionMeter.displayName = \"EmotionMeter\"\n\nexport { EmotionMeter }\n","\"use client\"\n\nimport React from \"react\"\nimport { merge } from '../../../lib/utils';\n\n/**\n * EmotionButton 컴포넌트의 props / EmotionButton component props\n * @typedef {Object} EmotionButtonProps\n * @property {string} emotion - 감정 이모지 또는 텍스트 / Emotion emoji or text\n * @property {boolean} [isSelected=false] - 선택 상태 / Selected state\n * @property {\"sm\" | \"md\" | \"lg\"} [size=\"md\"] - 버튼 크기 / Button size\n * @extends {React.ButtonHTMLAttributes<HTMLButtonElement>}\n */\nexport interface EmotionButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n emotion: string\n isSelected?: boolean\n size?: \"sm\" | \"md\" | \"lg\"\n}\n\n/**\n * EmotionButton 컴포넌트 / EmotionButton component\n *\n * 감정을 선택하는 버튼 컴포넌트입니다.\n * 이모지나 텍스트로 감정을 표시하며, 선택 상태를 지원합니다.\n *\n * Button component for selecting emotions.\n * Displays emotion as emoji or text and supports selected state.\n *\n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <EmotionButton emotion=\"😊\" />\n *\n * @example\n * // 선택 상태 / Selected state\n * <EmotionButton\n * emotion=\"😊\"\n * isSelected\n * size=\"lg\"\n * />\n *\n * @param {EmotionButtonProps} props - EmotionButton 컴포넌트의 props / EmotionButton component props\n * @param {React.Ref<HTMLButtonElement>} ref - button 요소 ref / button element ref\n * @returns {JSX.Element} EmotionButton 컴포넌트 / EmotionButton component\n */\nconst EmotionButton = React.forwardRef<HTMLButtonElement, EmotionButtonProps>(\n ({ className, emotion, isSelected = false, size = \"md\", ...props }, ref) => {\n const sizeClasses = {\n sm: \"w-8 h-8 text-sm\",\n md: \"w-12 h-12 text-lg\",\n lg: \"w-16 h-16 text-xl\"\n }\n\n return (\n <button\n ref={ref}\n className={merge(\n \"rounded-full border-2 transition-all duration-200 hover:scale-105 focus:outline-none focus:ring-1 focus:ring-ring\",\n sizeClasses[size],\n isSelected\n ? \"border-indigo-500 bg-indigo-50 dark:bg-indigo-900/20\"\n : \"border-border bg-background\",\n className\n )}\n {...props}\n >\n {emotion}\n </button>\n )\n }\n)\nEmotionButton.displayName = \"EmotionButton\"\n\nexport { EmotionButton }\n","'use client'\n\nimport React from \"react\"\nimport { EmotionButton } from \"./EmotionButton\"\nimport { EmotionMeter } from \"./EmotionMeter\"\nimport { merge } from '../../../lib/utils';\n\n/**\n * EmotionSelector 컴포넌트의 props / EmotionSelector component props\n * @typedef {Object} EmotionSelectorProps\n * @property {string} [selectedEmotion] - 선택된 감정 키 / Selected emotion key\n * @property {(emotion: string) => void} [onEmotionSelect] - 감정 선택 콜백 / Emotion selection callback\n * @property {\"grid\" | \"list\" | \"compact\"} [layout=\"grid\"] - 레이아웃 타입 / Layout type\n * @property {boolean} [showIntensity=false] - 강도 조절 표시 여부 / Show intensity control\n * @property {number} [intensity=50] - 감정 강도 (0-100) / Emotion intensity (0-100)\n * @property {(intensity: number) => void} [onIntensityChange] - 강도 변경 콜백 / Intensity change callback\n * @property {Array<Object>} [emotions] - 감정 목록 / Emotions list\n * @property {string} emotions[].key - 감정 키 / Emotion key\n * @property {string} emotions[].label - 감정 라벨 / Emotion label\n * @property {string} [emotions[].icon] - 감정 아이콘 / Emotion icon\n * @property {string} [emotions[].color] - 감정 색상 / Emotion color\n * @property {\"sm\" | \"md\" | \"lg\"} [size=\"md\"] - 감정 버튼 크기 / Emotion button size\n * @property {\"button\" | \"card\" | \"chip\"} [variant=\"button\"] - 감정 표시 스타일 / Emotion display style\n * @extends {React.HTMLAttributes<HTMLDivElement>}\n */\ninterface EmotionSelectorProps extends React.HTMLAttributes<HTMLDivElement> {\n selectedEmotion?: string\n onEmotionSelect?: (emotion: string) => void\n layout?: \"grid\" | \"list\" | \"compact\"\n showIntensity?: boolean\n intensity?: number\n onIntensityChange?: (intensity: number) => void\n emotions?: Array<{\n key: string\n label: string\n icon?: string\n color?: string\n }>\n size?: \"sm\" | \"md\" | \"lg\"\n variant?: \"button\" | \"card\" | \"chip\"\n}\n\nconst defaultEmotions = [\n { key: \"joy\", label: \"기쁨\", icon: \"smile\", color: \"yellow\" },\n { key: \"sadness\", label: \"슬픔\", icon: \"frown\", color: \"blue\" },\n { key: \"anger\", label: \"화남\", icon: \"angry\", color: \"red\" },\n { key: \"calm\", label: \"평온\", icon: \"heart\", color: \"green\" },\n { key: \"excitement\", label: \"설렘\", icon: \"star\", color: \"pink\" },\n { key: \"worry\", label: \"걱정\", icon: \"meh\", color: \"gray\" },\n { key: \"gratitude\", label: \"감사\", icon: \"heart\", color: \"purple\" },\n { key: \"loneliness\", label: \"외로움\", icon: \"user\", color: \"indigo\" }\n]\n\n/**\n * EmotionSelector 컴포넌트 / EmotionSelector component\n *\n * 감정을 선택하는 컴포넌트입니다.\n * 여러 감정 옵션을 제공하며, 강도 조절 기능을 포함할 수 있습니다.\n *\n * Component for selecting emotions.\n * Provides multiple emotion options and can include intensity control.\n *\n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <EmotionSelector\n * selectedEmotion=\"joy\"\n * onEmotionSelect={(emotion) => console.log(emotion)}\n * />\n *\n * @example\n * // 강도 조절 포함 / With intensity control\n * <EmotionSelector\n * selectedEmotion=\"calm\"\n * onEmotionSelect={handleEmotionSelect}\n * showIntensity\n * intensity={intensity}\n * onIntensityChange={setIntensity}\n * variant=\"card\"\n * />\n *\n * @param {EmotionSelectorProps} props - EmotionSelector 컴포넌트의 props / EmotionSelector component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} EmotionSelector 컴포넌트 / EmotionSelector component\n */\nconst EmotionSelector = React.forwardRef<HTMLDivElement, EmotionSelectorProps>(\n ({\n className,\n selectedEmotion,\n onEmotionSelect,\n layout = \"grid\",\n showIntensity = false,\n intensity = 50,\n onIntensityChange,\n emotions = defaultEmotions,\n size = \"md\",\n variant = \"button\",\n ...props\n }, ref) => {\n const handleEmotionClick = (emotionKey: string) => {\n onEmotionSelect?.(emotionKey)\n }\n\n const renderEmotionItem = (emotion: typeof emotions[0]) => {\n const isSelected = selectedEmotion === emotion.key\n\n if (variant === \"button\") {\n return (\n <EmotionButton\n key={emotion.key}\n emotion={emotion.key}\n isSelected={isSelected}\n size={size}\n onClick={() => handleEmotionClick(emotion.key)}\n className={merge(\n \"transition-all duration-200\",\n isSelected && \"ring-1 ring-offset-2 ring-primary\"\n )}\n >\n {emotion.label}\n </EmotionButton>\n )\n }\n\n if (variant === \"card\") {\n return (\n <div\n key={emotion.key}\n className={merge(\n \"p-4 rounded-lg border-2 cursor-pointer transition-all duration-200 hover:shadow-md\",\n isSelected\n ? \"border-primary bg-primary/5\"\n : \"border-border hover:border-primary/50\"\n )}\n onClick={() => handleEmotionClick(emotion.key)}\n >\n <div className=\"flex items-center space-x-3\">\n <div className={merge(\n \"w-8 h-8 rounded-full flex items-center justify-center\",\n isSelected ? \"bg-primary text-primary-foreground\" : \"bg-muted\"\n )}>\n {emotion.icon && (\n <span className=\"text-lg\">\n {emotion.icon === \"smile\" && \"😊\"}\n {emotion.icon === \"frown\" && \"😢\"}\n {emotion.icon === \"angry\" && \"😠\"}\n {emotion.icon === \"heart\" && \"❤️\"}\n {emotion.icon === \"star\" && \"⭐\"}\n {emotion.icon === \"meh\" && \"😐\"}\n {emotion.icon === \"user\" && \"👤\"}\n </span>\n )}\n </div>\n <span className=\"font-medium truncate max-w-[120px]\">{emotion.label}</span>\n </div>\n </div>\n )\n }\n\n if (variant === \"chip\") {\n return (\n <div\n key={emotion.key}\n className={merge(\n \"px-3 py-1 rounded-full cursor-pointer transition-all duration-200 text-sm font-medium\",\n isSelected\n ? \"bg-primary text-primary-foreground\"\n : \"bg-muted hover:bg-muted/80\"\n )}\n onClick={() => handleEmotionClick(emotion.key)}\n >\n <span className=\"truncate max-w-[100px]\">{emotion.label}</span>\n </div>\n )\n }\n\n return null\n }\n\n const layoutClasses = {\n grid: \"grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-2 md:gap-3\",\n list: \"space-y-2\",\n compact: \"flex flex-wrap gap-1\"\n }\n\n return (\n <div\n ref={ref}\n className={merge(\"space-y-4\", className)}\n {...props}\n >\n <div className={layoutClasses[layout]}>\n {emotions.map(renderEmotionItem)}\n </div>\n\n {showIntensity && selectedEmotion && (\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium\">감정 강도</span>\n <span className=\"text-sm text-muted-foreground\">{intensity}%</span>\n </div>\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n value={intensity}\n onChange={(e) => onIntensityChange?.(Number(e.target.value))}\n className=\"w-full h-2 bg-muted rounded-lg appearance-none cursor-pointer slider\"\n />\n <div className=\"flex justify-between text-xs text-muted-foreground\">\n <span>약함</span>\n <span>보통</span>\n <span>강함</span>\n </div>\n </div>\n )}\n\n {selectedEmotion && showIntensity && (\n <div className=\"flex justify-center\">\n <EmotionMeter\n value={intensity}\n size=\"md\"\n color=\"blue\"\n />\n </div>\n )}\n </div>\n )\n }\n)\n\nEmotionSelector.displayName = \"EmotionSelector\"\n\nexport { EmotionSelector }\nexport type { EmotionSelectorProps }\n","'use client'\n\nimport React from \"react\"\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from '../../Card';\nimport { Badge } from '../../Badge';\nimport { merge } from '../../../lib/utils';\nimport { EmotionMeter } from \"./EmotionMeter\"\n\n/**\n * EmotionAnalysis 컴포넌트의 props / EmotionAnalysis component props\n * @typedef {Object} EmotionAnalysisProps\n * @property {Object} [primaryEmotion] - 주요 감정 정보 / Primary emotion information\n * @property {string} primaryEmotion.name - 감정 이름 / Emotion name\n * @property {number} primaryEmotion.intensity - 감정 강도 (0-100) / Emotion intensity (0-100)\n * @property {string} [primaryEmotion.color] - 감정 색상 / Emotion color\n * @property {Array<Object>} [emotionDistribution] - 감정 분포 배열 / Emotion distribution array\n * @property {string} emotionDistribution[].emotion - 감정 이름 / Emotion name\n * @property {number} emotionDistribution[].percentage - 감정 비율 (0-100) / Emotion percentage (0-100)\n * @property {string} emotionDistribution[].color - 감정 색상 / Emotion color\n * @property {string[]} [keywords] - 키워드 배열 / Keywords array\n * @property {number} [intensity=50] - 전체 강도 (0-100) / Overall intensity (0-100)\n * @property {number} [positivity=70] - 긍정성 (0-100) / Positivity (0-100)\n * @property {number} [energy=60] - 에너지 (0-100) / Energy (0-100)\n * @property {boolean} [showMeter=true] - 강도 미터 표시 여부 / Show intensity meter\n * @property {boolean} [showDistribution=true] - 분포 표시 여부 / Show distribution\n * @property {boolean} [showKeywords=true] - 키워드 표시 여부 / Show keywords\n * @property {boolean} [showMetrics=true] - 메트릭 표시 여부 / Show metrics\n * @property {\"compact\" | \"detailed\" | \"card\"} [layout=\"detailed\"] - 레이아웃 타입 / Layout type\n * @extends {React.HTMLAttributes<HTMLDivElement>}\n */\ninterface EmotionAnalysisProps extends React.HTMLAttributes<HTMLDivElement> {\n primaryEmotion?: {\n name: string\n intensity: number\n color?: string\n }\n emotionDistribution?: Array<{\n emotion: string\n percentage: number\n color: string\n }>\n keywords?: string[]\n intensity?: number\n positivity?: number\n energy?: number\n showMeter?: boolean\n showDistribution?: boolean\n showKeywords?: boolean\n showMetrics?: boolean\n layout?: \"compact\" | \"detailed\" | \"card\"\n}\n\n/**\n * EmotionAnalysis 컴포넌트 / EmotionAnalysis component\n *\n * 감정 분석 결과를 표시하는 컴포넌트입니다.\n * 주요 감정, 감정 분포, 키워드, 메트릭(강도, 긍정성, 에너지)을 표시할 수 있습니다.\n *\n * Component that displays emotion analysis results.\n * Can display primary emotion, emotion distribution, keywords, and metrics (intensity, positivity, energy).\n *\n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <EmotionAnalysis\n * primaryEmotion={{ name: \"기쁨\", intensity: 80 }}\n * keywords={[\"행복\", \"만족\"]}\n * />\n *\n * @example\n * // 상세 레이아웃 / Detailed layout\n * <EmotionAnalysis\n * primaryEmotion={{ name: \"평온\", intensity: 65, color: \"green\" }}\n * emotionDistribution={[\n * { emotion: \"기쁨\", percentage: 40, color: \"yellow\" },\n * { emotion: \"평온\", percentage: 60, color: \"green\" }\n * ]}\n * keywords={[\"안정\", \"편안\"]}\n * intensity={65}\n * positivity={75}\n * energy={50}\n * layout=\"detailed\"\n * />\n *\n * @param {EmotionAnalysisProps} props - EmotionAnalysis 컴포넌트의 props / EmotionAnalysis component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} EmotionAnalysis 컴포넌트 / EmotionAnalysis component\n */\nconst EmotionAnalysis = React.forwardRef<HTMLDivElement, EmotionAnalysisProps>(\n ({\n className,\n primaryEmotion,\n emotionDistribution = [],\n keywords = [],\n intensity = 50,\n positivity = 70,\n energy = 60,\n showMeter = true,\n showDistribution = true,\n showKeywords = true,\n showMetrics = true,\n layout = \"detailed\",\n ...props\n }, ref) => {\n const getIntensityLabel = (value: number) => {\n if (value < 30) return \"약함\"\n if (value < 70) return \"보통\"\n return \"강함\"\n }\n\n const getPositivityLabel = (value: number) => {\n if (value < 30) return \"부정적\"\n if (value < 70) return \"중립적\"\n return \"긍정적\"\n }\n\n const getEnergyLabel = (value: number) => {\n if (value < 30) return \"낮음\"\n if (value < 70) return \"보통\"\n return \"높음\"\n }\n\n if (layout === \"compact\") {\n return (\n <div\n ref={ref}\n className={merge(\"space-y-3\", className)}\n {...props}\n >\n {primaryEmotion && (\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium\">주요 감정:</span>\n <div className=\"flex items-center space-x-2\">\n <span className=\"text-sm text-muted-foreground\">\n {primaryEmotion.name} ({primaryEmotion.intensity}%)\n </span>\n {showMeter && (\n <EmotionMeter\n value={primaryEmotion.intensity}\n size=\"sm\"\n color=\"blue\"\n />\n )}\n </div>\n </div>\n )}\n\n {showMetrics && (\n <>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium\">감정 강도:</span>\n <span className=\"text-sm text-muted-foreground\">\n {getIntensityLabel(intensity)}\n </span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium\">긍정성:</span>\n <span className=\"text-sm text-muted-foreground\">\n {getPositivityLabel(positivity)}\n </span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium\">에너지:</span>\n <span className=\"text-sm text-muted-foreground\">\n {getEnergyLabel(energy)}\n </span>\n </div>\n </>\n )}\n\n {showKeywords && keywords.length > 0 && (\n <div>\n <span className=\"text-sm font-medium\">키워드:</span>\n <div className=\"flex flex-wrap gap-1 mt-1\">\n {keywords.map((keyword) => (\n <Badge key={keyword} variant=\"secondary\" className=\"text-xs\">\n {keyword}\n </Badge>\n ))}\n </div>\n </div>\n )}\n </div>\n )\n }\n\n if (layout === \"card\") {\n return (\n <Card\n ref={ref}\n className={merge(\"\", className)}\n {...props}\n >\n <CardHeader>\n <CardTitle className=\"flex items-center\">\n <span className=\"text-2xl mr-2\">✨</span>\n AI 분석\n </CardTitle>\n <CardDescription>\n 감정 분석 결과\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n {primaryEmotion && (\n <div className=\"space-y-3\">\n <div className=\"text-sm\">\n <span className=\"font-medium\">주요 감정:</span>\n <span className=\"ml-2 text-muted-foreground\">\n {primaryEmotion.name} ({primaryEmotion.intensity}%)\n </span>\n </div>\n {showMeter && (\n <div className=\"flex justify-center\">\n <EmotionMeter\n value={primaryEmotion.intensity}\n size=\"md\"\n color=\"blue\"\n />\n </div>\n )}\n </div>\n )}\n\n {showMetrics && (\n <>\n <div className=\"text-sm\">\n <span className=\"font-medium\">감정 강도:</span>\n <span className=\"ml-2 text-muted-foreground\">\n {getIntensityLabel(intensity)}\n </span>\n </div>\n <div className=\"text-sm\">\n <span className=\"font-medium\">긍정성:</span>\n <span className=\"ml-2 text-muted-foreground\">\n {getPositivityLabel(positivity)}\n </span>\n </div>\n <div className=\"text-sm\">\n <span className=\"font-medium\">에너지:</span>\n <span className=\"ml-2 text-muted-foreground\">\n {getEnergyLabel(energy)}\n </span>\n </div>\n </>\n )}\n\n {showKeywords && keywords.length > 0 && (\n <div className=\"text-sm\">\n <span className=\"font-medium\">키워드:</span>\n <div className=\"flex flex-wrap gap-1 mt-1\">\n {keywords.map((keyword) => (\n <Badge key={keyword} variant=\"secondary\" className=\"text-xs\">\n {keyword}\n </Badge>\n ))}\n </div>\n </div>\n )}\n </CardContent>\n </Card>\n )\n }\n\n // detailed layout (default)\n return (\n <div\n ref={ref}\n className={merge(\"space-y-6\", className)}\n {...props}\n >\n {primaryEmotion && (\n <div className=\"space-y-4\">\n <h3 className=\"text-lg font-semibold\">주요 감정</h3>\n <div className=\"flex items-center space-x-4\">\n <div className=\"text-center\">\n <div className=\"text-2xl font-bold text-primary\">\n {primaryEmotion.name}\n </div>\n <div className=\"text-sm text-muted-foreground\">\n {primaryEmotion.intensity}% 강도\n </div>\n </div>\n {showMeter && (\n <EmotionMeter\n value={primaryEmotion.intensity}\n size=\"lg\"\n color=\"blue\"\n />\n )}\n </div>\n </div>\n )}\n\n {showDistribution && emotionDistribution.length > 0 && (\n <div className=\"space-y-4\">\n <h3 className=\"text-lg font-semibold\">감정 분포</h3>\n <div className=\"space-y-3\">\n {emotionDistribution.map((item, index) => (\n <div key={index} className=\"space-y-2\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm font-medium\">{item.emotion}</span>\n <span className=\"text-sm text-muted-foreground\">\n {item.percentage}%\n </span>\n </div>\n <div className=\"w-full bg-muted rounded-full h-2\">\n <div\n className={`${item.color} h-2 rounded-full transition-all duration-300`}\n style={{ width: `${item.percentage}%` }}\n />\n </div>\n </div>\n ))}\n </div>\n </div>\n )}\n\n {showMetrics && (\n <div className=\"space-y-4\">\n <h3 className=\"text-lg font-semibold\">분석 지표</h3>\n <div className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n <div className=\"space-y-2\">\n <div className=\"text-sm font-medium\">감정 강도</div>\n <div className=\"text-2xl font-bold text-primary\">\n {getIntensityLabel(intensity)}\n </div>\n <div className=\"w-full bg-muted rounded-full h-2\">\n <div\n className=\"bg-primary h-2 rounded-full transition-all duration-300\"\n style={{ width: `${intensity}%` }}\n />\n </div>\n </div>\n <div className=\"space-y-2\">\n <div className=\"text-sm font-medium\">긍정성</div>\n <div className=\"text-2xl font-bold text-green-600\">\n {getPositivityLabel(positivity)}\n </div>\n <div className=\"w-full bg-muted rounded-full h-2\">\n <div\n className=\"bg-green-500 h-2 rounded-full transition-all duration-300\"\n style={{ width: `${positivity}%` }}\n />\n </div>\n </div>\n <div className=\"space-y-2\">\n <div className=\"text-sm font-medium\">에너지</div>\n <div className=\"text-2xl font-bold text-orange-600\">\n {getEnergyLabel(energy)}\n </div>\n <div className=\"w-full bg-muted rounded-full h-2\">\n <div\n className=\"bg-orange-500 h-2 rounded-full transition-all duration-300\"\n style={{ width: `${energy}%` }}\n />\n </div>\n </div>\n </div>\n </div>\n )}\n\n {showKeywords && keywords.length > 0 && (\n <div className=\"space-y-4\">\n <h3 className=\"text-lg font-semibold\">감정 키워드</h3>\n <div className=\"flex flex-wrap gap-2\">\n {keywords.map((keyword) => (\n <Badge key={keyword} variant=\"outline\" className=\"text-sm\">\n {keyword}\n </Badge>\n ))}\n </div>\n </div>\n )}\n </div>\n )\n }\n)\n\nEmotionAnalysis.displayName = \"EmotionAnalysis\"\n\nexport { EmotionAnalysis }\nexport type { EmotionAnalysisProps }\n"]}
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- import {a}from'./chunk-UUHAXGMO.mjs';import m from'react';import {clsx}from'clsx';import {cva}from'class-variance-authority';import {jsxs,Fragment,jsx}from'react/jsx-runtime';function F(...o){return r=>{o.forEach(t=>{typeof t=="function"?t(r):t!=null&&(t.current=r);});}}function J(o,r){return t=>{o==null||o(t),t.defaultPrevented||r==null||r(t);}}function K(o,r){if(!(!o&&!r))return clsx(o,r)}function Q(o,r){if(!(!o&&!r))return {...o,...r}}function U(o,r){let t={...o};for(let e in r){let n=o[e],a=r[e];/^on[A-Z]/.test(e)?n&&a?t[e]=J(n,a):t[e]=a||n:e==="className"?t[e]=K(n,a):e==="style"?t[e]=Q(n,a):t[e]=a!==void 0?a:n;}return t}function X(o){return m.isValidElement(o)}var R=m.forwardRef(({children:o,...r},t)=>{let e=m.Children.toArray(o);if(e.length!==1)return process.env.NODE_ENV!=="production"&&console.warn("[Slot] asChild\uB294 \uC815\uD655\uD788 \uD558\uB098\uC758 \uC790\uC2DD \uC694\uC18C\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4."),null;let n=e[0];if(!X(n))return process.env.NODE_ENV!=="production"&&console.warn("[Slot] \uC790\uC2DD\uC740 \uC720\uD6A8\uD55C React \uC694\uC18C\uC5EC\uC57C \uD569\uB2C8\uB2E4."),null;let a=n.props,p=n.ref,c=U(r,a),g=F(t,p);return m.cloneElement(n,{...c,ref:g})});R.displayName="Slot";var M="[transition:transform_180ms_cubic-bezier(0.34,1.56,0.64,1),box-shadow_200ms_ease-out]",B=cva("inline-flex items-center justify-center whitespace-nowrap font-medium transition-all duration-200 disabled:pointer-events-none disabled:opacity-50 min-w-fit focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[var(--color-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-background)]",{variants:{variant:{default:"bg-[var(--color-primary)] text-[var(--color-primary-foreground)] hover:opacity-90",destructive:"bg-[var(--color-destructive)] text-[var(--color-destructive-foreground)] hover:opacity-90 focus-visible:ring-[var(--color-destructive)]",outline:"border-2 border-[var(--color-border)] bg-transparent text-[var(--color-foreground)] hover:bg-[var(--color-accent)] hover:text-[var(--color-accent-foreground)] focus-visible:ring-offset-0",secondary:"bg-[var(--color-secondary)] text-[var(--color-secondary-foreground)] hover:opacity-80",ghost:"bg-transparent text-[var(--color-foreground)] hover:bg-[var(--color-accent)] hover:text-[var(--color-accent-foreground)] focus-visible:ring-offset-0",link:"bg-transparent text-[var(--color-primary)] underline hover:opacity-80 focus-visible:ring-offset-0",gradient:"bg-gradient-to-r from-[var(--btn-gradient-from,theme(colors.teal.500))] to-[var(--btn-gradient-to,theme(colors.cyan.500))] text-white hover:shadow-lg",neon:"bg-slate-900 dark:bg-slate-950 text-teal-400 border border-teal-500/50 shadow-lg shadow-[var(--btn-neon-glow,theme(colors.teal.500/20%))] hover:shadow-[var(--btn-neon-glow,theme(colors.teal.500/40%))] hover:border-teal-400",glass:"bg-white/50 dark:bg-slate-900/50 backdrop-blur-md border border-slate-200/50 dark:border-slate-700/50 text-slate-900 dark:text-slate-100 hover:bg-white/70 dark:hover:bg-slate-900/70"},size:{sm:"h-8 px-4 py-2 text-sm",md:"h-10 px-6 py-2 text-base",lg:"h-12 px-8 py-3 text-lg",xl:"h-14 px-10 py-4 text-xl",icon:"h-10 w-10 p-0"},rounded:{sm:"rounded",md:"rounded-md",lg:"rounded-lg",full:"rounded-full"},shadow:{none:"",sm:"shadow-sm",md:"shadow-md",lg:"shadow-lg",xl:"shadow-xl"},hover:{springy:`hover:scale-[1.015] hover:shadow-md active:scale-[0.985] ${M} transform-gpu`,scale:"hover:scale-[1.015] active:scale-[0.985] transition-transform duration-150 ease-out transform-gpu",glow:"hover:shadow-lg hover:shadow-primary/25 transition-shadow duration-200",slide:`hover:-translate-y-0.5 hover:shadow-md ${M} transform-gpu`,none:""},fullWidth:{true:"w-full",false:""}},defaultVariants:{variant:"default",size:"md",rounded:"md",shadow:"md",hover:"springy",fullWidth:false}}),x={blue:"from-teal-500 to-cyan-500",purple:"from-purple-500 to-pink-500",green:"from-green-500 to-emerald-500 dark:from-green-400 dark:to-emerald-400",orange:"from-orange-500 to-red-500 dark:from-orange-300 dark:to-red-300",pink:"from-pink-500 to-rose-500"};var q=typeof window!="undefined";function ee(){let[o,r]=m.useState(false);return m.useEffect(()=>{var n;if(!q||!("matchMedia"in window))return;let t=window.matchMedia("(prefers-reduced-motion: reduce)"),e=()=>r(!!t.matches);return e(),(n=t.addEventListener)==null||n.call(t,"change",e),()=>{var a;return (a=t.removeEventListener)==null?void 0:a.call(t,"change",e)}},[]),o}var T=m.forwardRef(function({variant:r="default",size:t="md",loading:e=false,icon:n,iconPosition:a$1="left",gradient:p="blue",customGradient:c,rounded:g="md",shadow:L="md",hover:V="springy",fullWidth:h,iconOnly:H,className:O,children:P,disabled:d,asChild:_=false,...i},v){let z=ee(),D=r==="gradient"?c?`bg-gradient-to-r ${c}`:`bg-gradient-to-r ${x[p]||x.blue}`:void 0,b=a(B({variant:r,size:t,rounded:g,shadow:L,hover:z?"none":V,fullWidth:h!=null?h:false}),D,O),E=jsxs(Fragment,{children:[e&&jsxs("span",{role:"status","aria-live":"polite",className:"-ml-1 mr-2 inline-flex",children:[jsxs("svg",{className:"animate-spin h-4 w-4",viewBox:"0 0 24 24",fill:"none",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"})]}),jsx("span",{className:"sr-only",children:"\uB85C\uB529 \uC911"})]}),!e&&n&&a$1==="left"&&jsx("span",{className:"mr-2",children:n}),P,!e&&n&&a$1==="right"&&jsx("span",{className:"ml-2",children:n})]});if(H&&!("aria-label"in i)&&process.env.NODE_ENV!=="production"&&console.warn("[Button] iconOnly \uC0AC\uC6A9 \uC2DC aria-label\uC744 \uC81C\uACF5\uD558\uC138\uC694."),_){let l={className:b,ref:v,disabled:d||e,"aria-busy":e||void 0,"aria-disabled":d||e||void 0,...i};return jsx(R,{...l,children:P})}if("href"in i&&i.href){let{onClick:l,target:A,rel:u,href:G,"aria-label":oe,className:j,...C}=i,y=!!d||e,W=w=>{if(y){w.preventDefault(),w.stopPropagation();return}l==null||l(w);};return jsx("a",{ref:v,href:G,className:a(b,j),onClick:W,"aria-busy":e||void 0,"aria-disabled":y||void 0,tabIndex:y?-1:C.tabIndex,target:A,rel:A==="_blank"?u!=null?u:"noopener noreferrer":u,...C,children:E})}let{className:I,...$}=i,S=!!d||e;return jsx("button",{ref:v,className:a(b,I),type:"button",disabled:S,"aria-busy":e||void 0,"aria-disabled":S||void 0,...$,children:E})});T.displayName="Button";var me=T;export{F as a,U as b,R as c,me as d};//# sourceMappingURL=chunk-FFH4ZFKS.mjs.map
3
- //# sourceMappingURL=chunk-FFH4ZFKS.mjs.map
2
+ import {b}from'./chunk-U6CTBZ2U.mjs';import m from'react';import {clsx}from'clsx';import {cva}from'class-variance-authority';import {jsxs,Fragment,jsx}from'react/jsx-runtime';function F(...o){return r=>{o.forEach(t=>{typeof t=="function"?t(r):t!=null&&(t.current=r);});}}function J(o,r){return t=>{o==null||o(t),t.defaultPrevented||r==null||r(t);}}function K(o,r){if(!(!o&&!r))return clsx(o,r)}function Q(o,r){if(!(!o&&!r))return {...o,...r}}function U(o,r){let t={...o};for(let e in r){let n=o[e],a=r[e];/^on[A-Z]/.test(e)?n&&a?t[e]=J(n,a):t[e]=a||n:e==="className"?t[e]=K(n,a):e==="style"?t[e]=Q(n,a):t[e]=a!==void 0?a:n;}return t}function X(o){return m.isValidElement(o)}var R=m.forwardRef(({children:o,...r},t)=>{let e=m.Children.toArray(o);if(e.length!==1)return process.env.NODE_ENV!=="production"&&console.warn("[Slot] asChild\uB294 \uC815\uD655\uD788 \uD558\uB098\uC758 \uC790\uC2DD \uC694\uC18C\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4."),null;let n=e[0];if(!X(n))return process.env.NODE_ENV!=="production"&&console.warn("[Slot] \uC790\uC2DD\uC740 \uC720\uD6A8\uD55C React \uC694\uC18C\uC5EC\uC57C \uD569\uB2C8\uB2E4."),null;let a=n.props,p=n.ref,c=U(r,a),g=F(t,p);return m.cloneElement(n,{...c,ref:g})});R.displayName="Slot";var M="[transition:transform_180ms_cubic-bezier(0.34,1.56,0.64,1),box-shadow_200ms_ease-out]",B=cva("inline-flex items-center justify-center whitespace-nowrap font-medium transition-all duration-200 disabled:pointer-events-none disabled:opacity-50 min-w-fit focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[var(--color-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-background)]",{variants:{variant:{default:"bg-[var(--color-primary)] text-[var(--color-primary-foreground)] hover:opacity-90",destructive:"bg-[var(--color-destructive)] text-[var(--color-destructive-foreground)] hover:opacity-90 focus-visible:ring-[var(--color-destructive)]",outline:"border-2 border-[var(--color-border)] bg-transparent text-[var(--color-foreground)] hover:bg-[var(--color-accent)] hover:text-[var(--color-accent-foreground)] focus-visible:ring-offset-0",secondary:"bg-[var(--color-secondary)] text-[var(--color-secondary-foreground)] hover:opacity-80",ghost:"bg-transparent text-[var(--color-foreground)] hover:bg-[var(--color-accent)] hover:text-[var(--color-accent-foreground)] focus-visible:ring-offset-0",link:"bg-transparent text-[var(--color-primary)] underline hover:opacity-80 focus-visible:ring-offset-0",gradient:"bg-gradient-to-r from-[var(--btn-gradient-from,theme(colors.teal.500))] to-[var(--btn-gradient-to,theme(colors.cyan.500))] text-white hover:shadow-lg",neon:"bg-slate-900 dark:bg-slate-950 text-teal-400 border border-teal-500/50 shadow-lg shadow-[var(--btn-neon-glow,theme(colors.teal.500/20%))] hover:shadow-[var(--btn-neon-glow,theme(colors.teal.500/40%))] hover:border-teal-400",glass:"bg-white/50 dark:bg-slate-900/50 backdrop-blur-md border border-slate-200/50 dark:border-slate-700/50 text-slate-900 dark:text-slate-100 hover:bg-white/70 dark:hover:bg-slate-900/70"},size:{sm:"h-8 px-4 py-2 text-sm",md:"h-10 px-6 py-2 text-base",lg:"h-12 px-8 py-3 text-lg",xl:"h-14 px-10 py-4 text-xl",icon:"h-10 w-10 p-0"},rounded:{sm:"rounded",md:"rounded-md",lg:"rounded-lg",full:"rounded-full"},shadow:{none:"",sm:"shadow-sm",md:"shadow-md",lg:"shadow-lg",xl:"shadow-xl"},hover:{springy:`hover:scale-[1.015] hover:shadow-md active:scale-[0.985] ${M} transform-gpu`,scale:"hover:scale-[1.015] active:scale-[0.985] transition-transform duration-150 ease-out transform-gpu",glow:"hover:shadow-lg hover:shadow-primary/25 transition-shadow duration-200",slide:`hover:-translate-y-0.5 hover:shadow-md ${M} transform-gpu`,none:""},fullWidth:{true:"w-full",false:""}},defaultVariants:{variant:"default",size:"md",rounded:"md",shadow:"md",hover:"springy",fullWidth:false}}),x={blue:"from-teal-500 to-cyan-500",purple:"from-purple-500 to-pink-500",green:"from-green-500 to-emerald-500 dark:from-green-400 dark:to-emerald-400",orange:"from-orange-500 to-red-500 dark:from-orange-300 dark:to-red-300",pink:"from-pink-500 to-rose-500"};var q=typeof window!="undefined";function ee(){let[o,r]=m.useState(false);return m.useEffect(()=>{var n;if(!q||!("matchMedia"in window))return;let t=window.matchMedia("(prefers-reduced-motion: reduce)"),e=()=>r(!!t.matches);return e(),(n=t.addEventListener)==null||n.call(t,"change",e),()=>{var a;return (a=t.removeEventListener)==null?void 0:a.call(t,"change",e)}},[]),o}var T=m.forwardRef(function({variant:r="default",size:t="md",loading:e=false,icon:n,iconPosition:a="left",gradient:p="blue",customGradient:c,rounded:g="md",shadow:L="md",hover:V="springy",fullWidth:h,iconOnly:H,className:O,children:P,disabled:d,asChild:_=false,...i},v){let z=ee(),D=r==="gradient"?c?`bg-gradient-to-r ${c}`:`bg-gradient-to-r ${x[p]||x.blue}`:void 0,b$1=b(B({variant:r,size:t,rounded:g,shadow:L,hover:z?"none":V,fullWidth:h!=null?h:false}),D,O),E=jsxs(Fragment,{children:[e&&jsxs("span",{role:"status","aria-live":"polite",className:"-ml-1 mr-2 inline-flex",children:[jsxs("svg",{className:"animate-spin h-4 w-4",viewBox:"0 0 24 24",fill:"none",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"})]}),jsx("span",{className:"sr-only",children:"\uB85C\uB529 \uC911"})]}),!e&&n&&a==="left"&&jsx("span",{className:"mr-2",children:n}),P,!e&&n&&a==="right"&&jsx("span",{className:"ml-2",children:n})]});if(H&&!("aria-label"in i)&&process.env.NODE_ENV!=="production"&&console.warn("[Button] iconOnly \uC0AC\uC6A9 \uC2DC aria-label\uC744 \uC81C\uACF5\uD558\uC138\uC694."),_){let l={className:b$1,ref:v,disabled:d||e,"aria-busy":e||void 0,"aria-disabled":d||e||void 0,...i};return jsx(R,{...l,children:P})}if("href"in i&&i.href){let{onClick:l,target:A,rel:u,href:G,"aria-label":oe,className:j,...C}=i,y=!!d||e,W=w=>{if(y){w.preventDefault(),w.stopPropagation();return}l==null||l(w);};return jsx("a",{ref:v,href:G,className:b(b$1,j),onClick:W,"aria-busy":e||void 0,"aria-disabled":y||void 0,tabIndex:y?-1:C.tabIndex,target:A,rel:A==="_blank"?u!=null?u:"noopener noreferrer":u,...C,children:E})}let{className:I,...$}=i,S=!!d||e;return jsx("button",{ref:v,className:b(b$1,I),type:"button",disabled:S,"aria-busy":e||void 0,"aria-disabled":S||void 0,...$,children:E})});T.displayName="Button";var me=T;export{F as a,U as b,R as c,me as d};//# sourceMappingURL=chunk-XCZMLKPK.mjs.map
3
+ //# sourceMappingURL=chunk-XCZMLKPK.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/Slot.tsx","../src/components/Button.variants.ts","../src/components/Button.tsx"],"names":["composeRefs","refs","node","ref","composeEventHandlers","parentHandler","childHandler","event","mergeClassName","slotClassName","childClassName","clsx","mergeStyle","slotStyle","childStyle","mergeProps","slotProps","childProps","mergedProps","propName","slotValue","childValue","isSlottable","child","React","Slot","children","forwardedRef","childArray","childRef","mergedRef","springTransition","buttonVariants","cva","gradientPresets","isBrowser","useReducedMotion","reduce","setReduce","_a","mq","onChange","ButtonInner","variant","size","loading","icon","iconPosition","gradient","customGradient","rounded","shadow","hover","fullWidth","iconOnly","className","disabled","asChild","rest","reduced","gradientClass","base","merge","content","jsxs","Fragment","jsx","onClick","target","rel","href","_ariaLabel","anchorClassName","anchorProps","isDisabled","handleAnchorClick","e","buttonClassName","btnProps","Button"],"mappings":"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","file":"chunk-FFH4ZFKS.mjs","sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport { clsx } from \"clsx\";\n\n/**\n * Slot 컴포넌트\n *\n * Radix UI의 asChild 패턴을 구현합니다.\n * 자식 요소의 props와 ref를 병합하여 하나의 요소로 렌더링합니다.\n *\n * @example\n * // Button에서 asChild 사용\n * <Button asChild>\n * <Link href=\"/home\">홈으로</Link>\n * </Button>\n *\n * @see https://www.radix-ui.com/primitives/docs/utilities/slot\n */\n\ntype SlotProps = React.HTMLAttributes<HTMLElement> & {\n children?: React.ReactNode;\n};\n\n/**\n * 여러 ref를 하나로 합칩니다\n */\nfunction composeRefs<T>(\n ...refs: (React.Ref<T> | undefined)[]\n): React.RefCallback<T> {\n return (node) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref != null) {\n (ref as React.MutableRefObject<T | null>).current = node;\n }\n });\n };\n}\n\n/**\n * 이벤트 핸들러를 합성합니다\n * \n * 부모(slot) 핸들러를 먼저 실행하고, 그 다음 자식 핸들러를 실행합니다.\n * defaultPrevented가 true이면 자식 핸들러는 실행하지 않습니다.\n */\nfunction composeEventHandlers<E>(\n parentHandler?: (event: E) => void,\n childHandler?: (event: E) => void\n): (event: E) => void {\n return (event) => {\n parentHandler?.(event);\n if (!(event as unknown as { defaultPrevented: boolean }).defaultPrevented) {\n childHandler?.(event);\n }\n };\n}\n\n/**\n * className을 병합합니다\n */\nfunction mergeClassName(\n slotClassName?: string,\n childClassName?: string\n): string | undefined {\n if (!slotClassName && !childClassName) return undefined;\n return clsx(slotClassName, childClassName);\n}\n\n/**\n * style을 병합합니다\n */\nfunction mergeStyle(\n slotStyle?: React.CSSProperties,\n childStyle?: React.CSSProperties\n): React.CSSProperties | undefined {\n if (!slotStyle && !childStyle) return undefined;\n return { ...slotStyle, ...childStyle };\n}\n\n/**\n * props를 병합합니다 (이벤트 핸들러, className, style 등)\n */\nfunction mergeProps(\n slotProps: Record<string, unknown>,\n childProps: Record<string, unknown>\n): Record<string, unknown> {\n const mergedProps: Record<string, unknown> = { ...slotProps };\n\n for (const propName in childProps) {\n const slotValue = slotProps[propName];\n const childValue = childProps[propName];\n\n // 이벤트 핸들러 병합 (부모(slot) → 자식 순서)\n if (/^on[A-Z]/.test(propName)) {\n if (slotValue && childValue) {\n mergedProps[propName] = composeEventHandlers(\n slotValue as (event: unknown) => void,\n childValue as (event: unknown) => void\n );\n } else {\n mergedProps[propName] = childValue || slotValue;\n }\n }\n // className 병합\n else if (propName === \"className\") {\n mergedProps[propName] = mergeClassName(\n slotValue as string | undefined,\n childValue as string | undefined\n );\n }\n // style 병합\n else if (propName === \"style\") {\n mergedProps[propName] = mergeStyle(\n slotValue as React.CSSProperties | undefined,\n childValue as React.CSSProperties | undefined\n );\n }\n // 그 외: 자식 값 우선\n else {\n mergedProps[propName] = childValue !== undefined ? childValue : slotValue;\n }\n }\n\n return mergedProps;\n}\n\n/**\n * 유효한 단일 React 요소인지 확인\n */\nfunction isSlottable(child: React.ReactNode): child is React.ReactElement {\n return React.isValidElement(child);\n}\n\n/**\n * Slot 컴포넌트\n *\n * 자식 요소에 부모의 props를 주입합니다.\n * asChild 패턴을 구현할 때 사용합니다.\n */\nconst Slot = React.forwardRef<HTMLElement, SlotProps>(\n ({ children, ...slotProps }, forwardedRef) => {\n const childArray = React.Children.toArray(children);\n\n // 유효한 단일 자식이 있는지 확인\n if (childArray.length !== 1) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n \"[Slot] asChild는 정확히 하나의 자식 요소가 필요합니다.\"\n );\n }\n return null;\n }\n\n const child = childArray[0];\n\n if (!isSlottable(child)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[Slot] 자식은 유효한 React 요소여야 합니다.\");\n }\n return null;\n }\n\n // 자식 요소의 props와 ref 추출\n const childProps = child.props as Record<string, unknown>;\n const childRef = (child as unknown as { ref?: React.Ref<HTMLElement> }).ref;\n\n // props와 ref 병합\n const mergedProps = mergeProps(slotProps, childProps);\n const mergedRef = composeRefs(forwardedRef, childRef);\n\n return React.cloneElement(child, {\n ...mergedProps,\n ref: mergedRef,\n } as React.Attributes);\n }\n);\n\nSlot.displayName = \"Slot\";\n\nexport { Slot, composeRefs, mergeProps };\nexport type { SlotProps };\n","import { cva } from 'class-variance-authority'\n\n/**\n * HUA Spring Easing transition — 시그니처 \"쫀득한\" 느낌\n * cubic-bezier(0.34, 1.56, 0.64, 1)\n */\nconst springTransition =\n '[transition:transform_180ms_cubic-bezier(0.34,1.56,0.64,1),box-shadow_200ms_ease-out]'\n\nexport const buttonVariants = cva(\n // ── base ──\n 'inline-flex items-center justify-center whitespace-nowrap font-medium transition-all duration-200 disabled:pointer-events-none disabled:opacity-50 min-w-fit focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[var(--color-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-background)]',\n {\n variants: {\n /** 스타일 변형 */\n variant: {\n default:\n 'bg-[var(--color-primary)] text-[var(--color-primary-foreground)] hover:opacity-90',\n destructive:\n 'bg-[var(--color-destructive)] text-[var(--color-destructive-foreground)] hover:opacity-90 focus-visible:ring-[var(--color-destructive)]',\n outline:\n 'border-2 border-[var(--color-border)] bg-transparent text-[var(--color-foreground)] hover:bg-[var(--color-accent)] hover:text-[var(--color-accent-foreground)] focus-visible:ring-offset-0',\n secondary:\n 'bg-[var(--color-secondary)] text-[var(--color-secondary-foreground)] hover:opacity-80',\n ghost:\n 'bg-transparent text-[var(--color-foreground)] hover:bg-[var(--color-accent)] hover:text-[var(--color-accent-foreground)] focus-visible:ring-offset-0',\n link:\n 'bg-transparent text-[var(--color-primary)] underline hover:opacity-80 focus-visible:ring-offset-0',\n gradient:\n 'bg-gradient-to-r from-[var(--btn-gradient-from,theme(colors.teal.500))] to-[var(--btn-gradient-to,theme(colors.cyan.500))] text-white hover:shadow-lg',\n neon:\n 'bg-slate-900 dark:bg-slate-950 text-teal-400 border border-teal-500/50 shadow-lg shadow-[var(--btn-neon-glow,theme(colors.teal.500/20%))] hover:shadow-[var(--btn-neon-glow,theme(colors.teal.500/40%))] hover:border-teal-400',\n glass:\n 'bg-white/50 dark:bg-slate-900/50 backdrop-blur-md border border-slate-200/50 dark:border-slate-700/50 text-slate-900 dark:text-slate-100 hover:bg-white/70 dark:hover:bg-slate-900/70',\n },\n /** 크기 */\n size: {\n sm: 'h-8 px-4 py-2 text-sm',\n md: 'h-10 px-6 py-2 text-base',\n lg: 'h-12 px-8 py-3 text-lg',\n xl: 'h-14 px-10 py-4 text-xl',\n icon: 'h-10 w-10 p-0',\n },\n /** 모서리 둥글기 */\n rounded: {\n sm: 'rounded',\n md: 'rounded-md',\n lg: 'rounded-lg',\n full: 'rounded-full',\n },\n /** 그림자 */\n shadow: {\n none: '',\n sm: 'shadow-sm',\n md: 'shadow-md',\n lg: 'shadow-lg',\n xl: 'shadow-xl',\n },\n /** 호버 효과 — springy가 HUA-UI 시그니처 */\n hover: {\n springy: `hover:scale-[1.015] hover:shadow-md active:scale-[0.985] ${springTransition} transform-gpu`,\n scale:\n 'hover:scale-[1.015] active:scale-[0.985] transition-transform duration-150 ease-out transform-gpu',\n glow: 'hover:shadow-lg hover:shadow-primary/25 transition-shadow duration-200',\n slide: `hover:-translate-y-0.5 hover:shadow-md ${springTransition} transform-gpu`,\n none: '',\n },\n /** 전체 너비 */\n fullWidth: {\n true: 'w-full',\n false: '',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n rounded: 'md',\n shadow: 'md',\n hover: 'springy',\n fullWidth: false,\n },\n }\n)\n\n/** Gradient 프리셋 */\nexport const gradientPresets: Record<string, string> = {\n blue: 'from-teal-500 to-cyan-500',\n purple: 'from-purple-500 to-pink-500',\n green: 'from-green-500 to-emerald-500 dark:from-green-400 dark:to-emerald-400',\n orange: 'from-orange-500 to-red-500 dark:from-orange-300 dark:to-red-300',\n pink: 'from-pink-500 to-rose-500',\n}\n\nexport type { VariantProps } from 'class-variance-authority'\n","\"use client\";\n\nimport React from \"react\";\nimport { merge } from \"../lib/utils\";\nimport { buttonVariants, gradientPresets } from \"./Button.variants\";\nimport { Slot } from \"../lib/Slot\";\n\n/**\n * 버튼 스타일 변형 / Button style variant\n */\ntype Variant =\n | \"default\" | \"destructive\" | \"outline\" | \"secondary\"\n | \"ghost\" | \"link\" | \"gradient\" | \"neon\" | \"glass\";\n\n/**\n * 버튼 크기 / Button size\n */\ntype Size = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"icon\";\n\n/**\n * 버튼 모서리 둥글기 / Button border radius\n */\ntype Rounded = \"sm\" | \"md\" | \"lg\" | \"full\";\n\n/**\n * 버튼 그림자 / Button shadow\n */\ntype Shadow = \"none\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\n/**\n * 버튼 호버 효과 / Button hover effect\n * \"springy\"가 HUA-UI 시그니처 - 공 튕기듯 미세한 반동\n */\ntype Hover = \"springy\" | \"scale\" | \"glow\" | \"slide\" | \"none\";\n\n/**\n * 그라디언트 색상 이름 / Gradient color name\n */\ntype GradientName = \"blue\" | \"purple\" | \"green\" | \"orange\" | \"pink\" | \"custom\";\n\n/**\n * Button 컴포넌트의 공통 props / Common props for Button component\n */\ntype CommonProps = {\n variant?: Variant;\n size?: Size;\n loading?: boolean;\n icon?: React.ReactNode;\n iconPosition?: \"left\" | \"right\";\n gradient?: GradientName;\n customGradient?: string;\n rounded?: Rounded;\n shadow?: Shadow;\n hover?: Hover;\n fullWidth?: boolean;\n iconOnly?: boolean;\n \"aria-label\"?: string;\n className?: string;\n disabled?: boolean;\n asChild?: boolean;\n};\n\ntype AnchorProps = CommonProps &\n Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, \"className\"> & {\n href: string;\n };\n\ntype NativeButtonProps = CommonProps &\n Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"className\" | \"type\"> & {\n href?: undefined;\n };\n\n/**\n * Button 컴포넌트의 props 타입 / Button component props type\n * href가 제공되면 앵커 태그로, 그렇지 않으면 버튼 태그로 렌더링됩니다.\n */\nexport type ButtonProps = AnchorProps | NativeButtonProps;\n\ntype AnchorOrButton = HTMLAnchorElement | HTMLButtonElement;\n\nconst isBrowser = typeof window !== \"undefined\";\nfunction useReducedMotion() {\n const [reduce, setReduce] = React.useState(false);\n React.useEffect(() => {\n if (!isBrowser || !(\"matchMedia\" in window)) return;\n const mq = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n const onChange = () => setReduce(!!mq.matches);\n onChange();\n mq.addEventListener?.(\"change\", onChange);\n return () => mq.removeEventListener?.(\"change\", onChange);\n }, []);\n return reduce;\n}\n\n/**\n * Button 컴포넌트 / Button component\n *\n * 다양한 스타일과 크기를 지원하는 범용 버튼 컴포넌트입니다.\n * href prop을 제공하면 앵커 태그로, 그렇지 않으면 버튼 태그로 렌더링됩니다.\n *\n * @example\n * <Button onClick={() => console.log('클릭')}>클릭하세요</Button>\n * <Button variant=\"destructive\" size=\"lg\">삭제</Button>\n * <Button variant=\"gradient\" gradient=\"purple\">그라디언트</Button>\n * <Button href=\"/about\" variant=\"link\">자세히 보기</Button>\n */\nconst ButtonInner = React.forwardRef<AnchorOrButton, ButtonProps>(function ButtonInner(\n {\n variant = \"default\",\n size = \"md\",\n loading = false,\n icon,\n iconPosition = \"left\",\n gradient = \"blue\",\n customGradient,\n rounded = \"md\",\n shadow = \"md\",\n hover = \"springy\",\n fullWidth,\n iconOnly,\n className,\n children,\n disabled,\n asChild = false,\n ...rest\n },\n ref\n) {\n const reduced = useReducedMotion();\n\n // gradient variant: 커스텀 그라디언트 클래스 처리\n const gradientClass =\n variant === \"gradient\"\n ? customGradient\n ? `bg-gradient-to-r ${customGradient}`\n : `bg-gradient-to-r ${gradientPresets[gradient] || gradientPresets.blue}`\n : undefined;\n\n const base = merge(\n buttonVariants({\n variant,\n size,\n rounded,\n shadow,\n hover: reduced ? \"none\" : hover,\n fullWidth: fullWidth ?? false,\n }),\n gradientClass,\n className\n );\n\n const Spinner = (\n <span role=\"status\" aria-live=\"polite\" className=\"-ml-1 mr-2 inline-flex\">\n <svg className=\"animate-spin h-4 w-4\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\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\" />\n </svg>\n <span className=\"sr-only\">로딩 중</span>\n </span>\n );\n\n const content = (\n <>\n {loading && Spinner}\n {!loading && icon && iconPosition === \"left\" && <span className=\"mr-2\">{icon}</span>}\n {children}\n {!loading && icon && iconPosition === \"right\" && <span className=\"ml-2\">{icon}</span>}\n </>\n );\n\n if (iconOnly && !(\"aria-label\" in rest) && process.env.NODE_ENV !== \"production\") {\n console.warn(\"[Button] iconOnly 사용 시 aria-label을 제공하세요.\");\n }\n\n // asChild 모드: Slot을 사용하여 자식 요소에 props 병합\n if (asChild) {\n const slotProps = {\n className: base,\n ref,\n disabled: disabled || loading,\n \"aria-busy\": loading || undefined,\n \"aria-disabled\": (disabled || loading) || undefined,\n ...rest,\n };\n return <Slot {...slotProps}>{children}</Slot>;\n }\n\n // 앵커 모드\n if (\"href\" in rest && rest.href) {\n const { onClick, target, rel, href, \"aria-label\": _ariaLabel, className: anchorClassName, ...anchorProps } = rest as AnchorProps;\n const isDisabled = !!disabled || loading;\n\n const handleAnchorClick: React.MouseEventHandler<HTMLAnchorElement> = (e) => {\n if (isDisabled) { e.preventDefault(); e.stopPropagation(); return; }\n onClick?.(e);\n };\n\n return (\n <a\n ref={ref as React.Ref<HTMLAnchorElement>}\n href={href}\n className={merge(base, anchorClassName)}\n onClick={handleAnchorClick}\n aria-busy={loading || undefined}\n aria-disabled={isDisabled || undefined}\n tabIndex={isDisabled ? -1 : anchorProps.tabIndex}\n target={target}\n rel={target === \"_blank\" ? rel ?? \"noopener noreferrer\" : rel}\n {...anchorProps}\n >\n {content}\n </a>\n );\n }\n\n // 버튼 모드\n const { className: buttonClassName, ...btnProps } = rest as NativeButtonProps;\n const isDisabled = !!disabled || loading;\n return (\n <button\n ref={ref as React.Ref<HTMLButtonElement>}\n className={merge(base, buttonClassName)}\n type=\"button\"\n disabled={isDisabled}\n aria-busy={loading || undefined}\n aria-disabled={isDisabled || undefined}\n {...btnProps}\n >\n {content}\n </button>\n );\n});\n\nButtonInner.displayName = \"Button\";\n\nexport const Button = ButtonInner;\n"]}
1
+ {"version":3,"sources":["../src/lib/Slot.tsx","../src/components/Button.variants.ts","../src/components/Button.tsx"],"names":["composeRefs","refs","node","ref","composeEventHandlers","parentHandler","childHandler","event","mergeClassName","slotClassName","childClassName","clsx","mergeStyle","slotStyle","childStyle","mergeProps","slotProps","childProps","mergedProps","propName","slotValue","childValue","isSlottable","child","React","Slot","children","forwardedRef","childArray","childRef","mergedRef","springTransition","buttonVariants","cva","gradientPresets","isBrowser","useReducedMotion","reduce","setReduce","_a","mq","onChange","ButtonInner","variant","size","loading","icon","iconPosition","gradient","customGradient","rounded","shadow","hover","fullWidth","iconOnly","className","disabled","asChild","rest","reduced","gradientClass","base","merge","content","jsxs","Fragment","jsx","onClick","target","rel","href","_ariaLabel","anchorClassName","anchorProps","isDisabled","handleAnchorClick","e","buttonClassName","btnProps","Button"],"mappings":"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","file":"chunk-XCZMLKPK.mjs","sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport { clsx } from \"clsx\";\n\n/**\n * Slot 컴포넌트\n *\n * Radix UI의 asChild 패턴을 구현합니다.\n * 자식 요소의 props와 ref를 병합하여 하나의 요소로 렌더링합니다.\n *\n * @example\n * // Button에서 asChild 사용\n * <Button asChild>\n * <Link href=\"/home\">홈으로</Link>\n * </Button>\n *\n * @see https://www.radix-ui.com/primitives/docs/utilities/slot\n */\n\ntype SlotProps = React.HTMLAttributes<HTMLElement> & {\n children?: React.ReactNode;\n};\n\n/**\n * 여러 ref를 하나로 합칩니다\n */\nfunction composeRefs<T>(\n ...refs: (React.Ref<T> | undefined)[]\n): React.RefCallback<T> {\n return (node) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(node);\n } else if (ref != null) {\n (ref as React.MutableRefObject<T | null>).current = node;\n }\n });\n };\n}\n\n/**\n * 이벤트 핸들러를 합성합니다\n * \n * 부모(slot) 핸들러를 먼저 실행하고, 그 다음 자식 핸들러를 실행합니다.\n * defaultPrevented가 true이면 자식 핸들러는 실행하지 않습니다.\n */\nfunction composeEventHandlers<E>(\n parentHandler?: (event: E) => void,\n childHandler?: (event: E) => void\n): (event: E) => void {\n return (event) => {\n parentHandler?.(event);\n if (!(event as unknown as { defaultPrevented: boolean }).defaultPrevented) {\n childHandler?.(event);\n }\n };\n}\n\n/**\n * className을 병합합니다\n */\nfunction mergeClassName(\n slotClassName?: string,\n childClassName?: string\n): string | undefined {\n if (!slotClassName && !childClassName) return undefined;\n return clsx(slotClassName, childClassName);\n}\n\n/**\n * style을 병합합니다\n */\nfunction mergeStyle(\n slotStyle?: React.CSSProperties,\n childStyle?: React.CSSProperties\n): React.CSSProperties | undefined {\n if (!slotStyle && !childStyle) return undefined;\n return { ...slotStyle, ...childStyle };\n}\n\n/**\n * props를 병합합니다 (이벤트 핸들러, className, style 등)\n */\nfunction mergeProps(\n slotProps: Record<string, unknown>,\n childProps: Record<string, unknown>\n): Record<string, unknown> {\n const mergedProps: Record<string, unknown> = { ...slotProps };\n\n for (const propName in childProps) {\n const slotValue = slotProps[propName];\n const childValue = childProps[propName];\n\n // 이벤트 핸들러 병합 (부모(slot) → 자식 순서)\n if (/^on[A-Z]/.test(propName)) {\n if (slotValue && childValue) {\n mergedProps[propName] = composeEventHandlers(\n slotValue as (event: unknown) => void,\n childValue as (event: unknown) => void\n );\n } else {\n mergedProps[propName] = childValue || slotValue;\n }\n }\n // className 병합\n else if (propName === \"className\") {\n mergedProps[propName] = mergeClassName(\n slotValue as string | undefined,\n childValue as string | undefined\n );\n }\n // style 병합\n else if (propName === \"style\") {\n mergedProps[propName] = mergeStyle(\n slotValue as React.CSSProperties | undefined,\n childValue as React.CSSProperties | undefined\n );\n }\n // 그 외: 자식 값 우선\n else {\n mergedProps[propName] = childValue !== undefined ? childValue : slotValue;\n }\n }\n\n return mergedProps;\n}\n\n/**\n * 유효한 단일 React 요소인지 확인\n */\nfunction isSlottable(child: React.ReactNode): child is React.ReactElement {\n return React.isValidElement(child);\n}\n\n/**\n * Slot 컴포넌트\n *\n * 자식 요소에 부모의 props를 주입합니다.\n * asChild 패턴을 구현할 때 사용합니다.\n */\nconst Slot = React.forwardRef<HTMLElement, SlotProps>(\n ({ children, ...slotProps }, forwardedRef) => {\n const childArray = React.Children.toArray(children);\n\n // 유효한 단일 자식이 있는지 확인\n if (childArray.length !== 1) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\n \"[Slot] asChild는 정확히 하나의 자식 요소가 필요합니다.\"\n );\n }\n return null;\n }\n\n const child = childArray[0];\n\n if (!isSlottable(child)) {\n if (process.env.NODE_ENV !== \"production\") {\n console.warn(\"[Slot] 자식은 유효한 React 요소여야 합니다.\");\n }\n return null;\n }\n\n // 자식 요소의 props와 ref 추출\n const childProps = child.props as Record<string, unknown>;\n const childRef = (child as unknown as { ref?: React.Ref<HTMLElement> }).ref;\n\n // props와 ref 병합\n const mergedProps = mergeProps(slotProps, childProps);\n const mergedRef = composeRefs(forwardedRef, childRef);\n\n return React.cloneElement(child, {\n ...mergedProps,\n ref: mergedRef,\n } as React.Attributes);\n }\n);\n\nSlot.displayName = \"Slot\";\n\nexport { Slot, composeRefs, mergeProps };\nexport type { SlotProps };\n","import { cva } from 'class-variance-authority'\n\n/**\n * HUA Spring Easing transition — 시그니처 \"쫀득한\" 느낌\n * cubic-bezier(0.34, 1.56, 0.64, 1)\n */\nconst springTransition =\n '[transition:transform_180ms_cubic-bezier(0.34,1.56,0.64,1),box-shadow_200ms_ease-out]'\n\nexport const buttonVariants = cva(\n // ── base ──\n 'inline-flex items-center justify-center whitespace-nowrap font-medium transition-all duration-200 disabled:pointer-events-none disabled:opacity-50 min-w-fit focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[var(--color-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-background)]',\n {\n variants: {\n /** 스타일 변형 */\n variant: {\n default:\n 'bg-[var(--color-primary)] text-[var(--color-primary-foreground)] hover:opacity-90',\n destructive:\n 'bg-[var(--color-destructive)] text-[var(--color-destructive-foreground)] hover:opacity-90 focus-visible:ring-[var(--color-destructive)]',\n outline:\n 'border-2 border-[var(--color-border)] bg-transparent text-[var(--color-foreground)] hover:bg-[var(--color-accent)] hover:text-[var(--color-accent-foreground)] focus-visible:ring-offset-0',\n secondary:\n 'bg-[var(--color-secondary)] text-[var(--color-secondary-foreground)] hover:opacity-80',\n ghost:\n 'bg-transparent text-[var(--color-foreground)] hover:bg-[var(--color-accent)] hover:text-[var(--color-accent-foreground)] focus-visible:ring-offset-0',\n link:\n 'bg-transparent text-[var(--color-primary)] underline hover:opacity-80 focus-visible:ring-offset-0',\n gradient:\n 'bg-gradient-to-r from-[var(--btn-gradient-from,theme(colors.teal.500))] to-[var(--btn-gradient-to,theme(colors.cyan.500))] text-white hover:shadow-lg',\n neon:\n 'bg-slate-900 dark:bg-slate-950 text-teal-400 border border-teal-500/50 shadow-lg shadow-[var(--btn-neon-glow,theme(colors.teal.500/20%))] hover:shadow-[var(--btn-neon-glow,theme(colors.teal.500/40%))] hover:border-teal-400',\n glass:\n 'bg-white/50 dark:bg-slate-900/50 backdrop-blur-md border border-slate-200/50 dark:border-slate-700/50 text-slate-900 dark:text-slate-100 hover:bg-white/70 dark:hover:bg-slate-900/70',\n },\n /** 크기 */\n size: {\n sm: 'h-8 px-4 py-2 text-sm',\n md: 'h-10 px-6 py-2 text-base',\n lg: 'h-12 px-8 py-3 text-lg',\n xl: 'h-14 px-10 py-4 text-xl',\n icon: 'h-10 w-10 p-0',\n },\n /** 모서리 둥글기 */\n rounded: {\n sm: 'rounded',\n md: 'rounded-md',\n lg: 'rounded-lg',\n full: 'rounded-full',\n },\n /** 그림자 */\n shadow: {\n none: '',\n sm: 'shadow-sm',\n md: 'shadow-md',\n lg: 'shadow-lg',\n xl: 'shadow-xl',\n },\n /** 호버 효과 — springy가 HUA-UI 시그니처 */\n hover: {\n springy: `hover:scale-[1.015] hover:shadow-md active:scale-[0.985] ${springTransition} transform-gpu`,\n scale:\n 'hover:scale-[1.015] active:scale-[0.985] transition-transform duration-150 ease-out transform-gpu',\n glow: 'hover:shadow-lg hover:shadow-primary/25 transition-shadow duration-200',\n slide: `hover:-translate-y-0.5 hover:shadow-md ${springTransition} transform-gpu`,\n none: '',\n },\n /** 전체 너비 */\n fullWidth: {\n true: 'w-full',\n false: '',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n rounded: 'md',\n shadow: 'md',\n hover: 'springy',\n fullWidth: false,\n },\n }\n)\n\n/** Gradient 프리셋 */\nexport const gradientPresets: Record<string, string> = {\n blue: 'from-teal-500 to-cyan-500',\n purple: 'from-purple-500 to-pink-500',\n green: 'from-green-500 to-emerald-500 dark:from-green-400 dark:to-emerald-400',\n orange: 'from-orange-500 to-red-500 dark:from-orange-300 dark:to-red-300',\n pink: 'from-pink-500 to-rose-500',\n}\n\nexport type { VariantProps } from 'class-variance-authority'\n","\"use client\";\n\nimport React from \"react\";\nimport { merge } from \"../lib/utils\";\nimport { buttonVariants, gradientPresets } from \"./Button.variants\";\nimport { Slot } from \"../lib/Slot\";\n\n/**\n * 버튼 스타일 변형 / Button style variant\n */\ntype Variant =\n | \"default\" | \"destructive\" | \"outline\" | \"secondary\"\n | \"ghost\" | \"link\" | \"gradient\" | \"neon\" | \"glass\";\n\n/**\n * 버튼 크기 / Button size\n */\ntype Size = \"sm\" | \"md\" | \"lg\" | \"xl\" | \"icon\";\n\n/**\n * 버튼 모서리 둥글기 / Button border radius\n */\ntype Rounded = \"sm\" | \"md\" | \"lg\" | \"full\";\n\n/**\n * 버튼 그림자 / Button shadow\n */\ntype Shadow = \"none\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\n/**\n * 버튼 호버 효과 / Button hover effect\n * \"springy\"가 HUA-UI 시그니처 - 공 튕기듯 미세한 반동\n */\ntype Hover = \"springy\" | \"scale\" | \"glow\" | \"slide\" | \"none\";\n\n/**\n * 그라디언트 색상 이름 / Gradient color name\n */\ntype GradientName = \"blue\" | \"purple\" | \"green\" | \"orange\" | \"pink\" | \"custom\";\n\n/**\n * Button 컴포넌트의 공통 props / Common props for Button component\n */\ntype CommonProps = {\n variant?: Variant;\n size?: Size;\n loading?: boolean;\n icon?: React.ReactNode;\n iconPosition?: \"left\" | \"right\";\n gradient?: GradientName;\n customGradient?: string;\n rounded?: Rounded;\n shadow?: Shadow;\n hover?: Hover;\n fullWidth?: boolean;\n iconOnly?: boolean;\n \"aria-label\"?: string;\n className?: string;\n disabled?: boolean;\n asChild?: boolean;\n};\n\ntype AnchorProps = CommonProps &\n Omit<React.AnchorHTMLAttributes<HTMLAnchorElement>, \"className\"> & {\n href: string;\n };\n\ntype NativeButtonProps = CommonProps &\n Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, \"className\" | \"type\"> & {\n href?: undefined;\n };\n\n/**\n * Button 컴포넌트의 props 타입 / Button component props type\n * href가 제공되면 앵커 태그로, 그렇지 않으면 버튼 태그로 렌더링됩니다.\n */\nexport type ButtonProps = AnchorProps | NativeButtonProps;\n\ntype AnchorOrButton = HTMLAnchorElement | HTMLButtonElement;\n\nconst isBrowser = typeof window !== \"undefined\";\nfunction useReducedMotion() {\n const [reduce, setReduce] = React.useState(false);\n React.useEffect(() => {\n if (!isBrowser || !(\"matchMedia\" in window)) return;\n const mq = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n const onChange = () => setReduce(!!mq.matches);\n onChange();\n mq.addEventListener?.(\"change\", onChange);\n return () => mq.removeEventListener?.(\"change\", onChange);\n }, []);\n return reduce;\n}\n\n/**\n * Button 컴포넌트 / Button component\n *\n * 다양한 스타일과 크기를 지원하는 범용 버튼 컴포넌트입니다.\n * href prop을 제공하면 앵커 태그로, 그렇지 않으면 버튼 태그로 렌더링됩니다.\n *\n * @example\n * <Button onClick={() => console.log('클릭')}>클릭하세요</Button>\n * <Button variant=\"destructive\" size=\"lg\">삭제</Button>\n * <Button variant=\"gradient\" gradient=\"purple\">그라디언트</Button>\n * <Button href=\"/about\" variant=\"link\">자세히 보기</Button>\n */\nconst ButtonInner = React.forwardRef<AnchorOrButton, ButtonProps>(function ButtonInner(\n {\n variant = \"default\",\n size = \"md\",\n loading = false,\n icon,\n iconPosition = \"left\",\n gradient = \"blue\",\n customGradient,\n rounded = \"md\",\n shadow = \"md\",\n hover = \"springy\",\n fullWidth,\n iconOnly,\n className,\n children,\n disabled,\n asChild = false,\n ...rest\n },\n ref\n) {\n const reduced = useReducedMotion();\n\n // gradient variant: 커스텀 그라디언트 클래스 처리\n const gradientClass =\n variant === \"gradient\"\n ? customGradient\n ? `bg-gradient-to-r ${customGradient}`\n : `bg-gradient-to-r ${gradientPresets[gradient] || gradientPresets.blue}`\n : undefined;\n\n const base = merge(\n buttonVariants({\n variant,\n size,\n rounded,\n shadow,\n hover: reduced ? \"none\" : hover,\n fullWidth: fullWidth ?? false,\n }),\n gradientClass,\n className\n );\n\n const Spinner = (\n <span role=\"status\" aria-live=\"polite\" className=\"-ml-1 mr-2 inline-flex\">\n <svg className=\"animate-spin h-4 w-4\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\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\" />\n </svg>\n <span className=\"sr-only\">로딩 중</span>\n </span>\n );\n\n const content = (\n <>\n {loading && Spinner}\n {!loading && icon && iconPosition === \"left\" && <span className=\"mr-2\">{icon}</span>}\n {children}\n {!loading && icon && iconPosition === \"right\" && <span className=\"ml-2\">{icon}</span>}\n </>\n );\n\n if (iconOnly && !(\"aria-label\" in rest) && process.env.NODE_ENV !== \"production\") {\n console.warn(\"[Button] iconOnly 사용 시 aria-label을 제공하세요.\");\n }\n\n // asChild 모드: Slot을 사용하여 자식 요소에 props 병합\n if (asChild) {\n const slotProps = {\n className: base,\n ref,\n disabled: disabled || loading,\n \"aria-busy\": loading || undefined,\n \"aria-disabled\": (disabled || loading) || undefined,\n ...rest,\n };\n return <Slot {...slotProps}>{children}</Slot>;\n }\n\n // 앵커 모드\n if (\"href\" in rest && rest.href) {\n const { onClick, target, rel, href, \"aria-label\": _ariaLabel, className: anchorClassName, ...anchorProps } = rest as AnchorProps;\n const isDisabled = !!disabled || loading;\n\n const handleAnchorClick: React.MouseEventHandler<HTMLAnchorElement> = (e) => {\n if (isDisabled) { e.preventDefault(); e.stopPropagation(); return; }\n onClick?.(e);\n };\n\n return (\n <a\n ref={ref as React.Ref<HTMLAnchorElement>}\n href={href}\n className={merge(base, anchorClassName)}\n onClick={handleAnchorClick}\n aria-busy={loading || undefined}\n aria-disabled={isDisabled || undefined}\n tabIndex={isDisabled ? -1 : anchorProps.tabIndex}\n target={target}\n rel={target === \"_blank\" ? rel ?? \"noopener noreferrer\" : rel}\n {...anchorProps}\n >\n {content}\n </a>\n );\n }\n\n // 버튼 모드\n const { className: buttonClassName, ...btnProps } = rest as NativeButtonProps;\n const isDisabled = !!disabled || loading;\n return (\n <button\n ref={ref as React.Ref<HTMLButtonElement>}\n className={merge(base, buttonClassName)}\n type=\"button\"\n disabled={isDisabled}\n aria-busy={loading || undefined}\n aria-disabled={isDisabled || undefined}\n {...btnProps}\n >\n {content}\n </button>\n );\n});\n\nButtonInner.displayName = \"Button\";\n\nexport const Button = ButtonInner;\n"]}
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ import {b}from'./chunk-U6CTBZ2U.mjs';import o from'react';import {jsxs,jsx}from'react/jsx-runtime';var P=o.forwardRef(({className:l,children:s,trigger:n,open:a,onOpenChange:i,position:r="bottom",align:M="center",offset:d=8,disabled:g=false,contentClassName:x,fullWidth:y=false,...N},R)=>{let[T,w]=o.useState(false),f=o.useRef(null),b$1=o.useRef(null),m=a!==void 0,u=m?a:T,p=o.useCallback(e=>{g||(m||w(e),i==null||i(e));},[g,m,i]),L=()=>{p(!u);};o.useEffect(()=>{let e=v=>{f.current&&b$1.current&&!f.current.contains(v.target)&&!b$1.current.contains(v.target)&&p(false);};if(u)return document.addEventListener("mousedown",e),()=>{document.removeEventListener("mousedown",e);}},[u,p]);let k=()=>{let e="absolute z-50";switch(r){case "top":return b(e,"bottom-full",`mb-${Math.max(1,Math.floor(d/4))}`);case "bottom":return b(e,"top-full",`mt-${Math.max(1,Math.floor(d/4))}`);case "left":return b(e,"right-full",`mr-${Math.max(1,Math.floor(d/4))}`);case "right":return b(e,"left-full",`ml-${Math.max(1,Math.floor(d/4))}`);default:return b(e,"top-full",`mt-${Math.max(1,Math.floor(d/4))}`)}},E=()=>{switch(M){case "start":return r==="top"||r==="bottom"?"left-0":"top-0";case "end":return r==="top"||r==="bottom"?"right-0":"bottom-0";default:return r==="top"||r==="bottom"?"left-1/2 -translate-x-1/2":"top-1/2 -translate-y-1/2"}},H=()=>{let e="absolute w-0 h-0 border-4 border-transparent";switch(r){case "top":return `${e} top-full left-1/2 -translate-x-1/2 border-t-gray-200 dark:border-t-gray-700`;case "bottom":return `${e} bottom-full left-1/2 -translate-x-1/2 border-b-gray-200 dark:border-b-gray-700`;case "left":return `${e} left-full top-1/2 -translate-y-1/2 border-l-gray-200 dark:border-l-gray-700`;case "right":return `${e} right-full top-1/2 -translate-y-1/2 border-r-gray-200 dark:border-r-gray-700`;default:return `${e} bottom-full left-1/2 -translate-x-1/2 border-b-gray-200 dark:border-b-gray-700`}};return jsxs("div",{ref:R,className:b("relative",l),...N,children:[jsx("div",{ref:f,onClick:L,className:b(y?"block w-full":"inline-block","cursor-pointer"),children:n}),u&&jsxs("div",{ref:b$1,className:b("bg-popover text-popover-foreground border border-border rounded-lg shadow-lg p-4 min-w-[200px]",k(),E(),x),children:[jsx("div",{className:H()}),jsx("div",{className:"relative z-10",children:s})]})]})});P.displayName="Popover";var C=o.forwardRef(({className:l,children:s,...n},a)=>jsx("div",{ref:a,className:b("inline-block cursor-pointer",l),...n,children:s}));C.displayName="PopoverTrigger";var $=o.forwardRef(({className:l,children:s,...n},a)=>jsx("div",{ref:a,className:b("bg-popover text-popover-foreground border border-border rounded-lg shadow-lg p-4",l),...n,children:s}));$.displayName="PopoverContent";export{P as a,C as b,$ as c};//# sourceMappingURL=chunk-XGHT7WMO.mjs.map
3
+ //# sourceMappingURL=chunk-XGHT7WMO.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Popover.tsx"],"names":["Popover","React","className","children","trigger","controlledOpen","onOpenChange","position","align","offset","disabled","contentClassName","fullWidth","props","ref","internalOpen","setInternalOpen","triggerRef","popoverRef","isControlled","isOpen","handleOpenChange","newOpen","handleTriggerClick","handleClickOutside","event","getPositionClasses","baseClasses","merge","getAlignmentClasses","getArrowClasses","jsxs","jsx","PopoverTrigger","PopoverContent"],"mappings":"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","file":"chunk-XGHT7WMO.mjs","sourcesContent":["\"use client\"\n\nimport React from \"react\"\nimport { merge } from \"../lib/utils\"\n\n/**\n * Popover 컴포넌트의 props / Popover component props\n * @typedef {Object} PopoverProps\n * @property {React.ReactNode} children - Popover 내용 / Popover content\n * @property {React.ReactNode} trigger - Popover를 열기 위한 트리거 요소 / Trigger element to open popover\n * @property {boolean} [open] - 제어 모드에서 열림/닫힘 상태 / Open/close state in controlled mode\n * @property {(open: boolean) => void} [onOpenChange] - 상태 변경 콜백 / State change callback\n * @property {\"top\" | \"bottom\" | \"left\" | \"right\"} [position=\"bottom\"] - Popover 표시 위치 / Popover display position\n * @property {\"start\" | \"center\" | \"end\"} [align=\"center\"] - Popover 정렬 / Popover alignment\n * @property {number} [offset=8] - 트리거와 Popover 사이 간격 (px) / Spacing between trigger and popover (px)\n * @property {boolean} [disabled=false] - Popover 비활성화 여부 / Disable popover\n * @extends {React.HTMLAttributes<HTMLDivElement>}\n */\nexport interface PopoverProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n trigger: React.ReactNode\n open?: boolean\n onOpenChange?: (open: boolean) => void\n position?: \"top\" | \"bottom\" | \"left\" | \"right\"\n align?: \"start\" | \"center\" | \"end\"\n offset?: number\n disabled?: boolean\n /** Popover 콘텐츠 영역 추가 클래스 / Additional class for popover content area */\n contentClassName?: string\n /** 트리거를 full-width로 렌더링 (DatePicker 등) / Render trigger as full-width */\n fullWidth?: boolean\n}\n\n/**\n * Popover 컴포넌트 / Popover component\n * \n * 트리거 요소를 클릭하면 표시되는 팝오버 컴포넌트입니다.\n * 외부 클릭 시 자동으로 닫힙니다.\n * \n * Popover component that appears when the trigger element is clicked.\n * Automatically closes when clicking outside.\n * \n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <Popover trigger={<Button>열기</Button>}>\n * <div className=\"p-4\">Popover 내용</div>\n * </Popover>\n * \n * @example\n * // 제어 모드 / Controlled mode\n * const [open, setOpen] = useState(false)\n * <Popover \n * open={open}\n * onOpenChange={setOpen}\n * trigger={<Button>제어 모드</Button>}\n * position=\"top\"\n * >\n * <div className=\"p-4\">내용</div>\n * </Popover>\n * \n * @param {PopoverProps} props - Popover 컴포넌트의 props / Popover component props\n * @param {React.Ref<HTMLDivElement>} ref - div 요소 ref / div element ref\n * @returns {JSX.Element} Popover 컴포넌트 / Popover component\n */\nconst Popover = React.forwardRef<HTMLDivElement, PopoverProps>(\n ({ \n className,\n children,\n trigger,\n open: controlledOpen,\n onOpenChange,\n position = \"bottom\",\n align = \"center\",\n offset = 8,\n disabled = false,\n contentClassName,\n fullWidth = false,\n ...props\n }, ref) => {\n const [internalOpen, setInternalOpen] = React.useState(false)\n const triggerRef = React.useRef<HTMLDivElement>(null)\n const popoverRef = React.useRef<HTMLDivElement>(null)\n const isControlled = controlledOpen !== undefined\n const isOpen = isControlled ? controlledOpen : internalOpen\n\n const handleOpenChange = React.useCallback((newOpen: boolean) => {\n if (disabled) return\n\n if (!isControlled) {\n setInternalOpen(newOpen)\n }\n onOpenChange?.(newOpen)\n }, [disabled, isControlled, onOpenChange])\n\n const handleTriggerClick = () => {\n handleOpenChange(!isOpen)\n }\n\n React.useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n triggerRef.current && \n popoverRef.current && \n !triggerRef.current.contains(event.target as Node) &&\n !popoverRef.current.contains(event.target as Node)\n ) {\n handleOpenChange(false)\n }\n }\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside)\n return () => {\n document.removeEventListener('mousedown', handleClickOutside)\n }\n }\n }, [isOpen, handleOpenChange])\n\n const getPositionClasses = () => {\n const baseClasses = \"absolute z-50\"\n\n switch (position) {\n case \"top\":\n return merge(baseClasses, \"bottom-full\", `mb-${Math.max(1, Math.floor(offset / 4))}`)\n case \"bottom\":\n return merge(baseClasses, \"top-full\", `mt-${Math.max(1, Math.floor(offset / 4))}`)\n case \"left\":\n return merge(baseClasses, \"right-full\", `mr-${Math.max(1, Math.floor(offset / 4))}`)\n case \"right\":\n return merge(baseClasses, \"left-full\", `ml-${Math.max(1, Math.floor(offset / 4))}`)\n default:\n return merge(baseClasses, \"top-full\", `mt-${Math.max(1, Math.floor(offset / 4))}`)\n }\n }\n\n const getAlignmentClasses = () => {\n switch (align) {\n case \"start\":\n if (position === \"top\" || position === \"bottom\") {\n return \"left-0\"\n } else {\n return \"top-0\"\n }\n case \"end\":\n if (position === \"top\" || position === \"bottom\") {\n return \"right-0\"\n } else {\n return \"bottom-0\"\n }\n case \"center\":\n default:\n if (position === \"top\" || position === \"bottom\") {\n return \"left-1/2 -translate-x-1/2\"\n } else {\n return \"top-1/2 -translate-y-1/2\"\n }\n }\n }\n\n const getArrowClasses = () => {\n const baseClasses = \"absolute w-0 h-0 border-4 border-transparent\"\n \n switch (position) {\n case \"top\":\n return `${baseClasses} top-full left-1/2 -translate-x-1/2 border-t-gray-200 dark:border-t-gray-700`\n case \"bottom\":\n return `${baseClasses} bottom-full left-1/2 -translate-x-1/2 border-b-gray-200 dark:border-b-gray-700`\n case \"left\":\n return `${baseClasses} left-full top-1/2 -translate-y-1/2 border-l-gray-200 dark:border-l-gray-700`\n case \"right\":\n return `${baseClasses} right-full top-1/2 -translate-y-1/2 border-r-gray-200 dark:border-r-gray-700`\n default:\n return `${baseClasses} bottom-full left-1/2 -translate-x-1/2 border-b-gray-200 dark:border-b-gray-700`\n }\n }\n\n return (\n <div ref={ref} className={merge(\"relative\", className)} {...props}>\n {/* 트리거 */}\n <div\n ref={triggerRef}\n onClick={handleTriggerClick}\n className={merge(fullWidth ? \"block w-full\" : \"inline-block\", \"cursor-pointer\")}\n >\n {trigger}\n </div>\n\n {/* 팝오버 */}\n {isOpen && (\n <div\n ref={popoverRef}\n className={merge(\n \"bg-popover text-popover-foreground border border-border rounded-lg shadow-lg p-4 min-w-[200px]\",\n getPositionClasses(),\n getAlignmentClasses(),\n contentClassName\n )}\n >\n {/* 화살표 */}\n <div className={getArrowClasses()} />\n \n {/* 내용 */}\n <div className=\"relative z-10\">\n {children}\n </div>\n </div>\n )}\n </div>\n )\n }\n)\nPopover.displayName = \"Popover\"\n\n// 편의 컴포넌트들\nexport const PopoverTrigger = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={merge(\"inline-block cursor-pointer\", className)}\n {...props}\n >\n {children}\n </div>\n )\n)\nPopoverTrigger.displayName = \"PopoverTrigger\"\n\nexport const PopoverContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, children, ...props }, ref) => (\n <div\n ref={ref}\n className={merge(\"bg-popover text-popover-foreground border border-border rounded-lg shadow-lg p-4\", className)}\n {...props}\n >\n {children}\n </div>\n )\n)\nPopoverContent.displayName = \"PopoverContent\"\n\nexport { Popover } "]}
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ import {b}from'./chunk-U6CTBZ2U.mjs';import w from'react';import {jsxs,jsx}from'react/jsx-runtime';var R=w.forwardRef(({value:r,defaultValue:B=0,min:n,max:a,step:k=1,onChange:p,disabled:s=false,size:E="md",showButtons:N=true,buttonLayout:H="horizontal",className:y,...c},x)=>{let[V,z]=w.useState(B),f=r!==void 0,i=f?r:V,l=w.useCallback(o=>{let t=o;n!==void 0&&(t=Math.max(n,t)),a!==void 0&&(t=Math.min(a,t)),f||z(t),p==null||p(t);},[f,n,a,p]),v=()=>{s||l(i+k);},m=()=>{s||l(i-k);},C=o=>{let t=o.target.value;if(t===""||t==="-")return;let g=parseFloat(t);isNaN(g)||(n!==void 0&&g<n?l(n):l(g));},I=o=>{var t;n!==void 0&&i<n&&l(n),a!==void 0&&i>a&&l(a),(t=c.onBlur)==null||t.call(c,o);},L=o=>{o.key==="ArrowUp"?(o.preventDefault(),v()):o.key==="ArrowDown"&&(o.preventDefault(),m());},d={sm:{input:"h-8 text-sm px-2 py-1",button:"w-8 h-8 text-sm",wrapper:"gap-1"},md:{input:"h-10 text-sm px-3 py-2",button:"w-10 h-10 text-sm",wrapper:"gap-2"},lg:{input:"h-12 text-base px-4 py-2.5",button:"w-12 h-12 text-base",wrapper:"gap-2"}}[E],b$1=b("flex items-center justify-center rounded-md border border-input bg-background","hover:bg-secondary hover:border-primary/50 active:scale-95","transition-all duration-150","disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-background","focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2",d.button),M=n===void 0||i>n,D=a===void 0||i<a;return H==="vertical"?jsxs("div",{className:b("inline-flex items-center",d.wrapper,y),children:[jsxs("div",{className:"flex flex-col gap-0.5",children:[jsx("button",{type:"button",onClick:v,disabled:s||!D,className:b(b$1,"rounded-b-none h-[calc(50%-1px)]"),"aria-label":"Increase",children:jsx(K,{className:"w-3 h-3"})}),jsx("button",{type:"button",onClick:m,disabled:s||!M,className:b(b$1,"rounded-t-none h-[calc(50%-1px)]"),"aria-label":"Decrease",children:jsx(W,{className:"w-3 h-3"})})]}),jsx("input",{ref:x,type:"text",inputMode:"numeric",pattern:n!==void 0&&n>=0?"[0-9]*":"-?[0-9]*",value:i,onChange:C,onKeyDown:L,onBlur:I,disabled:s,className:b("w-16 text-center rounded-md border border-input bg-background","focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2","disabled:cursor-not-allowed disabled:opacity-50","[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",d.input),...c})]}):jsxs("div",{className:b("inline-flex items-center",d.wrapper,y),children:[N&&jsx("button",{type:"button",onClick:m,disabled:s||!M,className:b$1,"aria-label":"Decrease",children:jsx(T,{className:"w-3.5 h-3.5"})}),jsx("input",{ref:x,type:"text",inputMode:"numeric",pattern:n!==void 0&&n>=0?"[0-9]*":"-?[0-9]*",value:i,onChange:C,onKeyDown:L,onBlur:I,disabled:s,className:b("w-16 text-center rounded-md border border-input bg-background","focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2","disabled:cursor-not-allowed disabled:opacity-50","[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none",d.input),...c}),N&&jsx("button",{type:"button",onClick:v,disabled:s||!D,className:b$1,"aria-label":"Increase",children:jsx(j,{className:"w-3.5 h-3.5"})})]})});R.displayName="NumberInput";function T({className:r}){return jsx("svg",{className:r,fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M20 12H4"})})}function j({className:r}){return jsx("svg",{className:r,fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 4v16m8-8H4"})})}function K({className:r}){return jsx("svg",{className:r,fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M5 15l7-7 7 7"})})}function W({className:r}){return jsx("svg",{className:r,fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M19 9l-7 7-7-7"})})}export{R as a};//# sourceMappingURL=chunk-XL4KTJ4L.mjs.map
3
+ //# sourceMappingURL=chunk-XL4KTJ4L.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/NumberInput.tsx"],"names":["NumberInput","React","controlledValue","defaultValue","min","max","step","onChange","disabled","size","showButtons","buttonLayout","className","props","ref","internalValue","setInternalValue","isControlled","currentValue","updateValue","newValue","clampedValue","increment","decrement","handleInputChange","e","inputValue","handleBlur","_a","handleKeyDown","sizes","buttonBase","merge","canDecrement","canIncrement","jsxs","jsx","ChevronUp","ChevronDown","Minus","Plus"],"mappings":"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","file":"chunk-VWSBJUNI.mjs","sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport { merge } from \"../lib/utils\";\n\n/**\n * NumberInput 컴포넌트의 props / NumberInput component props\n * @typedef {Object} NumberInputProps\n * @property {number} [value] - 현재 값 / Current value\n * @property {number} [defaultValue=0] - 기본 값 / Default value\n * @property {number} [min] - 최소 값 / Minimum value\n * @property {number} [max] - 최대 값 / Maximum value\n * @property {number} [step=1] - 증감 단위 / Step amount\n * @property {(value: number) => void} [onChange] - 값 변경 콜백 / Value change callback\n * @property {boolean} [disabled=false] - 비활성화 / Disabled state\n * @property {\"sm\" | \"md\" | \"lg\"} [size=\"md\"] - 크기 / Size\n * @property {boolean} [showButtons=true] - +/- 버튼 표시 / Show +/- buttons\n * @property {\"horizontal\" | \"vertical\"} [buttonLayout=\"horizontal\"] - 버튼 배치 / Button layout\n * @property {string} [className] - 추가 CSS 클래스 / Additional CSS class\n */\nexport interface NumberInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"onChange\" | \"value\" | \"defaultValue\" | \"size\" | \"type\"> {\n value?: number;\n defaultValue?: number;\n min?: number;\n max?: number;\n step?: number;\n onChange?: (value: number) => void;\n disabled?: boolean;\n size?: \"sm\" | \"md\" | \"lg\";\n showButtons?: boolean;\n buttonLayout?: \"horizontal\" | \"vertical\";\n}\n\n/**\n * NumberInput 컴포넌트 / NumberInput component\n *\n * 숫자 입력을 위한 컴포넌트로, 커스텀 +/- 버튼을 제공합니다.\n * 브라우저 기본 스피너 대신 스타일링된 버튼을 사용합니다.\n *\n * Number input component with custom +/- buttons.\n * Uses styled buttons instead of browser default spinners.\n *\n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <NumberInput value={count} onChange={setCount} />\n *\n * @example\n * // 범위 지정 / With range\n * <NumberInput min={0} max={100} step={5} />\n *\n * @example\n * // 세로 버튼 / Vertical buttons\n * <NumberInput buttonLayout=\"vertical\" />\n */\nconst NumberInput = React.forwardRef<HTMLInputElement, NumberInputProps>(\n (\n {\n value: controlledValue,\n defaultValue = 0,\n min,\n max,\n step = 1,\n onChange,\n disabled = false,\n size = \"md\",\n showButtons = true,\n buttonLayout = \"horizontal\",\n className,\n ...props\n },\n ref\n ) => {\n const [internalValue, setInternalValue] = React.useState(defaultValue);\n const isControlled = controlledValue !== undefined;\n const currentValue = isControlled ? controlledValue : internalValue;\n\n const updateValue = React.useCallback(\n (newValue: number) => {\n // Clamp to min/max\n let clampedValue = newValue;\n if (min !== undefined) clampedValue = Math.max(min, clampedValue);\n if (max !== undefined) clampedValue = Math.min(max, clampedValue);\n\n if (!isControlled) {\n setInternalValue(clampedValue);\n }\n onChange?.(clampedValue);\n },\n [isControlled, min, max, onChange]\n );\n\n const increment = () => {\n if (disabled) return;\n updateValue(currentValue + step);\n };\n\n const decrement = () => {\n if (disabled) return;\n updateValue(currentValue - step);\n };\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const inputValue = e.target.value;\n // Allow empty string, minus sign alone (for typing negative numbers), or valid numbers\n if (inputValue === \"\" || inputValue === \"-\") {\n return;\n }\n const newValue = parseFloat(inputValue);\n if (!isNaN(newValue)) {\n // If min is set, enforce it on direct input\n if (min !== undefined && newValue < min) {\n updateValue(min);\n } else {\n updateValue(newValue);\n }\n }\n };\n\n const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n // On blur, ensure value is within bounds\n if (min !== undefined && currentValue < min) {\n updateValue(min);\n }\n if (max !== undefined && currentValue > max) {\n updateValue(max);\n }\n props.onBlur?.(e);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n increment();\n } else if (e.key === \"ArrowDown\") {\n e.preventDefault();\n decrement();\n }\n };\n\n // Spacing system: 4px grid\n // sm: h-8 (32px), px-2 (8px), gap-1 (4px)\n // md: h-10 (40px), px-3 (12px), gap-2 (8px)\n // lg: h-12 (48px), px-4 (16px), gap-2 (8px)\n const sizeClasses = {\n sm: {\n input: \"h-8 text-sm px-2 py-1\",\n button: \"w-8 h-8 text-sm\",\n wrapper: \"gap-1\",\n },\n md: {\n input: \"h-10 text-sm px-3 py-2\",\n button: \"w-10 h-10 text-sm\",\n wrapper: \"gap-2\",\n },\n lg: {\n input: \"h-12 text-base px-4 py-2.5\",\n button: \"w-12 h-12 text-base\",\n wrapper: \"gap-2\",\n },\n };\n\n const sizes = sizeClasses[size];\n\n const buttonBase = merge(\n \"flex items-center justify-center rounded-md border border-input bg-background\",\n \"hover:bg-secondary hover:border-primary/50 active:scale-95\",\n \"transition-all duration-150\",\n \"disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-background\",\n \"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2\",\n sizes.button\n );\n\n const canDecrement = min === undefined || currentValue > min;\n const canIncrement = max === undefined || currentValue < max;\n\n if (buttonLayout === \"vertical\") {\n return (\n <div className={merge(\"inline-flex items-center\", sizes.wrapper, className)}>\n <div className=\"flex flex-col gap-0.5\">\n <button\n type=\"button\"\n onClick={increment}\n disabled={disabled || !canIncrement}\n className={merge(buttonBase, \"rounded-b-none h-[calc(50%-1px)]\")}\n aria-label=\"Increase\"\n >\n <ChevronUp className=\"w-3 h-3\" />\n </button>\n <button\n type=\"button\"\n onClick={decrement}\n disabled={disabled || !canDecrement}\n className={merge(buttonBase, \"rounded-t-none h-[calc(50%-1px)]\")}\n aria-label=\"Decrease\"\n >\n <ChevronDown className=\"w-3 h-3\" />\n </button>\n </div>\n <input\n ref={ref}\n type=\"text\"\n inputMode=\"numeric\"\n pattern={min !== undefined && min >= 0 ? \"[0-9]*\" : \"-?[0-9]*\"}\n value={currentValue}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n disabled={disabled}\n className={merge(\n \"w-16 text-center rounded-md border border-input bg-background\",\n \"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none\",\n sizes.input\n )}\n {...props}\n />\n </div>\n );\n }\n\n return (\n <div className={merge(\"inline-flex items-center\", sizes.wrapper, className)}>\n {showButtons && (\n <button\n type=\"button\"\n onClick={decrement}\n disabled={disabled || !canDecrement}\n className={buttonBase}\n aria-label=\"Decrease\"\n >\n <Minus className=\"w-3.5 h-3.5\" />\n </button>\n )}\n <input\n ref={ref}\n type=\"text\"\n inputMode=\"numeric\"\n pattern={min !== undefined && min >= 0 ? \"[0-9]*\" : \"-?[0-9]*\"}\n value={currentValue}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n disabled={disabled}\n className={merge(\n \"w-16 text-center rounded-md border border-input bg-background\",\n \"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none\",\n sizes.input\n )}\n {...props}\n />\n {showButtons && (\n <button\n type=\"button\"\n onClick={increment}\n disabled={disabled || !canIncrement}\n className={buttonBase}\n aria-label=\"Increase\"\n >\n <Plus className=\"w-3.5 h-3.5\" />\n </button>\n )}\n </div>\n );\n }\n);\n\nNumberInput.displayName = \"NumberInput\";\n\n// Simple icon components to avoid external dependency\nfunction Minus({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M20 12H4\" />\n </svg>\n );\n}\n\nfunction Plus({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 4v16m8-8H4\" />\n </svg>\n );\n}\n\nfunction ChevronUp({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 15l7-7 7 7\" />\n </svg>\n );\n}\n\nfunction ChevronDown({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n </svg>\n );\n}\n\nexport { NumberInput };\n"]}
1
+ {"version":3,"sources":["../src/components/NumberInput.tsx"],"names":["NumberInput","React","controlledValue","defaultValue","min","max","step","onChange","disabled","size","showButtons","buttonLayout","className","props","ref","internalValue","setInternalValue","isControlled","currentValue","updateValue","newValue","clampedValue","increment","decrement","handleInputChange","e","inputValue","handleBlur","_a","handleKeyDown","sizes","buttonBase","merge","canDecrement","canIncrement","jsxs","jsx","ChevronUp","ChevronDown","Minus","Plus"],"mappings":"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","file":"chunk-XL4KTJ4L.mjs","sourcesContent":["\"use client\";\n\nimport React from \"react\";\nimport { merge } from \"../lib/utils\";\n\n/**\n * NumberInput 컴포넌트의 props / NumberInput component props\n * @typedef {Object} NumberInputProps\n * @property {number} [value] - 현재 값 / Current value\n * @property {number} [defaultValue=0] - 기본 값 / Default value\n * @property {number} [min] - 최소 값 / Minimum value\n * @property {number} [max] - 최대 값 / Maximum value\n * @property {number} [step=1] - 증감 단위 / Step amount\n * @property {(value: number) => void} [onChange] - 값 변경 콜백 / Value change callback\n * @property {boolean} [disabled=false] - 비활성화 / Disabled state\n * @property {\"sm\" | \"md\" | \"lg\"} [size=\"md\"] - 크기 / Size\n * @property {boolean} [showButtons=true] - +/- 버튼 표시 / Show +/- buttons\n * @property {\"horizontal\" | \"vertical\"} [buttonLayout=\"horizontal\"] - 버튼 배치 / Button layout\n * @property {string} [className] - 추가 CSS 클래스 / Additional CSS class\n */\nexport interface NumberInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, \"onChange\" | \"value\" | \"defaultValue\" | \"size\" | \"type\"> {\n value?: number;\n defaultValue?: number;\n min?: number;\n max?: number;\n step?: number;\n onChange?: (value: number) => void;\n disabled?: boolean;\n size?: \"sm\" | \"md\" | \"lg\";\n showButtons?: boolean;\n buttonLayout?: \"horizontal\" | \"vertical\";\n}\n\n/**\n * NumberInput 컴포넌트 / NumberInput component\n *\n * 숫자 입력을 위한 컴포넌트로, 커스텀 +/- 버튼을 제공합니다.\n * 브라우저 기본 스피너 대신 스타일링된 버튼을 사용합니다.\n *\n * Number input component with custom +/- buttons.\n * Uses styled buttons instead of browser default spinners.\n *\n * @component\n * @example\n * // 기본 사용 / Basic usage\n * <NumberInput value={count} onChange={setCount} />\n *\n * @example\n * // 범위 지정 / With range\n * <NumberInput min={0} max={100} step={5} />\n *\n * @example\n * // 세로 버튼 / Vertical buttons\n * <NumberInput buttonLayout=\"vertical\" />\n */\nconst NumberInput = React.forwardRef<HTMLInputElement, NumberInputProps>(\n (\n {\n value: controlledValue,\n defaultValue = 0,\n min,\n max,\n step = 1,\n onChange,\n disabled = false,\n size = \"md\",\n showButtons = true,\n buttonLayout = \"horizontal\",\n className,\n ...props\n },\n ref\n ) => {\n const [internalValue, setInternalValue] = React.useState(defaultValue);\n const isControlled = controlledValue !== undefined;\n const currentValue = isControlled ? controlledValue : internalValue;\n\n const updateValue = React.useCallback(\n (newValue: number) => {\n // Clamp to min/max\n let clampedValue = newValue;\n if (min !== undefined) clampedValue = Math.max(min, clampedValue);\n if (max !== undefined) clampedValue = Math.min(max, clampedValue);\n\n if (!isControlled) {\n setInternalValue(clampedValue);\n }\n onChange?.(clampedValue);\n },\n [isControlled, min, max, onChange]\n );\n\n const increment = () => {\n if (disabled) return;\n updateValue(currentValue + step);\n };\n\n const decrement = () => {\n if (disabled) return;\n updateValue(currentValue - step);\n };\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const inputValue = e.target.value;\n // Allow empty string, minus sign alone (for typing negative numbers), or valid numbers\n if (inputValue === \"\" || inputValue === \"-\") {\n return;\n }\n const newValue = parseFloat(inputValue);\n if (!isNaN(newValue)) {\n // If min is set, enforce it on direct input\n if (min !== undefined && newValue < min) {\n updateValue(min);\n } else {\n updateValue(newValue);\n }\n }\n };\n\n const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {\n // On blur, ensure value is within bounds\n if (min !== undefined && currentValue < min) {\n updateValue(min);\n }\n if (max !== undefined && currentValue > max) {\n updateValue(max);\n }\n props.onBlur?.(e);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"ArrowUp\") {\n e.preventDefault();\n increment();\n } else if (e.key === \"ArrowDown\") {\n e.preventDefault();\n decrement();\n }\n };\n\n // Spacing system: 4px grid\n // sm: h-8 (32px), px-2 (8px), gap-1 (4px)\n // md: h-10 (40px), px-3 (12px), gap-2 (8px)\n // lg: h-12 (48px), px-4 (16px), gap-2 (8px)\n const sizeClasses = {\n sm: {\n input: \"h-8 text-sm px-2 py-1\",\n button: \"w-8 h-8 text-sm\",\n wrapper: \"gap-1\",\n },\n md: {\n input: \"h-10 text-sm px-3 py-2\",\n button: \"w-10 h-10 text-sm\",\n wrapper: \"gap-2\",\n },\n lg: {\n input: \"h-12 text-base px-4 py-2.5\",\n button: \"w-12 h-12 text-base\",\n wrapper: \"gap-2\",\n },\n };\n\n const sizes = sizeClasses[size];\n\n const buttonBase = merge(\n \"flex items-center justify-center rounded-md border border-input bg-background\",\n \"hover:bg-secondary hover:border-primary/50 active:scale-95\",\n \"transition-all duration-150\",\n \"disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-background\",\n \"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2\",\n sizes.button\n );\n\n const canDecrement = min === undefined || currentValue > min;\n const canIncrement = max === undefined || currentValue < max;\n\n if (buttonLayout === \"vertical\") {\n return (\n <div className={merge(\"inline-flex items-center\", sizes.wrapper, className)}>\n <div className=\"flex flex-col gap-0.5\">\n <button\n type=\"button\"\n onClick={increment}\n disabled={disabled || !canIncrement}\n className={merge(buttonBase, \"rounded-b-none h-[calc(50%-1px)]\")}\n aria-label=\"Increase\"\n >\n <ChevronUp className=\"w-3 h-3\" />\n </button>\n <button\n type=\"button\"\n onClick={decrement}\n disabled={disabled || !canDecrement}\n className={merge(buttonBase, \"rounded-t-none h-[calc(50%-1px)]\")}\n aria-label=\"Decrease\"\n >\n <ChevronDown className=\"w-3 h-3\" />\n </button>\n </div>\n <input\n ref={ref}\n type=\"text\"\n inputMode=\"numeric\"\n pattern={min !== undefined && min >= 0 ? \"[0-9]*\" : \"-?[0-9]*\"}\n value={currentValue}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n disabled={disabled}\n className={merge(\n \"w-16 text-center rounded-md border border-input bg-background\",\n \"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none\",\n sizes.input\n )}\n {...props}\n />\n </div>\n );\n }\n\n return (\n <div className={merge(\"inline-flex items-center\", sizes.wrapper, className)}>\n {showButtons && (\n <button\n type=\"button\"\n onClick={decrement}\n disabled={disabled || !canDecrement}\n className={buttonBase}\n aria-label=\"Decrease\"\n >\n <Minus className=\"w-3.5 h-3.5\" />\n </button>\n )}\n <input\n ref={ref}\n type=\"text\"\n inputMode=\"numeric\"\n pattern={min !== undefined && min >= 0 ? \"[0-9]*\" : \"-?[0-9]*\"}\n value={currentValue}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onBlur={handleBlur}\n disabled={disabled}\n className={merge(\n \"w-16 text-center rounded-md border border-input bg-background\",\n \"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2\",\n \"disabled:cursor-not-allowed disabled:opacity-50\",\n \"[appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none\",\n sizes.input\n )}\n {...props}\n />\n {showButtons && (\n <button\n type=\"button\"\n onClick={increment}\n disabled={disabled || !canIncrement}\n className={buttonBase}\n aria-label=\"Increase\"\n >\n <Plus className=\"w-3.5 h-3.5\" />\n </button>\n )}\n </div>\n );\n }\n);\n\nNumberInput.displayName = \"NumberInput\";\n\n// Simple icon components to avoid external dependency\nfunction Minus({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M20 12H4\" />\n </svg>\n );\n}\n\nfunction Plus({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 4v16m8-8H4\" />\n </svg>\n );\n}\n\nfunction ChevronUp({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 15l7-7 7 7\" />\n </svg>\n );\n}\n\nfunction ChevronDown({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n >\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n </svg>\n );\n}\n\nexport { NumberInput };\n"]}
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ import {a}from'./chunk-CVWWS25A.mjs';import {b as b$1}from'./chunk-U6CTBZ2U.mjs';import x from'react';import {cva}from'class-variance-authority';import {jsxs,Fragment,jsx}from'react/jsx-runtime';var y=cva("relative w-full",{variants:{spacing:{none:"",sm:"py-12 sm:py-16",md:"py-16 sm:py-20 lg:py-24",lg:"py-20 sm:py-28",xl:"py-28 sm:py-36"},background:{none:"",muted:"bg-muted/30",accent:"bg-accent/5",primary:"bg-primary/5"}},defaultVariants:{spacing:"lg",background:"none"}}),b={width:"80px",height:"3px",borderRadius:"9999px",background:"linear-gradient(90deg, var(--color-primary, hsl(var(--primary))), var(--color-accent, hsl(var(--accent-foreground))))",marginBottom:"1.5rem"};function v({config:e}){let n=e.align!=="left";return jsxs("div",{className:b$1("mb-16",n&&"text-center"),children:[e.decorator!==false&&jsx("div",{style:b,className:b$1(n&&"mx-auto"),"aria-hidden":"true"}),jsx("h2",{className:"text-3xl md:text-5xl font-extrabold mb-4",children:e.title}),e.subtitle&&jsx("p",{className:"text-lg text-muted-foreground max-w-2xl mx-auto",children:e.subtitle}),e.action&&jsx("div",{className:"mt-6",children:e.action})]})}var S=x.forwardRef(({className:e,spacing:n,background:c,container:l="lg",containerPadding:p="none",header:r,fullWidth:d=false,children:m,...g},u)=>{let o=jsxs(Fragment,{children:[r&&jsx(v,{config:r}),m]});return jsx("section",{ref:u,className:b$1(y({spacing:n,background:c}),"px-6",e),...g,children:d?o:jsx(a,{size:l,padding:p,centered:true,children:o})})});S.displayName="Section";export{y as a,S as b};//# sourceMappingURL=chunk-Z74YUUVT.mjs.map
3
+ //# sourceMappingURL=chunk-Z74YUUVT.mjs.map