xertica-ui 2.6.0 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +20 -12
  3. package/bin/generate-tokens.ts +25 -9
  4. package/components/assistant/xertica-assistant/use-assistant.ts +5 -6
  5. package/components/assistant/xertica-assistant/xertica-assistant.tsx +1 -1
  6. package/{templates/src/features/auth/ui → components/blocks/auth}/AuthPageShell.tsx +8 -3
  7. package/components/blocks/auth/PasswordStrengthMeter.tsx +41 -0
  8. package/components/blocks/auth/SocialLoginButtons.tsx +95 -0
  9. package/components/blocks/auth/index.ts +11 -0
  10. package/components/blocks/auth/usePasswordStrength.ts +13 -0
  11. package/components/blocks/index.ts +1 -0
  12. package/components/pages/forgot-password-page/ForgotPasswordPage.tsx +45 -139
  13. package/components/pages/login-page/LoginPage.tsx +52 -145
  14. package/components/pages/reset-password-page/ResetPasswordPage.tsx +79 -169
  15. package/components/pages/verify-email-page/VerifyEmailPage.tsx +48 -150
  16. package/components/ui/button/button.test.tsx +2 -2
  17. package/components/ui/button/button.tsx +6 -6
  18. package/components/ui/card/card.tsx +14 -2
  19. package/components/ui/input/input.tsx +1 -1
  20. package/components/ui/input-otp/input-otp.tsx +1 -1
  21. package/components/ui/search/search.tsx +1 -1
  22. package/components/ui/select/select.tsx +2 -2
  23. package/components/ui/switch/switch.tsx +1 -1
  24. package/components/ui/textarea/textarea.tsx +1 -1
  25. package/contexts/BrandColorsContext.tsx +50 -2
  26. package/contexts/theme-data.ts +100 -3
  27. package/dist/AssistantChart-BFBJXVcm.js +3383 -0
  28. package/dist/AssistantChart-BTnE94FR.cjs +3551 -0
  29. package/dist/AssistantChart-BvccsQMx.cjs +3551 -0
  30. package/dist/AssistantChart-CImCNLfD.cjs +3551 -0
  31. package/dist/AssistantChart-CkskcBVD.js +3383 -0
  32. package/dist/AssistantChart-CrPkO9ip.js +3383 -0
  33. package/dist/AssistantChart-DKz2O1R8.cjs +3551 -0
  34. package/dist/AssistantChart-DYL6UEvo.cjs +3551 -0
  35. package/dist/AssistantChart-DfdIfmQr.js +3383 -0
  36. package/dist/AssistantChart-keo-ogKi.js +3383 -0
  37. package/dist/AudioPlayer-AoU5MTiM.cjs +1282 -0
  38. package/dist/AudioPlayer-Bx1vrblm.js +1278 -0
  39. package/dist/AudioPlayer-D0-I6J3J.cjs +1282 -0
  40. package/dist/AudioPlayer-DIWX_Yg7.cjs +1282 -0
  41. package/dist/AudioPlayer-DrWJnS7c.js +1278 -0
  42. package/dist/AudioPlayer-_P-Z7pAK.js +1278 -0
  43. package/dist/BrandColorsContext-B25Bpr3b.cjs +819 -0
  44. package/dist/BrandColorsContext-BCieATdW.js +812 -0
  45. package/dist/BrandColorsContext-DP0DXAXS.js +824 -0
  46. package/dist/BrandColorsContext-DjpC9wR_.cjs +798 -0
  47. package/dist/BrandColorsContext-MpXFhte7.cjs +831 -0
  48. package/dist/BrandColorsContext-V3tOc-Zw.js +791 -0
  49. package/dist/CodeBlock-CK4rO6lM.js +221 -0
  50. package/dist/CodeBlock-CKXamfVd.cjs +223 -0
  51. package/dist/CodeBlock-CVmE7isS.cjs +223 -0
  52. package/dist/CodeBlock-D7i5-cMv.js +221 -0
  53. package/dist/CodeBlock-Dg56j2ut.cjs +223 -0
  54. package/dist/CodeBlock-Dt6nUQoo.js +221 -0
  55. package/dist/CustomTooltipContent-Bxynuq7T.js +33 -0
  56. package/dist/CustomTooltipContent-BzjOSA0P.cjs +54 -0
  57. package/dist/CustomTooltipContent-C-ZeCNsf.js +33 -0
  58. package/dist/CustomTooltipContent-CON_QrXm.cjs +54 -0
  59. package/dist/CustomTooltipContent-UR_n2QfW.js +33 -0
  60. package/dist/CustomTooltipContent-v1SXjoFn.cjs +54 -0
  61. package/dist/FeatureCard-4n_8a63v.cjs +497 -0
  62. package/dist/FeatureCard-BLiAWT3w.js +485 -0
  63. package/dist/FeatureCard-BXRW97Ef.cjs +497 -0
  64. package/dist/FeatureCard-BhpfmPPx.js +485 -0
  65. package/dist/FeatureCard-CDgLlWE2.js +485 -0
  66. package/dist/FeatureCard-CgQ8lq-I.cjs +497 -0
  67. package/dist/FeatureCard-Cp8cVC6T.cjs +497 -0
  68. package/dist/FeatureCard-D-5yS_OD.cjs +497 -0
  69. package/dist/FeatureCard-D0MwrTRP.js +485 -0
  70. package/dist/FeatureCard-uE5i0in_.js +485 -0
  71. package/dist/ImageWithFallback-BOh1FM3I.js +98 -0
  72. package/dist/ImageWithFallback-BQO7952C.js +98 -0
  73. package/dist/ImageWithFallback-BkMXHCvV.cjs +122 -0
  74. package/dist/ImageWithFallback-C72nwszA.cjs +122 -0
  75. package/dist/ImageWithFallback-CCUMDuEC.cjs +122 -0
  76. package/dist/ImageWithFallback-CfkAkctC.cjs +122 -0
  77. package/dist/ImageWithFallback-DQD5TTlY.js +98 -0
  78. package/dist/ImageWithFallback-bw-CxxDc.js +98 -0
  79. package/dist/LanguageContext-CX_zdxre.js +1912 -0
  80. package/dist/LanguageContext-CjhSSqJT.cjs +1917 -0
  81. package/dist/LanguageSelector-1XhM7R1i.cjs +48 -0
  82. package/dist/LanguageSelector-B3ZVNc55.js +46 -0
  83. package/dist/LanguageSelector-BR3Ss0k_.js +46 -0
  84. package/dist/LanguageSelector-CHOLPmHr.cjs +48 -0
  85. package/dist/LanguageSelector-Cj6zl0CM.js +46 -0
  86. package/dist/LanguageSelector-DK1zD4VH.cjs +48 -0
  87. package/dist/LanguageSelector-DseCAa0p.cjs +48 -0
  88. package/dist/LanguageSelector-Du09anfM.js +46 -0
  89. package/dist/LanguageSelector-PZHlFfEs.cjs +48 -0
  90. package/dist/LanguageSelector-SB-NJSmx.js +46 -0
  91. package/dist/PasswordStrengthMeter-B3S6i_k4.cjs +179 -0
  92. package/dist/PasswordStrengthMeter-B8ky1nJI.js +173 -0
  93. package/dist/PasswordStrengthMeter-C5VEopH-.cjs +179 -0
  94. package/dist/PasswordStrengthMeter-C8irs0G1.js +173 -0
  95. package/dist/PasswordStrengthMeter-CIm7_jNT.js +173 -0
  96. package/dist/PasswordStrengthMeter-DKSAbQzu.js +173 -0
  97. package/dist/PasswordStrengthMeter-DxLu54p-.cjs +179 -0
  98. package/dist/PasswordStrengthMeter-MLzhax-d.cjs +179 -0
  99. package/dist/PasswordStrengthMeter-k-e9Pole.cjs +179 -0
  100. package/dist/PasswordStrengthMeter-pAi2viq5.js +173 -0
  101. package/dist/ThemeContext-CEY9pCn-.cjs +86 -0
  102. package/dist/ThemeContext-Dk3tH7Ym.js +83 -0
  103. package/dist/ThemeToggle-4pQbVkpK.js +215 -0
  104. package/dist/ThemeToggle-B6rIVLvC.cjs +219 -0
  105. package/dist/ThemeToggle-BUOTps5l.cjs +219 -0
  106. package/dist/ThemeToggle-BpM_iHh8.js +215 -0
  107. package/dist/ThemeToggle-CO5mPl6e.js +215 -0
  108. package/dist/ThemeToggle-CZRlv0d4.cjs +219 -0
  109. package/dist/ThemeToggle-DbZQ0JSV.cjs +219 -0
  110. package/dist/ThemeToggle-vLXEq2TS.js +215 -0
  111. package/dist/VerifyEmailPage-BKiaw2YK.js +2954 -0
  112. package/dist/VerifyEmailPage-BTjI2c9n.js +2954 -0
  113. package/dist/VerifyEmailPage-Beaicc6V.cjs +2963 -0
  114. package/dist/VerifyEmailPage-BehPBp0F.cjs +2963 -0
  115. package/dist/VerifyEmailPage-CJGfDSOx.js +2954 -0
  116. package/dist/VerifyEmailPage-DOlZUNc0.cjs +2963 -0
  117. package/dist/VerifyEmailPage-DQPRl_RJ.js +2954 -0
  118. package/dist/VerifyEmailPage-Djb6hthM.js +2954 -0
  119. package/dist/VerifyEmailPage-DrdqMbLC.cjs +2963 -0
  120. package/dist/VerifyEmailPage-hyDfeCRa.cjs +2963 -0
  121. package/dist/VerifyEmailPage-kKSXl8vu.cjs +2963 -0
  122. package/dist/VerifyEmailPage-w4N-bDhU.js +2954 -0
  123. package/dist/XerticaOrbe-B9tegV1n.js +1925 -0
  124. package/dist/XerticaOrbe-BQ_NjwPS.cjs +1927 -0
  125. package/dist/XerticaOrbe-BdUX171Q.cjs +1927 -0
  126. package/dist/XerticaOrbe-BdlKXRHU.cjs +1927 -0
  127. package/dist/XerticaOrbe-CByPAFE5.js +1925 -0
  128. package/dist/XerticaOrbe-Ccu9eFMu.js +1925 -0
  129. package/dist/XerticaProvider-BVid1oqn.cjs +46 -0
  130. package/dist/XerticaProvider-BijpC_py.cjs +46 -0
  131. package/dist/XerticaProvider-Bz_YfNY4.js +44 -0
  132. package/dist/XerticaProvider-C2wDRQhT.js +44 -0
  133. package/dist/XerticaProvider-CtvYfRbZ.cjs +46 -0
  134. package/dist/XerticaProvider-DMiyExQS.js +44 -0
  135. package/dist/XerticaProvider-DP2lzKip.cjs +46 -0
  136. package/dist/XerticaProvider-De79hhgp.js +44 -0
  137. package/dist/XerticaProvider-Dkk1Vbsy.js +44 -0
  138. package/dist/XerticaProvider-EdzH9Nrw.cjs +46 -0
  139. package/dist/alert-dialog-9XYAn5z5.js +819 -0
  140. package/dist/alert-dialog-B281hud0.cjs +872 -0
  141. package/dist/alert-dialog-BVWbrcrw.cjs +872 -0
  142. package/dist/alert-dialog-B_Ko1xpu.js +819 -0
  143. package/dist/alert-dialog-BzIcTKn_.cjs +872 -0
  144. package/dist/alert-dialog-CIxE8T-J.cjs +872 -0
  145. package/dist/alert-dialog-DW-_iPuf.js +819 -0
  146. package/dist/alert-dialog-kty5pxQp.js +819 -0
  147. package/dist/assistant.cjs.js +2 -2
  148. package/dist/assistant.es.js +2 -2
  149. package/dist/avatar-BJwIMbZ_.js +54 -0
  150. package/dist/avatar-C4Zh5fAJ.cjs +77 -0
  151. package/dist/avatar-CTEUKZUT.js +54 -0
  152. package/dist/avatar-D1bZhlhL.cjs +77 -0
  153. package/dist/avatar-DKIxHeKG.cjs +77 -0
  154. package/dist/avatar-v16eZC8p.js +54 -0
  155. package/dist/blocks.cjs.js +7 -3
  156. package/dist/blocks.es.js +2 -2
  157. package/dist/brand.cjs.js +8 -7
  158. package/dist/brand.es.js +4 -3
  159. package/dist/breadcrumb-B1mUiaWB.cjs +98 -0
  160. package/dist/breadcrumb-BIRgmem-.js +90 -0
  161. package/dist/breadcrumb-BSng-oUf.cjs +98 -0
  162. package/dist/breadcrumb-CES7furU.js +90 -0
  163. package/dist/breadcrumb-CP275kbF.cjs +98 -0
  164. package/dist/breadcrumb-D7hr1EvJ.js +90 -0
  165. package/dist/button-BYtQygX5.cjs +85 -0
  166. package/dist/button-BnAW-a_w.js +62 -0
  167. package/dist/button-CUPDQews.js +62 -0
  168. package/dist/button-DFa-rtPy.js +62 -0
  169. package/dist/button-DV1G6XrI.cjs +85 -0
  170. package/dist/button-Kd9Fj53S.cjs +85 -0
  171. package/dist/cli.js +94 -10
  172. package/dist/components/blocks/auth/AuthPageShell.d.ts +12 -0
  173. package/dist/components/blocks/auth/PasswordStrengthMeter.d.ts +7 -0
  174. package/dist/components/blocks/auth/SocialLoginButtons.d.ts +8 -0
  175. package/dist/components/blocks/auth/index.d.ts +8 -0
  176. package/dist/components/blocks/auth/usePasswordStrength.d.ts +3 -0
  177. package/dist/components/blocks/index.d.ts +1 -0
  178. package/dist/components/pages/reset-password-page/ResetPasswordPage.d.ts +1 -1
  179. package/dist/components/ui/card/card.d.ts +11 -1
  180. package/dist/contexts/theme-data.d.ts +15 -1
  181. package/dist/dropdown-menu-B9wTZ0uX.cjs +225 -0
  182. package/dist/dropdown-menu-BeBtZOrs.cjs +225 -0
  183. package/dist/dropdown-menu-D7mRDGis.js +190 -0
  184. package/dist/dropdown-menu-D8ZmqHB7.js +190 -0
  185. package/dist/dropdown-menu-_AWBeOts.cjs +225 -0
  186. package/dist/dropdown-menu-qGzLO_HO.js +190 -0
  187. package/dist/hooks.cjs.js +6 -5
  188. package/dist/hooks.es.js +3 -2
  189. package/dist/index.cjs.js +42 -37
  190. package/dist/index.es.js +25 -24
  191. package/dist/input-B53E6K8G.js +65 -0
  192. package/dist/input-B7Q7vcoG.cjs +91 -0
  193. package/dist/input-BysqLMK1.js +65 -0
  194. package/dist/input-CStdFsaH.cjs +91 -0
  195. package/dist/input-CXYth6nW.cjs +91 -0
  196. package/dist/input-CX_fWE2D.cjs +91 -0
  197. package/dist/input-CitUVnEn.js +65 -0
  198. package/dist/input-wkBYTp-B.js +65 -0
  199. package/dist/layout.cjs.js +1 -1
  200. package/dist/layout.es.js +1 -1
  201. package/dist/media.cjs.js +1 -1
  202. package/dist/media.es.js +1 -1
  203. package/dist/pages.cjs.js +1 -1
  204. package/dist/pages.es.js +1 -1
  205. package/dist/rich-text-editor-BHiRUzWZ.js +2894 -0
  206. package/dist/rich-text-editor-BWMRUMJ2.js +2894 -0
  207. package/dist/rich-text-editor-BoE6Ks5x.cjs +2968 -0
  208. package/dist/rich-text-editor-BzuEwR_X.js +2894 -0
  209. package/dist/rich-text-editor-CcopGbQ-.js +2894 -0
  210. package/dist/rich-text-editor-CmxSRJIi.cjs +2968 -0
  211. package/dist/rich-text-editor-DyYAu28v.cjs +2968 -0
  212. package/dist/rich-text-editor-JS_eMQCC.cjs +2968 -0
  213. package/dist/select-BNfFJwYp.js +130 -0
  214. package/dist/select-CN8IDjGB.js +130 -0
  215. package/dist/select-CwRzQHA7.cjs +161 -0
  216. package/dist/select-CwgD3nMD.js +130 -0
  217. package/dist/select-DEHUm_AC.cjs +161 -0
  218. package/dist/select-DJDgpVm3.cjs +161 -0
  219. package/dist/select-DSLWQLmo.cjs +161 -0
  220. package/dist/select-YFx0wCYT.js +130 -0
  221. package/dist/sidebar-B7YzwAp3.js +1151 -0
  222. package/dist/sidebar-BF7JEL7U.js +1151 -0
  223. package/dist/sidebar-Bjr2doX5.cjs +1154 -0
  224. package/dist/sidebar-CMrNCmhb.cjs +1154 -0
  225. package/dist/sidebar-CO9x8AVn.cjs +1154 -0
  226. package/dist/sidebar-Cb0U7NsV.cjs +1154 -0
  227. package/dist/sidebar-Cn_KB4c6.js +1151 -0
  228. package/dist/sidebar-Db_C30ph.cjs +1154 -0
  229. package/dist/sidebar-miPHsRz4.js +1151 -0
  230. package/dist/sidebar-pZF8mLLu.js +1151 -0
  231. package/dist/skeleton-BX2XTjMO.cjs +87 -0
  232. package/dist/skeleton-BoLK0iV7.js +78 -0
  233. package/dist/skeleton-Bysq8yeB.js +79 -0
  234. package/dist/skeleton-C7nspYnC.cjs +87 -0
  235. package/dist/skeleton-DL4V5Vub.cjs +87 -0
  236. package/dist/skeleton-DSMhdqp1.js +78 -0
  237. package/dist/skeleton-DhJswvTW.cjs +88 -0
  238. package/dist/skeleton-DicUfozA.js +78 -0
  239. package/dist/slider-77T_Eqw4.js +56 -0
  240. package/dist/slider-B6puMLXS.cjs +78 -0
  241. package/dist/slider-B785N7lZ.js +56 -0
  242. package/dist/slider-C6yssKyZ.cjs +78 -0
  243. package/dist/slider-CKZO9gVh.cjs +78 -0
  244. package/dist/slider-Cn-ImSze.js +56 -0
  245. package/dist/tooltip-BiJVGob3.cjs +72 -0
  246. package/dist/tooltip-D2OPn-1v.cjs +72 -0
  247. package/dist/tooltip-DlCHQuh1.js +48 -0
  248. package/dist/tooltip-fQ2Va0G8.cjs +72 -0
  249. package/dist/tooltip-oAw00FX2.js +48 -0
  250. package/dist/tooltip-u147L0wD.js +48 -0
  251. package/dist/ui.cjs.js +17 -17
  252. package/dist/ui.es.js +13 -13
  253. package/dist/xertica-assistant-8fh8KA2K.js +2173 -0
  254. package/dist/xertica-assistant-BjfG3zyL.cjs +2180 -0
  255. package/dist/xertica-assistant-C2A0R94j.js +2173 -0
  256. package/dist/xertica-assistant-CSUprvTR.js +2173 -0
  257. package/dist/xertica-assistant-Caubm0HR.js +2173 -0
  258. package/dist/xertica-assistant-DEexPM2u.cjs +2180 -0
  259. package/dist/xertica-assistant-Dh1dmEx3.cjs +2180 -0
  260. package/dist/xertica-assistant-GGcyHEZG.cjs +2180 -0
  261. package/dist/xertica-assistant-USefPe2L.js +2173 -0
  262. package/dist/xertica-assistant-cwSHFwfv.cjs +2180 -0
  263. package/dist/xertica-ui.css +1 -1
  264. package/docs/i18n.md +2 -0
  265. package/package.json +3 -2
  266. package/styles/xertica/base.css +38 -0
  267. package/styles/xertica/tokens.css +9 -0
  268. package/templates/package.json +2 -2
  269. package/templates/src/app/App.tsx +5 -1
  270. package/templates/src/features/auth/ui/ForgotPasswordContent.tsx +1 -2
  271. package/templates/src/features/auth/ui/LoginContent.tsx +1 -2
  272. package/templates/src/features/auth/ui/ResetPasswordContent.tsx +3 -57
  273. package/templates/src/features/auth/ui/VerifyEmailContent.tsx +1 -2
  274. package/templates/src/features/home/index.ts +0 -10
  275. package/templates/src/features/home/ui/HomeContent.tsx +19 -74
  276. package/templates/src/features/template/index.ts +0 -4
  277. package/templates/src/features/template/ui/TemplateContent.tsx +397 -1107
  278. package/templates/src/locales/en/pages/templates.json +70 -270
  279. package/templates/src/locales/es/pages/templates.json +77 -277
  280. package/templates/src/locales/pt-BR/pages/templates.json +77 -277
  281. package/templates/src/styles/xertica/tokens.css +9 -0
  282. package/templates/vite.config.ts +25 -0
  283. package/templates/src/features/auth/ui/SocialLoginButtons.tsx +0 -78
  284. package/templates/src/features/home/data/mock.ts +0 -41
  285. package/templates/src/features/home/hooks/useFeatureCards.ts +0 -20
  286. package/templates/src/features/home/store/dashboardStore.ts +0 -25
  287. package/templates/src/features/template/ui/CrudTemplate.tsx +0 -112
  288. package/templates/src/features/template/ui/DashboardTemplate.tsx +0 -110
  289. package/templates/src/features/template/ui/FormTemplate.tsx +0 -117
  290. package/templates/src/features/template/ui/LoginTemplate.tsx +0 -59
  291. package/templates/src/locales/en/pages/crudTemplate.json +0 -25
  292. package/templates/src/locales/en/pages/dashboardTemplate.json +0 -20
  293. package/templates/src/locales/en/pages/formTemplate.json +0 -16
  294. package/templates/src/locales/en/pages/loginTemplate.json +0 -9
  295. package/templates/src/locales/es/pages/crudTemplate.json +0 -25
  296. package/templates/src/locales/es/pages/dashboardTemplate.json +0 -20
  297. package/templates/src/locales/es/pages/formTemplate.json +0 -16
  298. package/templates/src/locales/es/pages/loginTemplate.json +0 -9
  299. package/templates/src/locales/pt-BR/pages/crudTemplate.json +0 -25
  300. package/templates/src/locales/pt-BR/pages/dashboardTemplate.json +0 -20
  301. package/templates/src/locales/pt-BR/pages/formTemplate.json +0 -16
  302. package/templates/src/locales/pt-BR/pages/loginTemplate.json +0 -9
  303. package/templates/vite.config.d.ts +0 -2
  304. package/templates/vite.config.js +0 -20
@@ -0,0 +1,2968 @@
1
+ 'use strict';
2
+
3
+ const jsxRuntime = require('react/jsx-runtime');
4
+ const ScrollAreaPrimitive = require('@radix-ui/react-scroll-area');
5
+ const button = require('./button-Kd9Fj53S.cjs');
6
+ const React = require('react');
7
+ const RechartsPrimitive = require('recharts');
8
+ const classVarianceAuthority = require('class-variance-authority');
9
+ const lucideReact = require('lucide-react');
10
+ const skeleton = require('./skeleton-C7nspYnC.cjs');
11
+ const select = require('./select-DEHUm_AC.cjs');
12
+ const DialogPrimitive = require('@radix-ui/react-dialog');
13
+ const dropdownMenu = require('./dropdown-menu-BeBtZOrs.cjs');
14
+ const input = require('./input-CXYth6nW.cjs');
15
+
16
+ function _interopNamespaceDefault(e) {
17
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
18
+ if (e) {
19
+ for (const k in e) {
20
+ if (k !== 'default') {
21
+ const d = Object.getOwnPropertyDescriptor(e, k);
22
+ Object.defineProperty(n, k, d.get ? d : {
23
+ enumerable: true,
24
+ get: () => e[k]
25
+ });
26
+ }
27
+ }
28
+ }
29
+ n.default = e;
30
+ return Object.freeze(n);
31
+ }
32
+
33
+ const ScrollAreaPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(ScrollAreaPrimitive);
34
+ const React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
35
+ const RechartsPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(RechartsPrimitive);
36
+ const DialogPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(DialogPrimitive);
37
+
38
+ function ScrollArea({
39
+ className,
40
+ children,
41
+ ...props
42
+ }) {
43
+ return /* @__PURE__ */ jsxRuntime.jsxs(
44
+ ScrollAreaPrimitive__namespace.Root,
45
+ {
46
+ "data-slot": "scroll-area",
47
+ className: button.cn("relative", className),
48
+ ...props,
49
+ children: [
50
+ /* @__PURE__ */ jsxRuntime.jsx(
51
+ ScrollAreaPrimitive__namespace.Viewport,
52
+ {
53
+ "data-slot": "scroll-area-viewport",
54
+ tabIndex: 0,
55
+ role: "region",
56
+ "aria-label": "Região rolável",
57
+ className: "focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1",
58
+ children
59
+ }
60
+ ),
61
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollBar, {}),
62
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollAreaPrimitive__namespace.Corner, {})
63
+ ]
64
+ }
65
+ );
66
+ }
67
+ function ScrollBar({
68
+ className,
69
+ orientation = "vertical",
70
+ ...props
71
+ }) {
72
+ return /* @__PURE__ */ jsxRuntime.jsx(
73
+ ScrollAreaPrimitive__namespace.ScrollAreaScrollbar,
74
+ {
75
+ "data-slot": "scroll-area-scrollbar",
76
+ orientation,
77
+ className: button.cn(
78
+ "flex touch-none p-px transition-colors select-none",
79
+ orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent",
80
+ orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent",
81
+ className
82
+ ),
83
+ ...props,
84
+ children: /* @__PURE__ */ jsxRuntime.jsx(
85
+ ScrollAreaPrimitive__namespace.ScrollAreaThumb,
86
+ {
87
+ "data-slot": "scroll-area-thumb",
88
+ className: "bg-border relative flex-1 rounded-full"
89
+ }
90
+ )
91
+ }
92
+ );
93
+ }
94
+
95
+ const alertVariants = classVarianceAuthority.cva(
96
+ "relative w-full rounded-[var(--radius)] border-l-4 px-4 py-3 grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-5 [&>svg]:translate-y-0.5 [&>svg]:text-current",
97
+ {
98
+ variants: {
99
+ variant: {
100
+ default: "bg-muted/50 border-l-border text-foreground [&>svg]:text-muted-foreground",
101
+ success: "bg-[color:var(--success)]/10 dark:bg-[color:var(--success)]/20 border-l-[color:var(--success)] text-foreground [&>svg]:text-[color:var(--success)]",
102
+ info: "bg-[color:var(--info)]/10 dark:bg-[color:var(--info)]/20 border-l-[color:var(--info)] text-foreground [&>svg]:text-[color:var(--info)]",
103
+ warning: "bg-[color:var(--warning)]/10 dark:bg-[color:var(--warning)]/20 border-l-[color:var(--warning)] text-foreground [&>svg]:text-[color:var(--warning)]",
104
+ destructive: "bg-[color:var(--destructive)]/10 dark:bg-[color:var(--destructive)]/20 border-l-[color:var(--destructive)] text-foreground [&>svg]:text-[color:var(--destructive)]"
105
+ }
106
+ },
107
+ defaultVariants: {
108
+ variant: "default"
109
+ }
110
+ }
111
+ );
112
+ const alertIcons = {
113
+ default: lucideReact.Info,
114
+ success: lucideReact.CheckCircle,
115
+ info: lucideReact.Info,
116
+ warning: lucideReact.AlertTriangle,
117
+ destructive: lucideReact.XCircle
118
+ };
119
+ function Alert({ className, variant, icon, children, ...props }) {
120
+ const alertVariant = variant && variant in alertIcons ? variant : "default";
121
+ const DefaultIcon = alertIcons[alertVariant];
122
+ return /* @__PURE__ */ jsxRuntime.jsxs(
123
+ "div",
124
+ {
125
+ "data-slot": "alert",
126
+ role: "alert",
127
+ className: button.cn(alertVariants({ variant }), className),
128
+ ...props,
129
+ children: [
130
+ icon !== void 0 ? icon : /* @__PURE__ */ jsxRuntime.jsx(DefaultIcon, { className: "flex-shrink-0" }),
131
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children })
132
+ ]
133
+ }
134
+ );
135
+ }
136
+ function AlertTitle({ className, ...props }) {
137
+ return /* @__PURE__ */ jsxRuntime.jsx(
138
+ "div",
139
+ {
140
+ "data-slot": "alert-title",
141
+ className: button.cn("font-medium mb-1 leading-tight", className),
142
+ ...props
143
+ }
144
+ );
145
+ }
146
+ function AlertDescription({ className, ...props }) {
147
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "alert-description", className: button.cn("leading-relaxed", className), ...props });
148
+ }
149
+
150
+ const Empty = React__namespace.forwardRef(
151
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
152
+ "div",
153
+ {
154
+ ref,
155
+ className: button.cn(
156
+ "flex min-h-[400px] flex-col items-center justify-center rounded-[var(--radius-card)] border border-dashed border-border p-8 text-center animate-in fade-in-50",
157
+ className
158
+ ),
159
+ ...props
160
+ }
161
+ )
162
+ );
163
+ Empty.displayName = "Empty";
164
+ const EmptyIcon = React__namespace.forwardRef(
165
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
166
+ "div",
167
+ {
168
+ ref,
169
+ className: button.cn(
170
+ "mx-auto flex h-20 w-20 items-center justify-center rounded-full bg-muted",
171
+ className
172
+ ),
173
+ ...props
174
+ }
175
+ )
176
+ );
177
+ EmptyIcon.displayName = "EmptyIcon";
178
+ const EmptyImage = React__namespace.forwardRef(
179
+ ({ className, alt, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
180
+ "img",
181
+ {
182
+ ref,
183
+ alt,
184
+ className: button.cn("mx-auto mb-4 h-48 w-48 object-contain opacity-50", className),
185
+ ...props
186
+ }
187
+ )
188
+ );
189
+ EmptyImage.displayName = "EmptyImage";
190
+ const EmptyTitle = React__namespace.forwardRef(
191
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("h3", { ref, className: button.cn("mt-4 font-semibold text-foreground", className), ...props })
192
+ );
193
+ EmptyTitle.displayName = "EmptyTitle";
194
+ const EmptyDescription = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
195
+ "p",
196
+ {
197
+ ref,
198
+ className: button.cn("mt-2 text-sm text-muted-foreground max-w-sm mx-auto", className),
199
+ ...props
200
+ }
201
+ ));
202
+ EmptyDescription.displayName = "EmptyDescription";
203
+ const EmptyAction = React__namespace.forwardRef(
204
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
205
+ "div",
206
+ {
207
+ ref,
208
+ className: button.cn("mt-6 flex flex-col gap-2 sm:flex-row sm:gap-4", className),
209
+ ...props
210
+ }
211
+ )
212
+ );
213
+ EmptyAction.displayName = "EmptyAction";
214
+
215
+ const THEMES = { light: "", dark: ".dark" };
216
+ const defaultPeriods = [
217
+ { value: "7d", label: "7 days" },
218
+ { value: "30d", label: "30 days" },
219
+ { value: "90d", label: "90 days" }
220
+ ];
221
+ const defaultChartColors = [
222
+ "var(--chart-1)",
223
+ "var(--chart-2)",
224
+ "var(--chart-3)",
225
+ "var(--chart-4)",
226
+ "var(--chart-5)",
227
+ "var(--chart-6)",
228
+ "var(--chart-7)",
229
+ "var(--chart-8)"
230
+ ];
231
+ const chartBarSizes = {
232
+ sm: 8,
233
+ md: 14,
234
+ lg: 22,
235
+ xl: 32
236
+ };
237
+ const ChartContext = React__namespace.createContext(null);
238
+ function useChart() {
239
+ const context = React__namespace.useContext(ChartContext);
240
+ if (!context) {
241
+ throw new Error("useChart must be used within a <ChartContainer />");
242
+ }
243
+ return context;
244
+ }
245
+ function ChartContainer({
246
+ id,
247
+ className,
248
+ children,
249
+ config,
250
+ ...props
251
+ }) {
252
+ const uniqueId = React__namespace.useId();
253
+ const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
254
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartContext.Provider, { value: { config }, children: /* @__PURE__ */ jsxRuntime.jsxs(
255
+ "div",
256
+ {
257
+ "data-slot": "chart",
258
+ "data-chart": chartId,
259
+ className: button.cn(
260
+ "[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border relative h-[300px] min-h-[200px] w-full min-w-0 overflow-hidden text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden",
261
+ className
262
+ ),
263
+ ...props,
264
+ children: [
265
+ /* @__PURE__ */ jsxRuntime.jsx(ChartStyle, { id: chartId, config }),
266
+ /* @__PURE__ */ jsxRuntime.jsx(RechartsPrimitive__namespace.ResponsiveContainer, { width: "100%", height: "100%", children })
267
+ ]
268
+ }
269
+ ) });
270
+ }
271
+ const SAFE_CSS_COLOR = /^(#[0-9a-fA-F]{3,8}|(rgb|rgba|hsl|hsla|var)\([^;{}<>]*\)|[a-zA-Z-]+)$/;
272
+ const ChartStyle = ({ id, config }) => {
273
+ const colorConfig = Object.entries(config).filter(([, config2]) => config2.theme || config2.color);
274
+ if (!colorConfig.length) {
275
+ return null;
276
+ }
277
+ return /* @__PURE__ */ jsxRuntime.jsx(
278
+ "style",
279
+ {
280
+ dangerouslySetInnerHTML: {
281
+ __html: Object.entries(THEMES).map(
282
+ ([theme, prefix]) => `
283
+ ${prefix} [data-chart=${id}] {
284
+ ${colorConfig.map(([key, itemConfig]) => {
285
+ const color = itemConfig.theme?.[theme] || itemConfig.color;
286
+ if (!color || !SAFE_CSS_COLOR.test(color.trim())) {
287
+ return null;
288
+ }
289
+ return ` --color-${key}: ${color};`;
290
+ }).join("\n")}
291
+ }
292
+ `
293
+ ).join("\n")
294
+ }
295
+ }
296
+ );
297
+ };
298
+ const ChartTooltip = RechartsPrimitive__namespace.Tooltip;
299
+ function ChartTooltipContent({
300
+ active,
301
+ payload,
302
+ className,
303
+ indicator = "dot",
304
+ hideLabel = false,
305
+ hideIndicator = false,
306
+ label,
307
+ labelFormatter,
308
+ labelClassName,
309
+ formatter,
310
+ color,
311
+ nameKey,
312
+ labelKey
313
+ }) {
314
+ const { config } = useChart();
315
+ const tooltipLabel = React__namespace.useMemo(() => {
316
+ if (hideLabel || !payload?.length) {
317
+ return null;
318
+ }
319
+ const [item] = payload;
320
+ const key = `${labelKey || item?.dataKey || item?.name || "value"}`;
321
+ const itemConfig = getPayloadConfigFromPayload(config, item, key);
322
+ const value = !labelKey && typeof label === "string" ? config[label]?.label || label : itemConfig?.label;
323
+ if (labelFormatter) {
324
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: button.cn("font-medium", labelClassName), children: labelFormatter(value, payload) });
325
+ }
326
+ if (!value) {
327
+ return null;
328
+ }
329
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: button.cn("font-medium", labelClassName), children: value });
330
+ }, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey]);
331
+ if (!active || !payload?.length) {
332
+ return null;
333
+ }
334
+ const nestLabel = payload.length === 1 && indicator !== "dot";
335
+ return /* @__PURE__ */ jsxRuntime.jsxs(
336
+ "div",
337
+ {
338
+ className: button.cn(
339
+ "border-border/50 bg-background/95 backdrop-blur-sm grid min-w-[8rem] items-start gap-1.5 rounded-xl border px-3 py-2 text-xs shadow-xl",
340
+ className
341
+ ),
342
+ children: [
343
+ !nestLabel ? tooltipLabel : null,
344
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-1.5", children: payload.map((item, index) => {
345
+ const key = `${nameKey || item.name || item.dataKey || "value"}`;
346
+ const itemConfig = getPayloadConfigFromPayload(config, item, key);
347
+ const indicatorColor = color || item.payload?.fill || item.color;
348
+ return /* @__PURE__ */ jsxRuntime.jsx(
349
+ "div",
350
+ {
351
+ className: button.cn(
352
+ "[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5",
353
+ indicator === "dot" && "items-center"
354
+ ),
355
+ children: formatter && item?.value !== void 0 && item.name ? formatter(item.value, item.name, item, index, item.payload) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
356
+ itemConfig?.icon ? /* @__PURE__ */ jsxRuntime.jsx(itemConfig.icon, {}) : !hideIndicator && /* @__PURE__ */ jsxRuntime.jsx(
357
+ "div",
358
+ {
359
+ className: button.cn(
360
+ "shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)",
361
+ {
362
+ "h-2.5 w-2.5": indicator === "dot",
363
+ "w-1": indicator === "line",
364
+ "w-0 border-[1.5px] border-dashed bg-transparent": indicator === "dashed",
365
+ "my-0.5": nestLabel && indicator === "dashed"
366
+ }
367
+ ),
368
+ style: {
369
+ "--color-bg": indicatorColor,
370
+ "--color-border": indicatorColor
371
+ }
372
+ }
373
+ ),
374
+ /* @__PURE__ */ jsxRuntime.jsxs(
375
+ "div",
376
+ {
377
+ className: button.cn(
378
+ "flex flex-1 justify-between leading-none",
379
+ nestLabel ? "items-end" : "items-center"
380
+ ),
381
+ children: [
382
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-1.5", children: [
383
+ nestLabel ? tooltipLabel : null,
384
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: itemConfig?.label || item.name })
385
+ ] }),
386
+ item.value && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground font-mono font-semibold tabular-nums", children: item.value.toLocaleString() })
387
+ ]
388
+ }
389
+ )
390
+ ] })
391
+ },
392
+ `${item.dataKey ?? index}`
393
+ );
394
+ }) })
395
+ ]
396
+ }
397
+ );
398
+ }
399
+ const ChartLegend = RechartsPrimitive__namespace.Legend;
400
+ function ChartLegendContent({
401
+ className,
402
+ hideIcon = false,
403
+ payload,
404
+ verticalAlign = "bottom",
405
+ nameKey
406
+ }) {
407
+ const { config } = useChart();
408
+ if (!payload?.length) {
409
+ return null;
410
+ }
411
+ return /* @__PURE__ */ jsxRuntime.jsx(
412
+ "div",
413
+ {
414
+ className: button.cn(
415
+ "flex items-center justify-center gap-4",
416
+ verticalAlign === "top" ? "pb-3" : "pt-3",
417
+ className
418
+ ),
419
+ children: payload.map((item) => {
420
+ const key = `${nameKey ? item.value : item.dataKey || item.value || "value"}`;
421
+ const itemConfig = getPayloadConfigFromPayload(config, item, key);
422
+ return /* @__PURE__ */ jsxRuntime.jsxs(
423
+ "div",
424
+ {
425
+ className: button.cn(
426
+ "[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3"
427
+ ),
428
+ children: [
429
+ itemConfig?.icon && !hideIcon ? /* @__PURE__ */ jsxRuntime.jsx(itemConfig.icon, {}) : /* @__PURE__ */ jsxRuntime.jsx(
430
+ "div",
431
+ {
432
+ className: "h-2 w-2 shrink-0 rounded-full bg-(--color-bg)",
433
+ style: {
434
+ "--color-bg": item.color || `var(--color-${key})`
435
+ }
436
+ }
437
+ ),
438
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-xs", children: itemConfig?.label || item.value })
439
+ ]
440
+ },
441
+ item.value
442
+ );
443
+ })
444
+ }
445
+ );
446
+ }
447
+ function getPayloadConfigFromPayload(config, payload, key) {
448
+ if (typeof payload !== "object" || payload === null) {
449
+ return void 0;
450
+ }
451
+ const payloadPayload = "payload" in payload && typeof payload.payload === "object" && payload.payload !== null ? payload.payload : void 0;
452
+ let configLabelKey = key;
453
+ if (key in payload && typeof payload[key] === "string") {
454
+ configLabelKey = payload[key];
455
+ } else if (payloadPayload && key in payloadPayload && typeof payloadPayload[key] === "string") {
456
+ configLabelKey = payloadPayload[key];
457
+ }
458
+ return configLabelKey in config ? config[configLabelKey] : config[key];
459
+ }
460
+ function getChartSeries(config, series) {
461
+ if (series?.length) {
462
+ return series;
463
+ }
464
+ return Object.entries(config).map(([key, item]) => ({
465
+ key,
466
+ label: item.label
467
+ }));
468
+ }
469
+ function getSeriesColor(key, index, colors) {
470
+ if (Array.isArray(colors)) {
471
+ return colors[index] || defaultChartColors[index % defaultChartColors.length];
472
+ }
473
+ return colors?.[key] || defaultChartColors[index % defaultChartColors.length];
474
+ }
475
+ function getChartConfigWithColors(config, keys, colors) {
476
+ return keys.reduce((nextConfig, key, index) => {
477
+ const item = config[key];
478
+ if (item?.theme && !colors) {
479
+ nextConfig[key] = item;
480
+ return nextConfig;
481
+ }
482
+ nextConfig[key] = {
483
+ label: item?.label || key,
484
+ icon: item?.icon,
485
+ color: colors ? getSeriesColor(key, index, colors) : item?.color || getSeriesColor(key, index)
486
+ };
487
+ return nextConfig;
488
+ }, {});
489
+ }
490
+ function buildChartConfig(keys, colors) {
491
+ return keys.reduce((cfg, key, index) => {
492
+ cfg[key] = {
493
+ label: key,
494
+ color: getSeriesColor(key, index, colors)
495
+ };
496
+ return cfg;
497
+ }, {});
498
+ }
499
+ function formatTick(value) {
500
+ if (typeof value !== "number") {
501
+ return value;
502
+ }
503
+ return Intl.NumberFormat("en", {
504
+ notation: "compact",
505
+ maximumFractionDigits: 1
506
+ }).format(value);
507
+ }
508
+ function defaultFilterData(data, period) {
509
+ const match = period.match(/^(\d+)/);
510
+ if (!match) {
511
+ return data;
512
+ }
513
+ const limit = Number(match[1]);
514
+ return data.slice(Math.max(data.length - limit, 0));
515
+ }
516
+ function getErrorDescription(error) {
517
+ if (typeof error === "string") {
518
+ return error;
519
+ }
520
+ if (error instanceof Error) {
521
+ return error.message;
522
+ }
523
+ return void 0;
524
+ }
525
+ function getBarSize(barSize = "md") {
526
+ return typeof barSize === "number" ? barSize : chartBarSizes[barSize];
527
+ }
528
+ function hasChartData(data, series) {
529
+ if (!data.length || !series.length) {
530
+ return false;
531
+ }
532
+ return data.some(
533
+ (item) => series.some((serie) => {
534
+ const value = item[serie.key];
535
+ return value !== null && value !== void 0 && value !== "";
536
+ })
537
+ );
538
+ }
539
+ function hasPieData(data, nameKey, valueKey) {
540
+ return data.some((item) => {
541
+ const name = item[nameKey];
542
+ const value = item[valueKey];
543
+ return name !== null && name !== void 0 && name !== "" && value !== null && value !== void 0 && value !== "";
544
+ });
545
+ }
546
+ function ChartState({
547
+ type,
548
+ className,
549
+ error,
550
+ onRetry,
551
+ retryLabel = "Try again",
552
+ emptyTitle = "No data available",
553
+ emptyDescription = "There is no data available for this chart yet.",
554
+ errorTitle = "Connection error",
555
+ errorDescription,
556
+ loadingLabel = "Loading chart data"
557
+ }) {
558
+ if (type === "loading") {
559
+ return /* @__PURE__ */ jsxRuntime.jsxs(
560
+ "div",
561
+ {
562
+ className: button.cn(
563
+ "flex min-h-[240px] flex-col justify-end gap-3 rounded-[var(--radius-card)] border border-border p-6",
564
+ className
565
+ ),
566
+ "aria-label": typeof loadingLabel === "string" ? loadingLabel : void 0,
567
+ children: [
568
+ /* @__PURE__ */ jsxRuntime.jsx(skeleton.Skeleton, { className: "h-8 w-2/5" }),
569
+ /* @__PURE__ */ jsxRuntime.jsx(skeleton.Skeleton, { className: "h-14 w-3/5" }),
570
+ /* @__PURE__ */ jsxRuntime.jsx(skeleton.Skeleton, { className: "h-24 w-4/5" }),
571
+ /* @__PURE__ */ jsxRuntime.jsx(skeleton.Skeleton, { className: "h-36 w-full" })
572
+ ]
573
+ }
574
+ );
575
+ }
576
+ if (type === "error") {
577
+ return /* @__PURE__ */ jsxRuntime.jsx(
578
+ "div",
579
+ {
580
+ className: button.cn(
581
+ "flex min-h-[240px] items-center justify-center rounded-[var(--radius-card)] border border-border p-6",
582
+ className
583
+ ),
584
+ children: /* @__PURE__ */ jsxRuntime.jsxs(Alert, { variant: "destructive", className: "max-w-xl", children: [
585
+ /* @__PURE__ */ jsxRuntime.jsx(AlertTitle, { children: errorTitle }),
586
+ /* @__PURE__ */ jsxRuntime.jsx(AlertDescription, { children: errorDescription || getErrorDescription(error) || "Unable to load chart data. Check your connection and try again." }),
587
+ onRetry ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsxRuntime.jsxs(button.Button, { size: "sm", variant: "outline", onClick: onRetry, children: [
588
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "size-4" }),
589
+ retryLabel
590
+ ] }) }) : null
591
+ ] })
592
+ }
593
+ );
594
+ }
595
+ return /* @__PURE__ */ jsxRuntime.jsxs(Empty, { className: button.cn("min-h-[240px]", className), children: [
596
+ /* @__PURE__ */ jsxRuntime.jsx(EmptyIcon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BarChart3, { className: "size-10 text-muted-foreground" }) }),
597
+ /* @__PURE__ */ jsxRuntime.jsx(EmptyTitle, { children: emptyTitle }),
598
+ /* @__PURE__ */ jsxRuntime.jsx(EmptyDescription, { children: emptyDescription }),
599
+ onRetry ? /* @__PURE__ */ jsxRuntime.jsx(EmptyAction, { children: /* @__PURE__ */ jsxRuntime.jsxs(button.Button, { size: "sm", variant: "outline", onClick: onRetry, children: [
600
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.WifiOff, { className: "size-4" }),
601
+ retryLabel
602
+ ] }) }) : null
603
+ ] });
604
+ }
605
+ function getChartState(state, hasData, className) {
606
+ if (state.isLoading) {
607
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartState, { ...state, type: "loading", className });
608
+ }
609
+ if (state.error) {
610
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartState, { ...state, type: "error", className });
611
+ }
612
+ if (!hasData) {
613
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartState, { ...state, type: "empty", className });
614
+ }
615
+ return null;
616
+ }
617
+ function ChartCard({
618
+ title,
619
+ description,
620
+ action,
621
+ footer,
622
+ children,
623
+ className,
624
+ contentClassName,
625
+ ...props
626
+ }) {
627
+ return /* @__PURE__ */ jsxRuntime.jsxs(skeleton.Card, { className: button.cn("w-full min-w-0 overflow-hidden", className), ...props, children: [
628
+ /* @__PURE__ */ jsxRuntime.jsxs(skeleton.CardHeader, { children: [
629
+ /* @__PURE__ */ jsxRuntime.jsx(skeleton.CardTitle, { children: title }),
630
+ description ? /* @__PURE__ */ jsxRuntime.jsx(skeleton.CardDescription, { children: description }) : null,
631
+ action ? /* @__PURE__ */ jsxRuntime.jsx(skeleton.CardAction, { children: action }) : null
632
+ ] }),
633
+ /* @__PURE__ */ jsxRuntime.jsx(skeleton.CardContent, { className: contentClassName, children }),
634
+ footer ? /* @__PURE__ */ jsxRuntime.jsx(skeleton.CardFooter, { children: footer }) : null
635
+ ] });
636
+ }
637
+ function AreaGradientDefs({
638
+ seriesKeys,
639
+ opacity = 0.3
640
+ }) {
641
+ return /* @__PURE__ */ jsxRuntime.jsx("defs", { children: seriesKeys.map((key) => /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: `gradient-${key}`, x1: "0", y1: "0", x2: "0", y2: "1", children: [
642
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "5%", stopColor: `var(--color-${key})`, stopOpacity: opacity }),
643
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "95%", stopColor: `var(--color-${key})`, stopOpacity: 0 })
644
+ ] }, key)) });
645
+ }
646
+ function DashboardBarChart({
647
+ data,
648
+ config,
649
+ indexKey = "name",
650
+ series,
651
+ colors,
652
+ barSize = "md",
653
+ stacked = false,
654
+ showGrid = true,
655
+ showLegend = true,
656
+ valueFormatter = formatTick,
657
+ isLoading,
658
+ error,
659
+ onRetry,
660
+ retryLabel,
661
+ emptyTitle,
662
+ emptyDescription,
663
+ errorTitle,
664
+ errorDescription,
665
+ loadingLabel,
666
+ stateClassName,
667
+ className,
668
+ ...props
669
+ }) {
670
+ const chartSeries = getChartSeries(config, series);
671
+ const chartConfig = getChartConfigWithColors(
672
+ config,
673
+ chartSeries.map((item) => item.key),
674
+ colors
675
+ );
676
+ const chartState = getChartState(
677
+ {
678
+ isLoading,
679
+ error,
680
+ onRetry,
681
+ retryLabel,
682
+ emptyTitle,
683
+ emptyDescription,
684
+ errorTitle,
685
+ errorDescription,
686
+ loadingLabel
687
+ },
688
+ hasChartData(data, chartSeries),
689
+ button.cn("h-[320px] w-full", stateClassName)
690
+ );
691
+ const barElements = React__namespace.useMemo(() => {
692
+ const topOfStack = /* @__PURE__ */ new Set();
693
+ if (stacked) {
694
+ const lastByStack = /* @__PURE__ */ new Map();
695
+ chartSeries.forEach((s) => lastByStack.set(s.stackId || "total", s.key));
696
+ lastByStack.forEach((key) => topOfStack.add(key));
697
+ }
698
+ return chartSeries.map((item) => {
699
+ const isTop = !stacked || topOfStack.has(item.key);
700
+ return /* @__PURE__ */ jsxRuntime.jsx(
701
+ RechartsPrimitive__namespace.Bar,
702
+ {
703
+ dataKey: item.key,
704
+ fill: `var(--color-${item.key})`,
705
+ radius: isTop ? [4, 4, 0, 0] : [0, 0, 0, 0],
706
+ barSize: getBarSize(barSize),
707
+ stackId: stacked ? item.stackId || "total" : item.stackId,
708
+ isAnimationActive: true,
709
+ animationDuration: 600,
710
+ animationEasing: "ease-out"
711
+ },
712
+ item.key
713
+ );
714
+ });
715
+ }, [stacked, chartSeries]);
716
+ if (chartState) {
717
+ return chartState;
718
+ }
719
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartContainer, { config: chartConfig, className: button.cn("h-[320px] w-full", className), ...props, children: /* @__PURE__ */ jsxRuntime.jsxs(RechartsPrimitive__namespace.BarChart, { data, accessibilityLayer: true, barGap: 4, children: [
720
+ showGrid ? /* @__PURE__ */ jsxRuntime.jsx(
721
+ RechartsPrimitive__namespace.CartesianGrid,
722
+ {
723
+ vertical: false,
724
+ strokeDasharray: "3 3",
725
+ stroke: "var(--border)",
726
+ strokeOpacity: 0.5
727
+ }
728
+ ) : null,
729
+ /* @__PURE__ */ jsxRuntime.jsx(
730
+ RechartsPrimitive__namespace.XAxis,
731
+ {
732
+ dataKey: indexKey,
733
+ tickLine: false,
734
+ axisLine: false,
735
+ tickMargin: 8
736
+ }
737
+ ),
738
+ /* @__PURE__ */ jsxRuntime.jsx(
739
+ RechartsPrimitive__namespace.YAxis,
740
+ {
741
+ tickLine: false,
742
+ axisLine: false,
743
+ tickMargin: 8,
744
+ tickFormatter: valueFormatter
745
+ }
746
+ ),
747
+ /* @__PURE__ */ jsxRuntime.jsx(
748
+ ChartTooltip,
749
+ {
750
+ cursor: { fill: "var(--muted)", opacity: 0.4, radius: 4 },
751
+ content: /* @__PURE__ */ jsxRuntime.jsx(ChartTooltipContent, {})
752
+ }
753
+ ),
754
+ showLegend ? /* @__PURE__ */ jsxRuntime.jsx(ChartLegend, { content: /* @__PURE__ */ jsxRuntime.jsx(ChartLegendContent, {}) }) : null,
755
+ barElements
756
+ ] }) });
757
+ }
758
+ function DashboardLineChart({
759
+ data,
760
+ config,
761
+ indexKey = "name",
762
+ series,
763
+ colors,
764
+ showDots = false,
765
+ showGrid = true,
766
+ showLegend = true,
767
+ curveType = "monotone",
768
+ strokeWidth = 2,
769
+ valueFormatter = formatTick,
770
+ isLoading,
771
+ error,
772
+ onRetry,
773
+ retryLabel,
774
+ emptyTitle,
775
+ emptyDescription,
776
+ errorTitle,
777
+ errorDescription,
778
+ loadingLabel,
779
+ stateClassName,
780
+ className,
781
+ ...props
782
+ }) {
783
+ const chartSeries = getChartSeries(config, series);
784
+ const chartConfig = getChartConfigWithColors(
785
+ config,
786
+ chartSeries.map((item) => item.key),
787
+ colors
788
+ );
789
+ const chartState = getChartState(
790
+ {
791
+ isLoading,
792
+ error,
793
+ onRetry,
794
+ retryLabel,
795
+ emptyTitle,
796
+ emptyDescription,
797
+ errorTitle,
798
+ errorDescription,
799
+ loadingLabel
800
+ },
801
+ hasChartData(data, chartSeries),
802
+ button.cn("h-[320px] w-full", stateClassName)
803
+ );
804
+ if (chartState) {
805
+ return chartState;
806
+ }
807
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartContainer, { config: chartConfig, className: button.cn("h-[320px] w-full", className), ...props, children: /* @__PURE__ */ jsxRuntime.jsxs(RechartsPrimitive__namespace.LineChart, { data, accessibilityLayer: true, children: [
808
+ showGrid ? /* @__PURE__ */ jsxRuntime.jsx(
809
+ RechartsPrimitive__namespace.CartesianGrid,
810
+ {
811
+ vertical: false,
812
+ strokeDasharray: "3 3",
813
+ stroke: "var(--border)",
814
+ strokeOpacity: 0.5
815
+ }
816
+ ) : null,
817
+ /* @__PURE__ */ jsxRuntime.jsx(
818
+ RechartsPrimitive__namespace.XAxis,
819
+ {
820
+ dataKey: indexKey,
821
+ tickLine: false,
822
+ axisLine: false,
823
+ tickMargin: 8
824
+ }
825
+ ),
826
+ /* @__PURE__ */ jsxRuntime.jsx(
827
+ RechartsPrimitive__namespace.YAxis,
828
+ {
829
+ tickLine: false,
830
+ axisLine: false,
831
+ tickMargin: 8,
832
+ tickFormatter: valueFormatter
833
+ }
834
+ ),
835
+ /* @__PURE__ */ jsxRuntime.jsx(ChartTooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(ChartTooltipContent, { indicator: "line" }) }),
836
+ showLegend ? /* @__PURE__ */ jsxRuntime.jsx(ChartLegend, { content: /* @__PURE__ */ jsxRuntime.jsx(ChartLegendContent, {}) }) : null,
837
+ chartSeries.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
838
+ RechartsPrimitive__namespace.Line,
839
+ {
840
+ type: curveType,
841
+ dataKey: item.key,
842
+ stroke: `var(--color-${item.key})`,
843
+ strokeWidth,
844
+ dot: showDots ? { r: 3, fill: `var(--color-${item.key})`, strokeWidth: 0 } : false,
845
+ activeDot: { r: 5, strokeWidth: 0 },
846
+ yAxisId: item.yAxisId,
847
+ isAnimationActive: true,
848
+ animationDuration: 600,
849
+ animationEasing: "ease-out"
850
+ },
851
+ item.key
852
+ ))
853
+ ] }) });
854
+ }
855
+ function HorizontalBarChart({
856
+ data,
857
+ config,
858
+ indexKey = "name",
859
+ series,
860
+ colors,
861
+ barSize = "md",
862
+ stacked = false,
863
+ categoryWidth = 96,
864
+ showGrid = true,
865
+ showLegend = true,
866
+ valueFormatter = formatTick,
867
+ isLoading,
868
+ error,
869
+ onRetry,
870
+ retryLabel,
871
+ emptyTitle,
872
+ emptyDescription,
873
+ errorTitle,
874
+ errorDescription,
875
+ loadingLabel,
876
+ stateClassName,
877
+ className,
878
+ ...props
879
+ }) {
880
+ const chartSeries = getChartSeries(config, series);
881
+ const chartConfig = getChartConfigWithColors(
882
+ config,
883
+ chartSeries.map((item) => item.key),
884
+ colors
885
+ );
886
+ const chartState = getChartState(
887
+ {
888
+ isLoading,
889
+ error,
890
+ onRetry,
891
+ retryLabel,
892
+ emptyTitle,
893
+ emptyDescription,
894
+ errorTitle,
895
+ errorDescription,
896
+ loadingLabel
897
+ },
898
+ hasChartData(data, chartSeries),
899
+ button.cn("h-[320px] w-full", stateClassName)
900
+ );
901
+ if (chartState) {
902
+ return chartState;
903
+ }
904
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartContainer, { config: chartConfig, className: button.cn("h-[320px] w-full", className), ...props, children: /* @__PURE__ */ jsxRuntime.jsxs(
905
+ RechartsPrimitive__namespace.BarChart,
906
+ {
907
+ data,
908
+ layout: "vertical",
909
+ accessibilityLayer: true,
910
+ margin: { left: 8, right: 16 },
911
+ children: [
912
+ showGrid ? /* @__PURE__ */ jsxRuntime.jsx(
913
+ RechartsPrimitive__namespace.CartesianGrid,
914
+ {
915
+ horizontal: false,
916
+ strokeDasharray: "3 3",
917
+ stroke: "var(--border)",
918
+ strokeOpacity: 0.5
919
+ }
920
+ ) : null,
921
+ /* @__PURE__ */ jsxRuntime.jsx(
922
+ RechartsPrimitive__namespace.XAxis,
923
+ {
924
+ type: "number",
925
+ tickLine: false,
926
+ axisLine: false,
927
+ tickMargin: 8,
928
+ tickFormatter: valueFormatter
929
+ }
930
+ ),
931
+ /* @__PURE__ */ jsxRuntime.jsx(
932
+ RechartsPrimitive__namespace.YAxis,
933
+ {
934
+ dataKey: indexKey,
935
+ type: "category",
936
+ tickLine: false,
937
+ axisLine: false,
938
+ tickMargin: 8,
939
+ width: categoryWidth
940
+ }
941
+ ),
942
+ /* @__PURE__ */ jsxRuntime.jsx(ChartTooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(ChartTooltipContent, {}) }),
943
+ showLegend ? /* @__PURE__ */ jsxRuntime.jsx(ChartLegend, { content: /* @__PURE__ */ jsxRuntime.jsx(ChartLegendContent, {}) }) : null,
944
+ chartSeries.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
945
+ RechartsPrimitive__namespace.Bar,
946
+ {
947
+ dataKey: item.key,
948
+ fill: `var(--color-${item.key})`,
949
+ radius: [0, 4, 4, 0],
950
+ barSize: getBarSize(barSize),
951
+ stackId: stacked ? item.stackId || "total" : item.stackId,
952
+ isAnimationActive: true,
953
+ animationDuration: 600,
954
+ animationEasing: "ease-out"
955
+ },
956
+ item.key
957
+ ))
958
+ ]
959
+ }
960
+ ) });
961
+ }
962
+ function InteractiveTimeSeriesChart({
963
+ data,
964
+ config,
965
+ indexKey = "date",
966
+ series,
967
+ colors,
968
+ periods = defaultPeriods,
969
+ defaultPeriod = periods[1]?.value || periods[0]?.value || "30d",
970
+ defaultSeries,
971
+ filterData = defaultFilterData,
972
+ showGrid = true,
973
+ showLegend = false,
974
+ showDots = false,
975
+ gradientFill = true,
976
+ curveType = "monotone",
977
+ strokeWidth = 2,
978
+ valueFormatter = formatTick,
979
+ isLoading,
980
+ error,
981
+ onRetry,
982
+ retryLabel,
983
+ emptyTitle,
984
+ emptyDescription,
985
+ errorTitle,
986
+ errorDescription,
987
+ loadingLabel,
988
+ stateClassName,
989
+ className,
990
+ ...props
991
+ }) {
992
+ const chartSeries = getChartSeries(config, series);
993
+ const chartConfig = getChartConfigWithColors(
994
+ config,
995
+ chartSeries.map((item) => item.key),
996
+ colors
997
+ );
998
+ const [period, setPeriod] = React__namespace.useState(defaultPeriod);
999
+ const [activeSeries, setActiveSeries] = React__namespace.useState(
1000
+ defaultSeries || chartSeries[0]?.key || ""
1001
+ );
1002
+ const filteredData = React__namespace.useMemo(() => filterData(data, period), [data, filterData, period]);
1003
+ const visibleSeries = chartSeries.length > 1 ? chartSeries.filter((item) => item.key === activeSeries) : chartSeries;
1004
+ const chartState = getChartState(
1005
+ {
1006
+ isLoading,
1007
+ error,
1008
+ onRetry,
1009
+ retryLabel,
1010
+ emptyTitle,
1011
+ emptyDescription,
1012
+ errorTitle,
1013
+ errorDescription,
1014
+ loadingLabel
1015
+ },
1016
+ hasChartData(filteredData, visibleSeries),
1017
+ button.cn("h-[320px] w-full", stateClassName)
1018
+ );
1019
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full space-y-4", children: [
1020
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between", children: [
1021
+ chartSeries.length > 1 ? /* @__PURE__ */ jsxRuntime.jsx(
1022
+ "div",
1023
+ {
1024
+ className: "inline-flex h-10 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
1025
+ role: "group",
1026
+ "aria-label": "Selecionar metrica do grafico",
1027
+ children: chartSeries.map((item) => {
1028
+ const label = item.label || config[item.key]?.label || item.key;
1029
+ return /* @__PURE__ */ jsxRuntime.jsx(
1030
+ button.Button,
1031
+ {
1032
+ type: "button",
1033
+ variant: "ghost",
1034
+ size: "sm",
1035
+ "aria-pressed": activeSeries === item.key,
1036
+ onClick: () => setActiveSeries(item.key),
1037
+ className: button.cn(
1038
+ "h-8 px-3 text-sm font-medium transition-all",
1039
+ activeSeries === item.key ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
1040
+ ),
1041
+ children: label
1042
+ },
1043
+ item.key
1044
+ );
1045
+ })
1046
+ }
1047
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", {}),
1048
+ /* @__PURE__ */ jsxRuntime.jsxs(select.Select, { value: period, onValueChange: setPeriod, children: [
1049
+ /* @__PURE__ */ jsxRuntime.jsx(
1050
+ select.SelectTrigger,
1051
+ {
1052
+ className: "w-full sm:w-[160px]",
1053
+ size: "sm",
1054
+ "aria-label": "Selecionar periodo do grafico",
1055
+ children: /* @__PURE__ */ jsxRuntime.jsx(select.SelectValue, { placeholder: "Period" })
1056
+ }
1057
+ ),
1058
+ /* @__PURE__ */ jsxRuntime.jsx(select.SelectContent, { children: periods.map((item) => /* @__PURE__ */ jsxRuntime.jsx(select.SelectItem, { value: item.value, children: item.label }, item.value)) })
1059
+ ] })
1060
+ ] }),
1061
+ chartState || /* @__PURE__ */ jsxRuntime.jsx(
1062
+ ChartContainer,
1063
+ {
1064
+ config: chartConfig,
1065
+ className: button.cn("h-[320px] w-full", className),
1066
+ ...props,
1067
+ children: /* @__PURE__ */ jsxRuntime.jsxs(RechartsPrimitive__namespace.AreaChart, { data: filteredData, accessibilityLayer: true, children: [
1068
+ gradientFill && /* @__PURE__ */ jsxRuntime.jsx(AreaGradientDefs, { seriesKeys: visibleSeries.map((s) => s.key), opacity: 0.4 }),
1069
+ showGrid ? /* @__PURE__ */ jsxRuntime.jsx(
1070
+ RechartsPrimitive__namespace.CartesianGrid,
1071
+ {
1072
+ vertical: false,
1073
+ strokeDasharray: "3 3",
1074
+ stroke: "var(--border)",
1075
+ strokeOpacity: 0.5
1076
+ }
1077
+ ) : null,
1078
+ /* @__PURE__ */ jsxRuntime.jsx(
1079
+ RechartsPrimitive__namespace.XAxis,
1080
+ {
1081
+ dataKey: indexKey,
1082
+ tickLine: false,
1083
+ axisLine: false,
1084
+ tickMargin: 8
1085
+ }
1086
+ ),
1087
+ /* @__PURE__ */ jsxRuntime.jsx(
1088
+ RechartsPrimitive__namespace.YAxis,
1089
+ {
1090
+ tickLine: false,
1091
+ axisLine: false,
1092
+ tickMargin: 8,
1093
+ tickFormatter: valueFormatter
1094
+ }
1095
+ ),
1096
+ /* @__PURE__ */ jsxRuntime.jsx(ChartTooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(ChartTooltipContent, { indicator: "line" }) }),
1097
+ showLegend ? /* @__PURE__ */ jsxRuntime.jsx(ChartLegend, { content: /* @__PURE__ */ jsxRuntime.jsx(ChartLegendContent, {}) }) : null,
1098
+ visibleSeries.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
1099
+ RechartsPrimitive__namespace.Area,
1100
+ {
1101
+ type: curveType,
1102
+ dataKey: item.key,
1103
+ stroke: `var(--color-${item.key})`,
1104
+ fill: gradientFill ? `url(#gradient-${item.key})` : `var(--color-${item.key})`,
1105
+ fillOpacity: gradientFill ? 1 : 0.16,
1106
+ strokeWidth,
1107
+ dot: showDots ? { r: 3, fill: `var(--color-${item.key})`, strokeWidth: 0 } : false,
1108
+ activeDot: { r: 5, strokeWidth: 0 },
1109
+ isAnimationActive: true,
1110
+ animationDuration: 600,
1111
+ animationEasing: "ease-out"
1112
+ },
1113
+ item.key
1114
+ ))
1115
+ ] })
1116
+ }
1117
+ )
1118
+ ] });
1119
+ }
1120
+ function ComboMetricChart({
1121
+ data,
1122
+ config,
1123
+ indexKey = "name",
1124
+ series,
1125
+ colors,
1126
+ barSize = "md",
1127
+ showGrid = true,
1128
+ showLegend = true,
1129
+ gradientFill = false,
1130
+ curveType = "monotone",
1131
+ valueFormatter = formatTick,
1132
+ isLoading,
1133
+ error,
1134
+ onRetry,
1135
+ retryLabel,
1136
+ emptyTitle,
1137
+ emptyDescription,
1138
+ errorTitle,
1139
+ errorDescription,
1140
+ loadingLabel,
1141
+ stateClassName,
1142
+ className,
1143
+ ...props
1144
+ }) {
1145
+ const chartSeries = getChartSeries(config, series);
1146
+ const chartConfig = getChartConfigWithColors(
1147
+ config,
1148
+ chartSeries.map((item) => item.key),
1149
+ colors
1150
+ );
1151
+ const chartState = getChartState(
1152
+ {
1153
+ isLoading,
1154
+ error,
1155
+ onRetry,
1156
+ retryLabel,
1157
+ emptyTitle,
1158
+ emptyDescription,
1159
+ errorTitle,
1160
+ errorDescription,
1161
+ loadingLabel
1162
+ },
1163
+ hasChartData(data, chartSeries),
1164
+ button.cn("h-[340px] w-full", stateClassName)
1165
+ );
1166
+ if (chartState) {
1167
+ return chartState;
1168
+ }
1169
+ const areaSeries = gradientFill ? chartSeries.filter((s) => s.type === "area").map((s) => s.key) : [];
1170
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartContainer, { config: chartConfig, className: button.cn("h-[340px] w-full", className), ...props, children: /* @__PURE__ */ jsxRuntime.jsxs(RechartsPrimitive__namespace.ComposedChart, { data, accessibilityLayer: true, children: [
1171
+ gradientFill && areaSeries.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(AreaGradientDefs, { seriesKeys: areaSeries, opacity: 0.35 }),
1172
+ showGrid ? /* @__PURE__ */ jsxRuntime.jsx(
1173
+ RechartsPrimitive__namespace.CartesianGrid,
1174
+ {
1175
+ vertical: false,
1176
+ strokeDasharray: "3 3",
1177
+ stroke: "var(--border)",
1178
+ strokeOpacity: 0.5
1179
+ }
1180
+ ) : null,
1181
+ /* @__PURE__ */ jsxRuntime.jsx(
1182
+ RechartsPrimitive__namespace.XAxis,
1183
+ {
1184
+ dataKey: indexKey,
1185
+ tickLine: false,
1186
+ axisLine: false,
1187
+ tickMargin: 8
1188
+ }
1189
+ ),
1190
+ /* @__PURE__ */ jsxRuntime.jsx(
1191
+ RechartsPrimitive__namespace.YAxis,
1192
+ {
1193
+ tickLine: false,
1194
+ axisLine: false,
1195
+ tickMargin: 8,
1196
+ tickFormatter: valueFormatter
1197
+ }
1198
+ ),
1199
+ /* @__PURE__ */ jsxRuntime.jsx(ChartTooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(ChartTooltipContent, {}) }),
1200
+ showLegend ? /* @__PURE__ */ jsxRuntime.jsx(ChartLegend, { content: /* @__PURE__ */ jsxRuntime.jsx(ChartLegendContent, {}) }) : null,
1201
+ chartSeries.map(
1202
+ (item) => item.type === "line" ? /* @__PURE__ */ jsxRuntime.jsx(
1203
+ RechartsPrimitive__namespace.Line,
1204
+ {
1205
+ type: curveType,
1206
+ dataKey: item.key,
1207
+ stroke: `var(--color-${item.key})`,
1208
+ strokeWidth: 2,
1209
+ dot: false,
1210
+ activeDot: { r: 5, strokeWidth: 0 },
1211
+ yAxisId: item.yAxisId,
1212
+ isAnimationActive: true,
1213
+ animationDuration: 600,
1214
+ animationEasing: "ease-out"
1215
+ },
1216
+ item.key
1217
+ ) : item.type === "area" ? /* @__PURE__ */ jsxRuntime.jsx(
1218
+ RechartsPrimitive__namespace.Area,
1219
+ {
1220
+ type: curveType,
1221
+ dataKey: item.key,
1222
+ stroke: `var(--color-${item.key})`,
1223
+ fill: gradientFill ? `url(#gradient-${item.key})` : `var(--color-${item.key})`,
1224
+ fillOpacity: gradientFill ? 1 : 0.12,
1225
+ strokeWidth: 2,
1226
+ dot: false,
1227
+ activeDot: { r: 5, strokeWidth: 0 },
1228
+ yAxisId: item.yAxisId,
1229
+ isAnimationActive: true,
1230
+ animationDuration: 600,
1231
+ animationEasing: "ease-out"
1232
+ },
1233
+ item.key
1234
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1235
+ RechartsPrimitive__namespace.Bar,
1236
+ {
1237
+ dataKey: item.key,
1238
+ fill: `var(--color-${item.key})`,
1239
+ radius: [4, 4, 0, 0],
1240
+ barSize: getBarSize(barSize),
1241
+ yAxisId: item.yAxisId,
1242
+ isAnimationActive: true,
1243
+ animationDuration: 600,
1244
+ animationEasing: "ease-out"
1245
+ },
1246
+ item.key
1247
+ )
1248
+ )
1249
+ ] }) });
1250
+ }
1251
+ function DonutBreakdownChart({
1252
+ data,
1253
+ config,
1254
+ nameKey = "name",
1255
+ valueKey = "value",
1256
+ colors,
1257
+ centerLabel,
1258
+ centerValue,
1259
+ showLegend = true,
1260
+ innerRadius = "58%",
1261
+ outerRadius = "82%",
1262
+ isLoading,
1263
+ error,
1264
+ onRetry,
1265
+ retryLabel,
1266
+ emptyTitle,
1267
+ emptyDescription,
1268
+ errorTitle,
1269
+ errorDescription,
1270
+ loadingLabel,
1271
+ stateClassName,
1272
+ className,
1273
+ ...props
1274
+ }) {
1275
+ const [activeIndex, setActiveIndex] = React__namespace.useState(0);
1276
+ const chartKeys = data.map((entry, index) => String(entry[nameKey] || `segment-${index}`));
1277
+ const chartConfig = getChartConfigWithColors(config, chartKeys, colors);
1278
+ const chartState = getChartState(
1279
+ {
1280
+ isLoading,
1281
+ error,
1282
+ onRetry,
1283
+ retryLabel,
1284
+ emptyTitle,
1285
+ emptyDescription,
1286
+ errorTitle,
1287
+ errorDescription,
1288
+ loadingLabel
1289
+ },
1290
+ hasPieData(data, nameKey, valueKey),
1291
+ button.cn("h-[320px] w-full", stateClassName)
1292
+ );
1293
+ if (chartState) {
1294
+ return chartState;
1295
+ }
1296
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartContainer, { config: chartConfig, className: button.cn("h-[320px] w-full", className), ...props, children: /* @__PURE__ */ jsxRuntime.jsxs(RechartsPrimitive__namespace.PieChart, { accessibilityLayer: true, children: [
1297
+ /* @__PURE__ */ jsxRuntime.jsx(
1298
+ ChartTooltip,
1299
+ {
1300
+ cursor: false,
1301
+ content: /* @__PURE__ */ jsxRuntime.jsx(ChartTooltipContent, { hideLabel: true, nameKey })
1302
+ }
1303
+ ),
1304
+ showLegend ? /* @__PURE__ */ jsxRuntime.jsx(ChartLegend, { content: /* @__PURE__ */ jsxRuntime.jsx(ChartLegendContent, { nameKey }), verticalAlign: "bottom" }) : null,
1305
+ /* @__PURE__ */ jsxRuntime.jsxs(
1306
+ RechartsPrimitive__namespace.Pie,
1307
+ {
1308
+ data,
1309
+ dataKey: valueKey,
1310
+ nameKey,
1311
+ innerRadius,
1312
+ outerRadius,
1313
+ paddingAngle: 3,
1314
+ onMouseEnter: (_, index) => setActiveIndex(index),
1315
+ isAnimationActive: true,
1316
+ animationDuration: 600,
1317
+ animationEasing: "ease-out",
1318
+ children: [
1319
+ data.map((entry, index) => {
1320
+ const key = String(entry[nameKey] || `segment-${index}`);
1321
+ return /* @__PURE__ */ jsxRuntime.jsx(
1322
+ RechartsPrimitive__namespace.Cell,
1323
+ {
1324
+ fill: `var(--color-${key})`,
1325
+ opacity: index === activeIndex ? 1 : 0.7,
1326
+ stroke: "transparent"
1327
+ },
1328
+ key
1329
+ );
1330
+ }),
1331
+ centerValue || centerLabel ? /* @__PURE__ */ jsxRuntime.jsx(
1332
+ RechartsPrimitive__namespace.Label,
1333
+ {
1334
+ position: "center",
1335
+ content: ({ viewBox }) => {
1336
+ if (!viewBox || !("cx" in viewBox) || !("cy" in viewBox)) {
1337
+ return null;
1338
+ }
1339
+ return /* @__PURE__ */ jsxRuntime.jsxs("text", { x: viewBox.cx, y: viewBox.cy, textAnchor: "middle", dominantBaseline: "middle", children: [
1340
+ centerValue ? /* @__PURE__ */ jsxRuntime.jsx(
1341
+ "tspan",
1342
+ {
1343
+ x: viewBox.cx,
1344
+ y: viewBox.cy,
1345
+ className: "fill-foreground text-2xl font-semibold",
1346
+ children: centerValue
1347
+ }
1348
+ ) : null,
1349
+ centerLabel ? /* @__PURE__ */ jsxRuntime.jsx(
1350
+ "tspan",
1351
+ {
1352
+ x: viewBox.cx,
1353
+ y: Number(viewBox.cy) + 22,
1354
+ className: "fill-muted-foreground text-xs",
1355
+ children: centerLabel
1356
+ }
1357
+ ) : null
1358
+ ] });
1359
+ }
1360
+ }
1361
+ ) : null
1362
+ ]
1363
+ }
1364
+ )
1365
+ ] }) });
1366
+ }
1367
+ function SparklineChart({
1368
+ data,
1369
+ dataKey,
1370
+ color = "var(--chart-1)",
1371
+ filled = true,
1372
+ showEndDot = true,
1373
+ curveType = "monotone",
1374
+ strokeWidth = 2,
1375
+ className
1376
+ }) {
1377
+ const sparkId = React__namespace.useId().replace(/:/g, "");
1378
+ const lastPoint = data[data.length - 1];
1379
+ const lastValue = lastPoint ? lastPoint[dataKey] : void 0;
1380
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: button.cn("relative h-12 w-full min-w-0", className), children: [
1381
+ /* @__PURE__ */ jsxRuntime.jsx(RechartsPrimitive__namespace.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
1382
+ RechartsPrimitive__namespace.AreaChart,
1383
+ {
1384
+ data,
1385
+ margin: { top: 4, right: showEndDot ? 8 : 0, bottom: 0, left: 0 },
1386
+ children: [
1387
+ filled && /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: `spark-gradient-${sparkId}`, x1: "0", y1: "0", x2: "0", y2: "1", children: [
1388
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "5%", stopColor: color, stopOpacity: 0.3 }),
1389
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "95%", stopColor: color, stopOpacity: 0 })
1390
+ ] }) }),
1391
+ /* @__PURE__ */ jsxRuntime.jsx(
1392
+ RechartsPrimitive__namespace.Area,
1393
+ {
1394
+ type: curveType,
1395
+ dataKey,
1396
+ stroke: color,
1397
+ strokeWidth,
1398
+ fill: filled ? `url(#spark-gradient-${sparkId})` : "none",
1399
+ fillOpacity: 1,
1400
+ dot: false,
1401
+ activeDot: false,
1402
+ isAnimationActive: true,
1403
+ animationDuration: 600,
1404
+ animationEasing: "ease-out"
1405
+ }
1406
+ )
1407
+ ]
1408
+ }
1409
+ ) }),
1410
+ showEndDot && lastValue !== void 0 && lastValue !== null && /* @__PURE__ */ jsxRuntime.jsx(
1411
+ "div",
1412
+ {
1413
+ className: "pointer-events-none absolute right-0 top-1/2 h-2.5 w-2.5 -translate-y-1/2 rounded-full ring-2 ring-background",
1414
+ style: { backgroundColor: color }
1415
+ }
1416
+ )
1417
+ ] });
1418
+ }
1419
+ function RadarMetricChart({
1420
+ data,
1421
+ labelKey,
1422
+ series,
1423
+ colors,
1424
+ filled = true,
1425
+ fillOpacity = 0.25,
1426
+ showDots = false,
1427
+ showGrid = true,
1428
+ showLegend,
1429
+ valueFormatter,
1430
+ isLoading,
1431
+ error,
1432
+ onRetry,
1433
+ retryLabel,
1434
+ emptyTitle,
1435
+ emptyDescription,
1436
+ errorTitle,
1437
+ errorDescription,
1438
+ loadingLabel,
1439
+ stateClassName,
1440
+ className
1441
+ }) {
1442
+ const chartConfig = React__namespace.useMemo(
1443
+ () => buildChartConfig(
1444
+ series.map((s) => s.key),
1445
+ colors
1446
+ ),
1447
+ [series, colors]
1448
+ );
1449
+ const hasData = data.length > 0 && series.length > 0;
1450
+ const chartState = getChartState(
1451
+ {
1452
+ isLoading,
1453
+ error,
1454
+ emptyTitle,
1455
+ emptyDescription,
1456
+ errorTitle,
1457
+ errorDescription,
1458
+ loadingLabel,
1459
+ stateClassName,
1460
+ onRetry,
1461
+ retryLabel
1462
+ },
1463
+ hasData
1464
+ );
1465
+ const displayLegend = showLegend ?? series.length > 1;
1466
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartContainer, { config: chartConfig, className: button.cn("h-[300px] w-full", className), children: chartState ?? /* @__PURE__ */ jsxRuntime.jsxs(RechartsPrimitive__namespace.RadarChart, { data, accessibilityLayer: true, children: [
1467
+ showGrid && /* @__PURE__ */ jsxRuntime.jsx(RechartsPrimitive__namespace.PolarGrid, { stroke: "var(--border)", strokeOpacity: 0.6 }),
1468
+ /* @__PURE__ */ jsxRuntime.jsx(
1469
+ RechartsPrimitive__namespace.PolarAngleAxis,
1470
+ {
1471
+ dataKey: labelKey,
1472
+ tick: { fill: "var(--muted-foreground)", fontSize: 12 }
1473
+ }
1474
+ ),
1475
+ /* @__PURE__ */ jsxRuntime.jsx(
1476
+ RechartsPrimitive__namespace.PolarRadiusAxis,
1477
+ {
1478
+ tick: false,
1479
+ axisLine: false,
1480
+ tickFormatter: valueFormatter
1481
+ }
1482
+ ),
1483
+ /* @__PURE__ */ jsxRuntime.jsx(
1484
+ ChartTooltip,
1485
+ {
1486
+ content: /* @__PURE__ */ jsxRuntime.jsx(
1487
+ ChartTooltipContent,
1488
+ {
1489
+ formatter: valueFormatter ? (v) => valueFormatter(v) : void 0
1490
+ }
1491
+ )
1492
+ }
1493
+ ),
1494
+ displayLegend && /* @__PURE__ */ jsxRuntime.jsx(ChartLegend, { content: /* @__PURE__ */ jsxRuntime.jsx(ChartLegendContent, {}) }),
1495
+ series.map((s) => /* @__PURE__ */ jsxRuntime.jsx(
1496
+ RechartsPrimitive__namespace.Radar,
1497
+ {
1498
+ name: s.label ?? s.key,
1499
+ dataKey: s.key,
1500
+ stroke: `var(--color-${s.key})`,
1501
+ fill: filled ? `var(--color-${s.key})` : "none",
1502
+ fillOpacity: filled ? fillOpacity : 0,
1503
+ dot: showDots ? { r: 3, fill: `var(--color-${s.key})` } : false,
1504
+ isAnimationActive: true,
1505
+ animationDuration: 600,
1506
+ animationEasing: "ease-out"
1507
+ },
1508
+ s.key
1509
+ ))
1510
+ ] }) });
1511
+ }
1512
+ function PieMetricChart({
1513
+ data,
1514
+ nameKey,
1515
+ valueKey,
1516
+ colors,
1517
+ outerRadius = "80%",
1518
+ innerRadius = 0,
1519
+ showLabels = false,
1520
+ showLegend = true,
1521
+ explodeIndex,
1522
+ explodeOffset = 12,
1523
+ valueFormatter,
1524
+ isLoading,
1525
+ error,
1526
+ onRetry,
1527
+ retryLabel,
1528
+ emptyTitle,
1529
+ emptyDescription,
1530
+ errorTitle,
1531
+ errorDescription,
1532
+ loadingLabel,
1533
+ stateClassName,
1534
+ className
1535
+ }) {
1536
+ const names = React__namespace.useMemo(() => data.map((d) => String(d[nameKey] ?? "")), [data, nameKey]);
1537
+ const chartConfig = React__namespace.useMemo(() => buildChartConfig(names, colors), [names, colors]);
1538
+ const hasData = hasPieData(data, nameKey, valueKey);
1539
+ const chartState = getChartState(
1540
+ {
1541
+ isLoading,
1542
+ error,
1543
+ emptyTitle,
1544
+ emptyDescription,
1545
+ errorTitle,
1546
+ errorDescription,
1547
+ loadingLabel,
1548
+ stateClassName,
1549
+ onRetry,
1550
+ retryLabel
1551
+ },
1552
+ hasData
1553
+ );
1554
+ return /* @__PURE__ */ jsxRuntime.jsx(ChartContainer, { config: chartConfig, className: button.cn("h-[300px] w-full", className), children: chartState ?? /* @__PURE__ */ jsxRuntime.jsxs(RechartsPrimitive__namespace.PieChart, { accessibilityLayer: true, children: [
1555
+ /* @__PURE__ */ jsxRuntime.jsx(
1556
+ ChartTooltip,
1557
+ {
1558
+ content: /* @__PURE__ */ jsxRuntime.jsx(
1559
+ ChartTooltipContent,
1560
+ {
1561
+ nameKey,
1562
+ formatter: valueFormatter ? (v) => valueFormatter(v) : void 0
1563
+ }
1564
+ )
1565
+ }
1566
+ ),
1567
+ showLegend && /* @__PURE__ */ jsxRuntime.jsx(ChartLegend, { content: /* @__PURE__ */ jsxRuntime.jsx(ChartLegendContent, { nameKey }) }),
1568
+ /* @__PURE__ */ jsxRuntime.jsx(
1569
+ RechartsPrimitive__namespace.Pie,
1570
+ {
1571
+ data,
1572
+ dataKey: valueKey,
1573
+ nameKey,
1574
+ outerRadius,
1575
+ innerRadius,
1576
+ paddingAngle: 2,
1577
+ label: showLabels ? ({ cx, cy, midAngle, innerRadius: ir, outerRadius: or, percent }) => {
1578
+ if (midAngle == null || percent == null) return null;
1579
+ const RADIAN = Math.PI / 180;
1580
+ const radius = Number(ir) + (Number(or) - Number(ir)) * 1.35;
1581
+ const x = Number(cx) + radius * Math.cos(-midAngle * RADIAN);
1582
+ const y = Number(cy) + radius * Math.sin(-midAngle * RADIAN);
1583
+ return percent > 0.04 ? /* @__PURE__ */ jsxRuntime.jsx(
1584
+ "text",
1585
+ {
1586
+ x,
1587
+ y,
1588
+ fill: "var(--foreground)",
1589
+ textAnchor: x > Number(cx) ? "start" : "end",
1590
+ dominantBaseline: "central",
1591
+ fontSize: 12,
1592
+ fontWeight: 500,
1593
+ children: `${(percent * 100).toFixed(0)}%`
1594
+ }
1595
+ ) : null;
1596
+ } : false,
1597
+ labelLine: false,
1598
+ isAnimationActive: true,
1599
+ animationDuration: 600,
1600
+ animationEasing: "ease-out",
1601
+ children: data.map((entry, index) => {
1602
+ const name = String(entry[nameKey] ?? "");
1603
+ const isExploded = index === explodeIndex;
1604
+ return /* @__PURE__ */ jsxRuntime.jsx(
1605
+ RechartsPrimitive__namespace.Cell,
1606
+ {
1607
+ fill: chartConfig[name]?.color ?? `var(--chart-${index % 8 + 1})`,
1608
+ stroke: "var(--background)",
1609
+ strokeWidth: 2,
1610
+ style: isExploded ? {
1611
+ filter: `drop-shadow(0 4px 8px color-mix(in srgb, ${chartConfig[name]?.color ?? "var(--chart-1)"} 40%, transparent))`
1612
+ } : void 0
1613
+ },
1614
+ `cell-${index}`
1615
+ );
1616
+ })
1617
+ }
1618
+ )
1619
+ ] }) });
1620
+ }
1621
+ function RadialBarMetricChart({
1622
+ data,
1623
+ dataKey = "value",
1624
+ nameKey = "name",
1625
+ colors,
1626
+ innerRadius = "30%",
1627
+ outerRadius = "100%",
1628
+ startAngle = 90,
1629
+ endAngle = -270,
1630
+ showBackground = true,
1631
+ showLegend = true,
1632
+ valueFormatter,
1633
+ isLoading,
1634
+ error,
1635
+ onRetry,
1636
+ retryLabel,
1637
+ emptyTitle,
1638
+ emptyDescription,
1639
+ errorTitle,
1640
+ errorDescription,
1641
+ loadingLabel,
1642
+ stateClassName,
1643
+ className
1644
+ }) {
1645
+ const names = React__namespace.useMemo(() => data.map((d) => String(d[nameKey] ?? "")), [data, nameKey]);
1646
+ const chartConfig = React__namespace.useMemo(() => buildChartConfig(names, colors), [names, colors]);
1647
+ const hasData = data.length > 0;
1648
+ const chartState = getChartState(
1649
+ {
1650
+ isLoading,
1651
+ error,
1652
+ emptyTitle,
1653
+ emptyDescription,
1654
+ errorTitle,
1655
+ errorDescription,
1656
+ loadingLabel,
1657
+ stateClassName,
1658
+ onRetry,
1659
+ retryLabel
1660
+ },
1661
+ hasData
1662
+ );
1663
+ const coloredData = React__namespace.useMemo(
1664
+ () => data.map((item, index) => {
1665
+ const name = String(item[nameKey] ?? "");
1666
+ return {
1667
+ ...item,
1668
+ fill: chartConfig[name]?.color ?? `var(--chart-${index % 8 + 1})`
1669
+ };
1670
+ }),
1671
+ [data, nameKey, chartConfig]
1672
+ );
1673
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: button.cn("flex w-full flex-col gap-3", className), children: [
1674
+ /* @__PURE__ */ jsxRuntime.jsx(ChartContainer, { config: chartConfig, className: "h-[260px] w-full", children: chartState ?? /* @__PURE__ */ jsxRuntime.jsxs(
1675
+ RechartsPrimitive__namespace.RadialBarChart,
1676
+ {
1677
+ data: coloredData,
1678
+ innerRadius,
1679
+ outerRadius,
1680
+ startAngle,
1681
+ endAngle,
1682
+ accessibilityLayer: true,
1683
+ children: [
1684
+ /* @__PURE__ */ jsxRuntime.jsx(
1685
+ ChartTooltip,
1686
+ {
1687
+ cursor: false,
1688
+ content: /* @__PURE__ */ jsxRuntime.jsx(
1689
+ ChartTooltipContent,
1690
+ {
1691
+ nameKey,
1692
+ formatter: valueFormatter ? (v) => valueFormatter(v) : void 0
1693
+ }
1694
+ )
1695
+ }
1696
+ ),
1697
+ /* @__PURE__ */ jsxRuntime.jsx(
1698
+ RechartsPrimitive__namespace.RadialBar,
1699
+ {
1700
+ dataKey,
1701
+ background: showBackground ? { fill: "var(--muted)" } : false,
1702
+ cornerRadius: 6,
1703
+ isAnimationActive: true,
1704
+ animationDuration: 700,
1705
+ animationEasing: "ease-out"
1706
+ }
1707
+ )
1708
+ ]
1709
+ }
1710
+ ) }),
1711
+ showLegend && !chartState && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap justify-center gap-x-4 gap-y-1.5 px-2", children: coloredData.map((item, index) => {
1712
+ const d = item;
1713
+ const name = String(d[nameKey] ?? "");
1714
+ const fillColor = d.fill ?? `var(--chart-${index % 8 + 1})`;
1715
+ const val = d[dataKey];
1716
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
1717
+ /* @__PURE__ */ jsxRuntime.jsx(
1718
+ "span",
1719
+ {
1720
+ className: "inline-block h-2.5 w-2.5 shrink-0 rounded-full",
1721
+ style: { backgroundColor: fillColor }
1722
+ }
1723
+ ),
1724
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
1725
+ name,
1726
+ val !== void 0 && val !== null && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 font-medium text-foreground", children: valueFormatter ? valueFormatter(val) : String(val) })
1727
+ ] })
1728
+ ] }, name);
1729
+ }) })
1730
+ ] });
1731
+ }
1732
+ function GaugeChart({
1733
+ value,
1734
+ min = 0,
1735
+ max = 100,
1736
+ thresholds,
1737
+ label,
1738
+ valueFormatter,
1739
+ showNeedle = true,
1740
+ className
1741
+ }) {
1742
+ const percent = Math.min(1, Math.max(0, (value - min) / (max - min)));
1743
+ const percentInt = Math.round(percent * 100);
1744
+ const activeColor = React__namespace.useMemo(() => {
1745
+ if (!thresholds || thresholds.length === 0) return "var(--chart-1)";
1746
+ for (const t of thresholds) {
1747
+ if (percentInt <= t.value) return t.color;
1748
+ }
1749
+ return thresholds[thresholds.length - 1].color;
1750
+ }, [thresholds, percentInt]);
1751
+ const displayText = valueFormatter ? valueFormatter(value, percentInt) : `${percentInt}%`;
1752
+ const cx = 100;
1753
+ const cy = 100;
1754
+ const R = 80;
1755
+ const r = 54;
1756
+ const polar = (angleDeg, radius) => {
1757
+ const rad = angleDeg * Math.PI / 180;
1758
+ return {
1759
+ x: cx + radius * Math.cos(rad),
1760
+ y: cy - radius * Math.sin(rad)
1761
+ };
1762
+ };
1763
+ const trackStart = polar(180, R);
1764
+ const trackEnd = polar(0, R);
1765
+ const trackStartI = polar(180, r);
1766
+ const trackEndI = polar(0, r);
1767
+ const trackPath = [
1768
+ `M ${trackStart.x} ${trackStart.y}`,
1769
+ `A ${R} ${R} 0 0 1 ${trackEnd.x} ${trackEnd.y}`,
1770
+ `L ${trackEndI.x} ${trackEndI.y}`,
1771
+ `A ${r} ${r} 0 0 0 ${trackStartI.x} ${trackStartI.y}`,
1772
+ "Z"
1773
+ ].join(" ");
1774
+ const valueAngle = 180 - percent * 180;
1775
+ const valueEnd = polar(valueAngle, R);
1776
+ const valueEndI = polar(valueAngle, r);
1777
+ const valuePath = percent <= 0 ? "" : percent >= 1 ? trackPath : [
1778
+ `M ${trackStart.x} ${trackStart.y}`,
1779
+ `A ${R} ${R} 0 0 1 ${valueEnd.x} ${valueEnd.y}`,
1780
+ `L ${valueEndI.x} ${valueEndI.y}`,
1781
+ `A ${r} ${r} 0 0 0 ${trackStartI.x} ${trackStartI.y}`,
1782
+ "Z"
1783
+ ].join(" ");
1784
+ const needleAngle = 180 - percent * 180;
1785
+ const needleTip = polar(needleAngle, r - 6);
1786
+ const needleBase1 = polar(needleAngle + 90, 5);
1787
+ const needleBase2 = polar(needleAngle - 90, 5);
1788
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: button.cn("flex flex-col items-center gap-2", className), children: [
1789
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full max-w-[260px]", children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 200 130", className: "w-full", "aria-label": `Gauge: ${displayText}`, children: [
1790
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: trackPath, fill: "var(--muted)" }),
1791
+ valuePath && /* @__PURE__ */ jsxRuntime.jsx("path", { d: valuePath, fill: activeColor }),
1792
+ showNeedle && /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
1793
+ /* @__PURE__ */ jsxRuntime.jsx(
1794
+ "polygon",
1795
+ {
1796
+ points: `${needleTip.x},${needleTip.y} ${needleBase1.x},${needleBase1.y} ${needleBase2.x},${needleBase2.y}`,
1797
+ fill: "var(--foreground)",
1798
+ opacity: 0.85
1799
+ }
1800
+ ),
1801
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx, cy, r: 5, fill: "var(--foreground)" })
1802
+ ] }),
1803
+ /* @__PURE__ */ jsxRuntime.jsx(
1804
+ "text",
1805
+ {
1806
+ x: cx,
1807
+ y: cy + 18,
1808
+ textAnchor: "middle",
1809
+ dominantBaseline: "middle",
1810
+ fontSize: 22,
1811
+ fontWeight: 700,
1812
+ fill: "currentColor",
1813
+ className: "fill-foreground",
1814
+ children: displayText
1815
+ }
1816
+ ),
1817
+ label && /* @__PURE__ */ jsxRuntime.jsx(
1818
+ "text",
1819
+ {
1820
+ x: cx,
1821
+ y: cy + 36,
1822
+ textAnchor: "middle",
1823
+ dominantBaseline: "middle",
1824
+ fontSize: 10,
1825
+ fill: "currentColor",
1826
+ className: "fill-muted-foreground",
1827
+ children: label
1828
+ }
1829
+ )
1830
+ ] }) }),
1831
+ thresholds && thresholds.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap justify-center gap-x-3 gap-y-1", children: thresholds.map((t, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
1832
+ /* @__PURE__ */ jsxRuntime.jsx(
1833
+ "span",
1834
+ {
1835
+ className: "inline-block h-2 w-2 shrink-0 rounded-full",
1836
+ style: { backgroundColor: t.color }
1837
+ }
1838
+ ),
1839
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: t.label })
1840
+ ] }, i)) })
1841
+ ] });
1842
+ }
1843
+
1844
+ function Table({ className, ...props }) {
1845
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "table-container", className: "relative w-full overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsx(
1846
+ "table",
1847
+ {
1848
+ "data-slot": "table",
1849
+ className: button.cn("w-full caption-bottom text-sm", className),
1850
+ ...props
1851
+ }
1852
+ ) });
1853
+ }
1854
+ function TableHeader({ className, ...props }) {
1855
+ return /* @__PURE__ */ jsxRuntime.jsx("thead", { "data-slot": "table-header", className: button.cn("[&_tr]:border-b", className), ...props });
1856
+ }
1857
+ function TableBody({ className, ...props }) {
1858
+ return /* @__PURE__ */ jsxRuntime.jsx(
1859
+ "tbody",
1860
+ {
1861
+ "data-slot": "table-body",
1862
+ className: button.cn("[&_tr:last-child]:border-0", className),
1863
+ ...props
1864
+ }
1865
+ );
1866
+ }
1867
+ function TableFooter({ className, ...props }) {
1868
+ return /* @__PURE__ */ jsxRuntime.jsx(
1869
+ "tfoot",
1870
+ {
1871
+ "data-slot": "table-footer",
1872
+ className: button.cn("bg-muted/50 border-t font-medium [&>tr]:last:border-b-0", className),
1873
+ ...props
1874
+ }
1875
+ );
1876
+ }
1877
+ function TableRow({ className, ...props }) {
1878
+ return /* @__PURE__ */ jsxRuntime.jsx(
1879
+ "tr",
1880
+ {
1881
+ "data-slot": "table-row",
1882
+ className: button.cn(
1883
+ "hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
1884
+ className
1885
+ ),
1886
+ ...props
1887
+ }
1888
+ );
1889
+ }
1890
+ function TableHead({ className, ...props }) {
1891
+ return /* @__PURE__ */ jsxRuntime.jsx(
1892
+ "th",
1893
+ {
1894
+ "data-slot": "table-head",
1895
+ className: button.cn(
1896
+ "text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
1897
+ className
1898
+ ),
1899
+ ...props
1900
+ }
1901
+ );
1902
+ }
1903
+ function TableCell({ className, ...props }) {
1904
+ return /* @__PURE__ */ jsxRuntime.jsx(
1905
+ "td",
1906
+ {
1907
+ "data-slot": "table-cell",
1908
+ className: button.cn(
1909
+ "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
1910
+ className
1911
+ ),
1912
+ ...props
1913
+ }
1914
+ );
1915
+ }
1916
+ function TableCaption({ className, ...props }) {
1917
+ return /* @__PURE__ */ jsxRuntime.jsx(
1918
+ "caption",
1919
+ {
1920
+ "data-slot": "table-caption",
1921
+ className: button.cn("text-muted-foreground mt-4 text-sm", className),
1922
+ ...props
1923
+ }
1924
+ );
1925
+ }
1926
+
1927
+ const Textarea = React__namespace.forwardRef(
1928
+ ({ className, size = "md", ...props }, ref) => {
1929
+ const sizeClasses = {
1930
+ sm: "px-2 py-1 text-sm",
1931
+ md: "px-3 py-2 text-base",
1932
+ lg: "px-4 py-3 text-base"
1933
+ };
1934
+ return /* @__PURE__ */ jsxRuntime.jsx(
1935
+ "textarea",
1936
+ {
1937
+ "data-slot": "textarea",
1938
+ className: button.cn(
1939
+ "flex min-h-16 w-full bg-background rounded-[var(--radius)] border border-border transition-colors outline-none resize-none text-foreground",
1940
+ "placeholder:text-muted-foreground",
1941
+ "focus:ring-2 focus:ring-primary focus:border-transparent",
1942
+ "disabled:cursor-not-allowed disabled:opacity-50",
1943
+ sizeClasses[size],
1944
+ className
1945
+ ),
1946
+ ref,
1947
+ ...props
1948
+ }
1949
+ );
1950
+ }
1951
+ );
1952
+ Textarea.displayName = "Textarea";
1953
+
1954
+ function Dialog({ ...props }) {
1955
+ return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Root, { "data-slot": "dialog", ...props });
1956
+ }
1957
+ function DialogTrigger({ ...props }) {
1958
+ return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Trigger, { "data-slot": "dialog-trigger", ...props });
1959
+ }
1960
+ function DialogPortal({ ...props }) {
1961
+ return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Portal, { "data-slot": "dialog-portal", ...props });
1962
+ }
1963
+ function DialogClose({ ...props }) {
1964
+ return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Close, { "data-slot": "dialog-close", ...props });
1965
+ }
1966
+ const DialogOverlay = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
1967
+ DialogPrimitive__namespace.Overlay,
1968
+ {
1969
+ ref,
1970
+ "data-slot": "dialog-overlay",
1971
+ className: button.cn(
1972
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/40 backdrop-blur-sm",
1973
+ className
1974
+ ),
1975
+ ...props
1976
+ }
1977
+ ));
1978
+ DialogOverlay.displayName = DialogPrimitive__namespace.Overlay.displayName;
1979
+ const dialogVariants = classVarianceAuthority.cva(
1980
+ "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 flex flex-col w-full translate-x-[-50%] translate-y-[-50%] border shadow-elevation-sm duration-200 rounded-[var(--radius-card)] overflow-hidden max-h-[calc(100dvh-2rem)]",
1981
+ {
1982
+ variants: {
1983
+ size: {
1984
+ sm: "max-w-sm",
1985
+ md: "max-w-md",
1986
+ lg: "max-w-lg",
1987
+ xl: "max-w-xl",
1988
+ "2xl": "max-w-2xl",
1989
+ "3xl": "max-w-3xl",
1990
+ "4xl": "max-w-4xl",
1991
+ "5xl": "max-w-5xl",
1992
+ full: "max-w-[calc(100vw-2rem)] h-[calc(100dvh-2rem)]"
1993
+ }
1994
+ },
1995
+ defaultVariants: {
1996
+ size: "lg"
1997
+ }
1998
+ }
1999
+ );
2000
+ const DialogContent = React__namespace.forwardRef(({ className, children, size, showClose = true, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { "data-slot": "dialog-portal", children: [
2001
+ /* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
2002
+ /* @__PURE__ */ jsxRuntime.jsxs(
2003
+ DialogPrimitive__namespace.Content,
2004
+ {
2005
+ ref,
2006
+ "data-slot": "dialog-content",
2007
+ className: button.cn(dialogVariants({ size }), className),
2008
+ ...props,
2009
+ children: [
2010
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4 p-6 overflow-y-auto flex-1 min-h-0", children }),
2011
+ showClose && /* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.Close, { className: "absolute top-4 right-4 z-10 rounded-full p-2 opacity-70 transition-all hover:opacity-100 hover:bg-accent focus:ring-2 focus:ring-primary focus:ring-offset-2 focus:outline-none disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", children: [
2012
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {}),
2013
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
2014
+ ] })
2015
+ ]
2016
+ }
2017
+ )
2018
+ ] }));
2019
+ DialogContent.displayName = DialogPrimitive__namespace.Content.displayName;
2020
+ function DialogHeader({ className, ...props }) {
2021
+ return /* @__PURE__ */ jsxRuntime.jsx(
2022
+ "div",
2023
+ {
2024
+ "data-slot": "dialog-header",
2025
+ className: button.cn("flex flex-col gap-2 text-left shrink-0", className),
2026
+ ...props
2027
+ }
2028
+ );
2029
+ }
2030
+ function DialogBody({ className, ...props }) {
2031
+ return /* @__PURE__ */ jsxRuntime.jsx(
2032
+ "div",
2033
+ {
2034
+ "data-slot": "dialog-body",
2035
+ className: button.cn("flex-1 overflow-y-auto min-h-0 -mx-6 px-6", className),
2036
+ ...props
2037
+ }
2038
+ );
2039
+ }
2040
+ function DialogFooter({ className, ...props }) {
2041
+ return /* @__PURE__ */ jsxRuntime.jsx(
2042
+ "div",
2043
+ {
2044
+ "data-slot": "dialog-footer",
2045
+ className: button.cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end shrink-0", className),
2046
+ ...props
2047
+ }
2048
+ );
2049
+ }
2050
+ function DialogTitle({ className, ...props }) {
2051
+ return /* @__PURE__ */ jsxRuntime.jsx(
2052
+ DialogPrimitive__namespace.Title,
2053
+ {
2054
+ "data-slot": "dialog-title",
2055
+ className: button.cn(
2056
+ "text-foreground font-semibold leading-tight text-[length:var(--text-h4)]",
2057
+ className
2058
+ ),
2059
+ ...props
2060
+ }
2061
+ );
2062
+ }
2063
+ function DialogDescription({
2064
+ className,
2065
+ ...props
2066
+ }) {
2067
+ return /* @__PURE__ */ jsxRuntime.jsx(
2068
+ DialogPrimitive__namespace.Description,
2069
+ {
2070
+ "data-slot": "dialog-description",
2071
+ className: button.cn("text-muted-foreground", className),
2072
+ ...props
2073
+ }
2074
+ );
2075
+ }
2076
+
2077
+ function useRichTextEditor({
2078
+ value,
2079
+ onChange
2080
+ }) {
2081
+ const editorRef = React.useRef(null);
2082
+ const searchInputRef = React.useRef(null);
2083
+ const linkInputRef = React.useRef(null);
2084
+ const savedSelection = React.useRef(null);
2085
+ const [wordCount, setWordCount] = React.useState(0);
2086
+ const [characterCount, setCharacterCount] = React.useState(0);
2087
+ const [activeFormats, setActiveFormats] = React.useState({
2088
+ bold: false,
2089
+ italic: false,
2090
+ underline: false,
2091
+ justifyLeft: false,
2092
+ justifyCenter: false,
2093
+ justifyRight: false,
2094
+ insertUnorderedList: false,
2095
+ insertOrderedList: false,
2096
+ link: false,
2097
+ h1: false,
2098
+ h2: false,
2099
+ h3: false,
2100
+ p: true
2101
+ });
2102
+ const [isSearchOpen, setIsSearchOpen] = React.useState(false);
2103
+ const [searchQuery, setSearchQuery] = React.useState("");
2104
+ const [linkUrl, setLinkUrl] = React.useState("https://");
2105
+ const [isLinkOpen, setIsLinkOpen] = React.useState(false);
2106
+ const [hasSavedSelection, setHasSavedSelection] = React.useState(false);
2107
+ const findParentTag = React.useCallback((node, tagName) => {
2108
+ let current = node;
2109
+ while (current && current !== editorRef.current) {
2110
+ if (current.nodeName === tagName) return current;
2111
+ current = current.parentNode;
2112
+ }
2113
+ return null;
2114
+ }, []);
2115
+ const updateActiveFormats = React.useCallback(() => {
2116
+ let formatBlock = "";
2117
+ try {
2118
+ formatBlock = document.queryCommandValue("formatBlock");
2119
+ } catch (_e) {
2120
+ }
2121
+ const selection = window.getSelection();
2122
+ const anchorNode = selection?.anchorNode;
2123
+ const focusNode = selection?.focusNode;
2124
+ setActiveFormats({
2125
+ bold: document.queryCommandState("bold"),
2126
+ italic: document.queryCommandState("italic"),
2127
+ underline: document.queryCommandState("underline"),
2128
+ justifyLeft: document.queryCommandState("justifyLeft"),
2129
+ justifyCenter: document.queryCommandState("justifyCenter"),
2130
+ justifyRight: document.queryCommandState("justifyRight"),
2131
+ insertUnorderedList: document.queryCommandState("insertUnorderedList"),
2132
+ insertOrderedList: document.queryCommandState("insertOrderedList"),
2133
+ link: !!(findParentTag(anchorNode || null, "A") || findParentTag(focusNode || null, "A")),
2134
+ h1: formatBlock === "h1" || formatBlock === "H1",
2135
+ h2: formatBlock === "h2" || formatBlock === "H2",
2136
+ h3: formatBlock === "h3" || formatBlock === "H3",
2137
+ p: formatBlock === "p" || formatBlock === "P" || formatBlock === "div" || formatBlock === "DIV" || formatBlock === ""
2138
+ });
2139
+ }, [findParentTag]);
2140
+ const updateActiveFormatsRef = React.useRef(updateActiveFormats);
2141
+ React.useEffect(() => {
2142
+ updateActiveFormatsRef.current = updateActiveFormats;
2143
+ }, [updateActiveFormats]);
2144
+ React.useEffect(() => {
2145
+ if (editorRef.current && editorRef.current.innerHTML !== value) {
2146
+ editorRef.current.innerHTML = value;
2147
+ }
2148
+ const handleSelectionChange = () => {
2149
+ if (document.activeElement === editorRef.current) {
2150
+ updateActiveFormatsRef.current();
2151
+ }
2152
+ };
2153
+ document.addEventListener("selectionchange", handleSelectionChange);
2154
+ return () => document.removeEventListener("selectionchange", handleSelectionChange);
2155
+ }, []);
2156
+ React.useEffect(() => {
2157
+ const text = editorRef.current?.innerText || "";
2158
+ setWordCount(text.trim() ? text.trim().split(/\s+/).length : 0);
2159
+ setCharacterCount(text.trim() ? text.length : 0);
2160
+ }, [value]);
2161
+ const handleInput = React.useCallback(() => {
2162
+ if (editorRef.current) {
2163
+ onChange?.(editorRef.current.innerHTML);
2164
+ updateActiveFormats();
2165
+ const text = editorRef.current.innerText || "";
2166
+ setWordCount(text.trim() ? text.trim().split(/\s+/).length : 0);
2167
+ setCharacterCount(text.trim() ? text.length : 0);
2168
+ }
2169
+ }, [onChange, updateActiveFormats]);
2170
+ const execCommand = React.useCallback(
2171
+ (command, val = "") => {
2172
+ document.execCommand(command, false, val);
2173
+ updateActiveFormats();
2174
+ editorRef.current?.focus();
2175
+ if (editorRef.current) {
2176
+ onChange?.(editorRef.current.innerHTML);
2177
+ }
2178
+ },
2179
+ [onChange, updateActiveFormats]
2180
+ );
2181
+ const performSearch = React.useCallback((text, backward = false) => {
2182
+ if (!text || !editorRef.current) return;
2183
+ const editor = editorRef.current;
2184
+ const selection = window.getSelection();
2185
+ if (!selection) return;
2186
+ const walker = document.createTreeWalker(editor, NodeFilter.SHOW_TEXT);
2187
+ const segments = [];
2188
+ let offset = 0;
2189
+ let node;
2190
+ while (node = walker.nextNode()) {
2191
+ segments.push({ node, start: offset });
2192
+ offset += node.length;
2193
+ }
2194
+ const fullText = segments.reduce((acc, s) => acc + (s.node.textContent ?? ""), "");
2195
+ let searchFrom = 0;
2196
+ if (selection.rangeCount > 0) {
2197
+ const range2 = selection.getRangeAt(0);
2198
+ if (editor.contains(range2.startContainer)) {
2199
+ const seg = segments.find((s) => s.node === range2.startContainer);
2200
+ if (seg) {
2201
+ searchFrom = backward ? seg.start + range2.startOffset - 1 : seg.start + range2.endOffset;
2202
+ }
2203
+ }
2204
+ }
2205
+ const lowerFull = fullText.toLowerCase();
2206
+ const lowerQuery = text.toLowerCase();
2207
+ let matchStart = -1;
2208
+ if (backward) {
2209
+ matchStart = lowerFull.lastIndexOf(lowerQuery, Math.max(0, searchFrom));
2210
+ if (matchStart === -1) matchStart = lowerFull.lastIndexOf(lowerQuery);
2211
+ } else {
2212
+ matchStart = lowerFull.indexOf(lowerQuery, searchFrom);
2213
+ if (matchStart === -1) matchStart = lowerFull.indexOf(lowerQuery);
2214
+ }
2215
+ if (matchStart === -1) return;
2216
+ const matchEnd = matchStart + text.length;
2217
+ const range = document.createRange();
2218
+ let startSet = false;
2219
+ let endSet = false;
2220
+ for (let i = 0; i < segments.length && !endSet; i++) {
2221
+ const seg = segments[i];
2222
+ const segEnd = seg.start + seg.node.length;
2223
+ if (!startSet && matchStart < segEnd && matchStart >= seg.start) {
2224
+ range.setStart(seg.node, matchStart - seg.start);
2225
+ startSet = true;
2226
+ }
2227
+ if (startSet && matchEnd <= segEnd) {
2228
+ range.setEnd(seg.node, matchEnd - seg.start);
2229
+ endSet = true;
2230
+ }
2231
+ }
2232
+ if (startSet && endSet) {
2233
+ selection.removeAllRanges();
2234
+ selection.addRange(range);
2235
+ range.startContainer.parentElement?.scrollIntoView?.({ block: "nearest" });
2236
+ }
2237
+ }, []);
2238
+ const handleCreateLink = React.useCallback(() => {
2239
+ if (savedSelection.current) {
2240
+ const selection2 = window.getSelection();
2241
+ selection2?.removeAllRanges();
2242
+ selection2?.addRange(savedSelection.current);
2243
+ }
2244
+ const selection = window.getSelection();
2245
+ const anchorNode = selection?.anchorNode;
2246
+ const existingLink = findParentTag(anchorNode || null, "A");
2247
+ if (existingLink) {
2248
+ if (linkUrl) {
2249
+ existingLink.setAttribute("href", linkUrl);
2250
+ existingLink.setAttribute("target", "_blank");
2251
+ existingLink.setAttribute("rel", "noopener noreferrer");
2252
+ existingLink.style.color = "hsl(var(--primary))";
2253
+ existingLink.style.textDecoration = "underline";
2254
+ existingLink.style.cursor = "pointer";
2255
+ }
2256
+ handleInput();
2257
+ setIsLinkOpen(false);
2258
+ savedSelection.current = null;
2259
+ return;
2260
+ }
2261
+ if (!selection || selection.rangeCount === 0 || selection.isCollapsed) {
2262
+ return;
2263
+ }
2264
+ if (linkUrl) {
2265
+ document.execCommand("createLink", false, linkUrl);
2266
+ setTimeout(() => {
2267
+ const anchor = findParentTag(window.getSelection()?.anchorNode || null, "A");
2268
+ if (anchor) {
2269
+ anchor.setAttribute("target", "_blank");
2270
+ anchor.setAttribute("rel", "noopener noreferrer");
2271
+ anchor.style.color = "hsl(var(--primary))";
2272
+ anchor.style.textDecoration = "underline";
2273
+ anchor.style.cursor = "pointer";
2274
+ }
2275
+ handleInput();
2276
+ }, 10);
2277
+ setIsLinkOpen(false);
2278
+ savedSelection.current = null;
2279
+ }
2280
+ }, [linkUrl, findParentTag, handleInput]);
2281
+ const handleUnlink = React.useCallback(() => {
2282
+ const selection = window.getSelection();
2283
+ const anchorNode = selection?.anchorNode;
2284
+ const existingLink = findParentTag(anchorNode || null, "A");
2285
+ if (existingLink) {
2286
+ const parent = existingLink.parentNode;
2287
+ while (existingLink.firstChild) {
2288
+ parent?.insertBefore(existingLink.firstChild, existingLink);
2289
+ }
2290
+ parent?.removeChild(existingLink);
2291
+ handleInput();
2292
+ } else {
2293
+ document.execCommand("unlink", false, "");
2294
+ }
2295
+ }, [findParentTag, handleInput]);
2296
+ const onLinkPopoverOpenChange = React.useCallback(
2297
+ (open) => {
2298
+ if (open) {
2299
+ const selection = window.getSelection();
2300
+ const anchorNode = selection?.anchorNode;
2301
+ const focusNode = selection?.focusNode;
2302
+ const existingLink = findParentTag(anchorNode || null, "A") || findParentTag(focusNode || null, "A");
2303
+ if (existingLink) {
2304
+ setLinkUrl(existingLink.getAttribute("href") || "https://");
2305
+ } else {
2306
+ setLinkUrl("https://");
2307
+ }
2308
+ if (selection && selection.rangeCount > 0 && (!selection.isCollapsed || existingLink)) {
2309
+ savedSelection.current = selection.getRangeAt(0).cloneRange();
2310
+ setHasSavedSelection(true);
2311
+ } else {
2312
+ savedSelection.current = null;
2313
+ setHasSavedSelection(false);
2314
+ }
2315
+ setTimeout(() => linkInputRef.current?.focus(), 100);
2316
+ } else {
2317
+ setHasSavedSelection(false);
2318
+ }
2319
+ setIsLinkOpen(open);
2320
+ },
2321
+ [findParentTag]
2322
+ );
2323
+ return {
2324
+ // Refs
2325
+ editorRef,
2326
+ searchInputRef,
2327
+ linkInputRef,
2328
+ // State
2329
+ activeFormats,
2330
+ isSearchOpen,
2331
+ setIsSearchOpen,
2332
+ searchQuery,
2333
+ setSearchQuery,
2334
+ linkUrl,
2335
+ setLinkUrl,
2336
+ isLinkOpen,
2337
+ hasSavedSelection,
2338
+ // Computed
2339
+ wordCount,
2340
+ characterCount,
2341
+ // Handlers
2342
+ updateActiveFormats,
2343
+ execCommand,
2344
+ handleInput,
2345
+ performSearch,
2346
+ handleCreateLink,
2347
+ handleUnlink,
2348
+ onLinkPopoverOpenChange
2349
+ };
2350
+ }
2351
+
2352
+ function RichTextEditor({
2353
+ value,
2354
+ onChange,
2355
+ placeholder,
2356
+ className,
2357
+ actionButton,
2358
+ allowSearch = true,
2359
+ allowLinks = true,
2360
+ allowUndoRedo = true,
2361
+ allowHeadings = true,
2362
+ allowFormatting = true,
2363
+ allowAlignment = true,
2364
+ allowLists = true,
2365
+ showWordCount = true,
2366
+ showCharacterCount = true,
2367
+ disabled = false,
2368
+ readOnly = false,
2369
+ onFocus,
2370
+ onBlur,
2371
+ minHeight,
2372
+ maxHeight
2373
+ }) {
2374
+ const isEditable = !disabled && !readOnly;
2375
+ const showToolbar = isEditable;
2376
+ const {
2377
+ editorRef,
2378
+ searchInputRef,
2379
+ linkInputRef,
2380
+ activeFormats,
2381
+ isSearchOpen,
2382
+ setIsSearchOpen,
2383
+ searchQuery,
2384
+ setSearchQuery,
2385
+ linkUrl,
2386
+ setLinkUrl,
2387
+ isLinkOpen,
2388
+ hasSavedSelection,
2389
+ wordCount,
2390
+ characterCount,
2391
+ updateActiveFormats,
2392
+ execCommand,
2393
+ handleInput,
2394
+ performSearch,
2395
+ handleCreateLink,
2396
+ handleUnlink,
2397
+ onLinkPopoverOpenChange
2398
+ } = useRichTextEditor({ value, onChange });
2399
+ const getCurrentBlockLabel = () => {
2400
+ if (activeFormats.h1)
2401
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2402
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Heading1, { className: "w-4 h-4 mr-1 shrink-0" }),
2403
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: "Título 1" })
2404
+ ] });
2405
+ if (activeFormats.h2)
2406
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2407
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Heading2, { className: "w-4 h-4 mr-1 shrink-0" }),
2408
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: "Título 2" })
2409
+ ] });
2410
+ if (activeFormats.h3)
2411
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2412
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Heading3, { className: "w-4 h-4 mr-1 shrink-0" }),
2413
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: "Título 3" })
2414
+ ] });
2415
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2416
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Type, { className: "w-4 h-4 mr-1 shrink-0" }),
2417
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: "Parágrafo" })
2418
+ ] });
2419
+ };
2420
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2421
+ "div",
2422
+ {
2423
+ className: button.cn(
2424
+ "flex flex-col h-full w-full bg-background sm:border border-border sm:shadow-sm sm:rounded-lg overflow-hidden",
2425
+ disabled && "opacity-50 pointer-events-none",
2426
+ className
2427
+ ),
2428
+ children: [
2429
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
2430
+ [contenteditable]:empty:before {
2431
+ content: attr(data-placeholder);
2432
+ color: hsl(var(--muted-foreground));
2433
+ pointer-events: none;
2434
+ display: block;
2435
+ }
2436
+ .prose-editor ul {
2437
+ list-style-type: disc !important;
2438
+ padding-left: 1.5rem !important;
2439
+ margin-top: 0.5rem !important;
2440
+ margin-bottom: 0.5rem !important;
2441
+ }
2442
+ .prose-editor ol {
2443
+ list-style-type: decimal !important;
2444
+ padding-left: 1.5rem !important;
2445
+ margin-top: 0.5rem !important;
2446
+ margin-bottom: 0.5rem !important;
2447
+ }
2448
+ .prose-editor b, .prose-editor strong {
2449
+ font-weight: 600 !important;
2450
+ }
2451
+ .prose-editor i, .prose-editor em {
2452
+ font-style: italic !important;
2453
+ }
2454
+ .prose-editor u {
2455
+ text-decoration: underline !important;
2456
+ }
2457
+ .prose-editor h1 {
2458
+ font-size: 2.25rem !important;
2459
+ font-weight: 700 !important;
2460
+ margin-bottom: 1.25rem !important;
2461
+ line-height: 1.2 !important;
2462
+ margin-top: 2rem !important;
2463
+ color: hsl(var(--foreground));
2464
+ }
2465
+ .prose-editor h2 {
2466
+ font-size: 1.75rem !important;
2467
+ font-weight: 600 !important;
2468
+ margin-bottom: 1rem !important;
2469
+ margin-top: 1.5rem !important;
2470
+ color: hsl(var(--foreground));
2471
+ }
2472
+ .prose-editor h3 {
2473
+ font-size: 1.35rem !important;
2474
+ font-weight: 600 !important;
2475
+ margin-bottom: 0.75rem !important;
2476
+ margin-top: 1.25rem !important;
2477
+ color: hsl(var(--foreground));
2478
+ }
2479
+ .prose-editor p {
2480
+ margin-bottom: 1rem !important;
2481
+ line-height: 1.6 !important;
2482
+ }
2483
+ .prose-editor a {
2484
+ color: var(--info) !important;
2485
+ text-decoration: underline !important;
2486
+ cursor: pointer !important;
2487
+ }
2488
+ .prose-editor h1:first-child, .prose-editor h2:first-child, .prose-editor h3:first-child, .prose-editor p:first-child {
2489
+ margin-top: 0 !important;
2490
+ }
2491
+ .prose-editor {
2492
+ outline: none !important;
2493
+ }
2494
+ ` }),
2495
+ showToolbar && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-2 border-b border-border bg-muted/30 flex items-center gap-1 flex-wrap shrink-0", children: [
2496
+ allowUndoRedo && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2497
+ /* @__PURE__ */ jsxRuntime.jsx(
2498
+ button.Button,
2499
+ {
2500
+ variant: "ghost",
2501
+ size: "icon",
2502
+ className: "h-8 w-8 text-muted-foreground",
2503
+ onClick: () => execCommand("undo"),
2504
+ title: "Desfazer",
2505
+ "aria-label": "Desfazer",
2506
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Undo, { className: "w-4 h-4" })
2507
+ }
2508
+ ),
2509
+ /* @__PURE__ */ jsxRuntime.jsx(
2510
+ button.Button,
2511
+ {
2512
+ variant: "ghost",
2513
+ size: "icon",
2514
+ className: "h-8 w-8 text-muted-foreground",
2515
+ onClick: () => execCommand("redo"),
2516
+ title: "Refazer",
2517
+ "aria-label": "Refazer",
2518
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Redo, { className: "w-4 h-4" })
2519
+ }
2520
+ ),
2521
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-6 bg-border mx-1 hidden sm:block" })
2522
+ ] }),
2523
+ allowHeadings && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2524
+ /* @__PURE__ */ jsxRuntime.jsxs(dropdownMenu.DropdownMenu, { modal: false, children: [
2525
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
2526
+ button.Button,
2527
+ {
2528
+ variant: "ghost",
2529
+ size: "sm",
2530
+ className: "h-8 gap-0 text-muted-foreground w-[120px] justify-start px-2",
2531
+ children: [
2532
+ getCurrentBlockLabel(),
2533
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "w-3 h-3 ml-auto opacity-50 shrink-0" })
2534
+ ]
2535
+ }
2536
+ ) }),
2537
+ /* @__PURE__ */ jsxRuntime.jsxs(dropdownMenu.DropdownMenuContent, { align: "start", className: "w-[160px]", style: { zIndex: 9999 }, children: [
2538
+ /* @__PURE__ */ jsxRuntime.jsxs(
2539
+ dropdownMenu.DropdownMenuItem,
2540
+ {
2541
+ onPointerDown: (e) => e.preventDefault(),
2542
+ onClick: () => execCommand("formatBlock", "P"),
2543
+ className: "gap-2",
2544
+ children: [
2545
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Type, { className: "w-4 h-4 text-muted-foreground" }),
2546
+ " Parágrafo"
2547
+ ]
2548
+ }
2549
+ ),
2550
+ /* @__PURE__ */ jsxRuntime.jsxs(
2551
+ dropdownMenu.DropdownMenuItem,
2552
+ {
2553
+ onPointerDown: (e) => e.preventDefault(),
2554
+ onClick: () => execCommand("formatBlock", "H1"),
2555
+ className: "gap-2",
2556
+ children: [
2557
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Heading1, { className: "w-4 h-4 text-muted-foreground" }),
2558
+ " Título 1"
2559
+ ]
2560
+ }
2561
+ ),
2562
+ /* @__PURE__ */ jsxRuntime.jsxs(
2563
+ dropdownMenu.DropdownMenuItem,
2564
+ {
2565
+ onPointerDown: (e) => e.preventDefault(),
2566
+ onClick: () => execCommand("formatBlock", "H2"),
2567
+ className: "gap-2",
2568
+ children: [
2569
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Heading2, { className: "w-4 h-4 text-muted-foreground" }),
2570
+ " Título 2"
2571
+ ]
2572
+ }
2573
+ ),
2574
+ /* @__PURE__ */ jsxRuntime.jsxs(
2575
+ dropdownMenu.DropdownMenuItem,
2576
+ {
2577
+ onPointerDown: (e) => e.preventDefault(),
2578
+ onClick: () => execCommand("formatBlock", "H3"),
2579
+ className: "gap-2",
2580
+ children: [
2581
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Heading3, { className: "w-4 h-4 text-muted-foreground" }),
2582
+ " Título 3"
2583
+ ]
2584
+ }
2585
+ )
2586
+ ] })
2587
+ ] }),
2588
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-6 bg-border mx-1 hidden sm:block" })
2589
+ ] }),
2590
+ allowFormatting && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2591
+ /* @__PURE__ */ jsxRuntime.jsx(
2592
+ button.Button,
2593
+ {
2594
+ variant: "ghost",
2595
+ size: "icon",
2596
+ className: button.cn(
2597
+ "h-8 w-8 text-muted-foreground",
2598
+ activeFormats.bold && "bg-muted text-foreground"
2599
+ ),
2600
+ onClick: () => execCommand("bold"),
2601
+ title: "Negrito",
2602
+ "aria-label": "Negrito",
2603
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bold, { className: "w-4 h-4" })
2604
+ }
2605
+ ),
2606
+ /* @__PURE__ */ jsxRuntime.jsx(
2607
+ button.Button,
2608
+ {
2609
+ variant: "ghost",
2610
+ size: "icon",
2611
+ className: button.cn(
2612
+ "h-8 w-8 text-muted-foreground",
2613
+ activeFormats.italic && "bg-muted text-foreground"
2614
+ ),
2615
+ onClick: () => execCommand("italic"),
2616
+ title: "Itálico",
2617
+ "aria-label": "Itálico",
2618
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Italic, { className: "w-4 h-4" })
2619
+ }
2620
+ ),
2621
+ /* @__PURE__ */ jsxRuntime.jsx(
2622
+ button.Button,
2623
+ {
2624
+ variant: "ghost",
2625
+ size: "icon",
2626
+ className: button.cn(
2627
+ "h-8 w-8 text-muted-foreground",
2628
+ activeFormats.underline && "bg-muted text-foreground"
2629
+ ),
2630
+ onClick: () => execCommand("underline"),
2631
+ title: "Sublinhado",
2632
+ "aria-label": "Sublinhado",
2633
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Underline, { className: "w-4 h-4" })
2634
+ }
2635
+ ),
2636
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-6 bg-border mx-1 hidden sm:block" })
2637
+ ] }),
2638
+ allowAlignment && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2639
+ /* @__PURE__ */ jsxRuntime.jsx(
2640
+ button.Button,
2641
+ {
2642
+ variant: "ghost",
2643
+ size: "icon",
2644
+ className: button.cn(
2645
+ "h-8 w-8 text-muted-foreground",
2646
+ activeFormats.justifyLeft && "bg-muted text-foreground"
2647
+ ),
2648
+ onClick: () => execCommand("justifyLeft"),
2649
+ title: "Alinhar à esquerda",
2650
+ "aria-label": "Alinhar à esquerda",
2651
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignLeft, { className: "w-4 h-4" })
2652
+ }
2653
+ ),
2654
+ /* @__PURE__ */ jsxRuntime.jsx(
2655
+ button.Button,
2656
+ {
2657
+ variant: "ghost",
2658
+ size: "icon",
2659
+ className: button.cn(
2660
+ "h-8 w-8 text-muted-foreground",
2661
+ activeFormats.justifyCenter && "bg-muted text-foreground"
2662
+ ),
2663
+ onClick: () => execCommand("justifyCenter"),
2664
+ title: "Centralizar",
2665
+ "aria-label": "Centralizar",
2666
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignCenter, { className: "w-4 h-4" })
2667
+ }
2668
+ ),
2669
+ /* @__PURE__ */ jsxRuntime.jsx(
2670
+ button.Button,
2671
+ {
2672
+ variant: "ghost",
2673
+ size: "icon",
2674
+ className: button.cn(
2675
+ "h-8 w-8 text-muted-foreground",
2676
+ activeFormats.justifyRight && "bg-muted text-foreground"
2677
+ ),
2678
+ onClick: () => execCommand("justifyRight"),
2679
+ title: "Alinhar à direita",
2680
+ "aria-label": "Alinhar à direita",
2681
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignRight, { className: "w-4 h-4" })
2682
+ }
2683
+ ),
2684
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-6 bg-border mx-1 hidden sm:block" })
2685
+ ] }),
2686
+ allowLists && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2687
+ /* @__PURE__ */ jsxRuntime.jsx(
2688
+ button.Button,
2689
+ {
2690
+ variant: "ghost",
2691
+ size: "icon",
2692
+ className: button.cn(
2693
+ "h-8 w-8 text-muted-foreground",
2694
+ activeFormats.insertUnorderedList && "bg-muted text-foreground"
2695
+ ),
2696
+ onClick: () => execCommand("insertUnorderedList"),
2697
+ title: "Lista com marcadores",
2698
+ "aria-label": "Lista com marcadores",
2699
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.List, { className: "w-4 h-4" })
2700
+ }
2701
+ ),
2702
+ /* @__PURE__ */ jsxRuntime.jsx(
2703
+ button.Button,
2704
+ {
2705
+ variant: "ghost",
2706
+ size: "icon",
2707
+ className: button.cn(
2708
+ "h-8 w-8 text-muted-foreground",
2709
+ activeFormats.insertOrderedList && "bg-muted text-foreground"
2710
+ ),
2711
+ onClick: () => execCommand("insertOrderedList"),
2712
+ title: "Lista numerada",
2713
+ "aria-label": "Lista numerada",
2714
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListOrdered, { className: "w-4 h-4" })
2715
+ }
2716
+ ),
2717
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-6 bg-border mx-1 hidden sm:block" })
2718
+ ] }),
2719
+ allowLinks && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2720
+ /* @__PURE__ */ jsxRuntime.jsxs(input.Popover, { open: isLinkOpen, onOpenChange: onLinkPopoverOpenChange, modal: false, children: [
2721
+ /* @__PURE__ */ jsxRuntime.jsx(input.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
2722
+ button.Button,
2723
+ {
2724
+ variant: "ghost",
2725
+ size: "icon",
2726
+ className: button.cn(
2727
+ "h-8 w-8 text-muted-foreground",
2728
+ (activeFormats.link || isLinkOpen) && "bg-muted text-foreground"
2729
+ ),
2730
+ title: "Inserir link",
2731
+ "aria-label": "Inserir link",
2732
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link, { className: "w-4 h-4" })
2733
+ }
2734
+ ) }),
2735
+ /* @__PURE__ */ jsxRuntime.jsx(input.PopoverContent, { className: "w-80 p-3", align: "start", style: { zIndex: 9999 }, children: !activeFormats.link && !hasSavedSelection ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground py-1", children: "Selecione um texto para criar um link." }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
2736
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs font-medium", children: activeFormats.link ? "Editar Link" : "Inserir Link" }),
2737
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
2738
+ /* @__PURE__ */ jsxRuntime.jsx(
2739
+ input.Input,
2740
+ {
2741
+ ref: linkInputRef,
2742
+ placeholder: "https://...",
2743
+ value: linkUrl,
2744
+ onChange: (e) => setLinkUrl(e.target.value),
2745
+ onKeyDown: (e) => {
2746
+ if (e.key === "Enter") {
2747
+ e.preventDefault();
2748
+ e.stopPropagation();
2749
+ handleCreateLink();
2750
+ }
2751
+ },
2752
+ className: "h-8 text-xs"
2753
+ }
2754
+ ),
2755
+ /* @__PURE__ */ jsxRuntime.jsx(button.Button, { size: "sm", className: "h-8", onClick: handleCreateLink, children: "Aplicar" })
2756
+ ] })
2757
+ ] }) })
2758
+ ] }),
2759
+ /* @__PURE__ */ jsxRuntime.jsx(
2760
+ button.Button,
2761
+ {
2762
+ variant: "ghost",
2763
+ size: "icon",
2764
+ className: "h-8 w-8 text-muted-foreground",
2765
+ onClick: handleUnlink,
2766
+ title: "Remover link",
2767
+ "aria-label": "Remover link",
2768
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4" })
2769
+ }
2770
+ ),
2771
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-6 bg-border mx-1 hidden sm:block" })
2772
+ ] }),
2773
+ (allowFormatting || allowHeadings || allowAlignment || allowLists || allowLinks) && /* @__PURE__ */ jsxRuntime.jsx(
2774
+ button.Button,
2775
+ {
2776
+ variant: "ghost",
2777
+ size: "icon",
2778
+ className: "h-8 w-8 text-muted-foreground",
2779
+ onClick: () => execCommand("removeFormat"),
2780
+ title: "Limpar formatação",
2781
+ "aria-label": "Limpar formatação",
2782
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Type, { className: "w-4 h-4" })
2783
+ }
2784
+ ),
2785
+ allowSearch && /* @__PURE__ */ jsxRuntime.jsx(
2786
+ button.Button,
2787
+ {
2788
+ variant: "ghost",
2789
+ size: "icon",
2790
+ className: button.cn(
2791
+ "h-8 w-8 text-muted-foreground",
2792
+ isSearchOpen && "bg-muted text-foreground"
2793
+ ),
2794
+ onClick: () => {
2795
+ setIsSearchOpen(!isSearchOpen);
2796
+ if (!isSearchOpen) setTimeout(() => searchInputRef.current?.focus(), 100);
2797
+ },
2798
+ title: "Buscar",
2799
+ "aria-label": "Buscar",
2800
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "w-4 h-4" })
2801
+ }
2802
+ ),
2803
+ actionButton && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2804
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
2805
+ actionButton
2806
+ ] })
2807
+ ] }),
2808
+ isSearchOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-1.5 border-b border-border bg-muted/20 flex items-center gap-2", children: [
2809
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1 max-w-sm", children: [
2810
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground" }),
2811
+ /* @__PURE__ */ jsxRuntime.jsx(
2812
+ input.Input,
2813
+ {
2814
+ ref: searchInputRef,
2815
+ placeholder: "Buscar no texto...",
2816
+ value: searchQuery,
2817
+ onChange: (e) => setSearchQuery(e.target.value),
2818
+ onKeyDown: (e) => {
2819
+ if (e.key === "Enter") {
2820
+ e.preventDefault();
2821
+ performSearch(searchQuery, e.shiftKey);
2822
+ }
2823
+ if (e.key === "Escape") {
2824
+ setIsSearchOpen(false);
2825
+ }
2826
+ },
2827
+ className: "h-8 pl-8 text-xs bg-background"
2828
+ }
2829
+ )
2830
+ ] }),
2831
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
2832
+ /* @__PURE__ */ jsxRuntime.jsx(
2833
+ button.Button,
2834
+ {
2835
+ variant: "ghost",
2836
+ size: "icon",
2837
+ className: "h-7 w-7",
2838
+ onMouseDown: (e) => e.preventDefault(),
2839
+ onClick: () => performSearch(searchQuery, true),
2840
+ title: "Anterior",
2841
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { className: "w-4 h-4" })
2842
+ }
2843
+ ),
2844
+ /* @__PURE__ */ jsxRuntime.jsx(
2845
+ button.Button,
2846
+ {
2847
+ variant: "ghost",
2848
+ size: "icon",
2849
+ className: "h-7 w-7",
2850
+ onMouseDown: (e) => e.preventDefault(),
2851
+ onClick: () => performSearch(searchQuery, false),
2852
+ title: "Próximo",
2853
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "w-4 h-4" })
2854
+ }
2855
+ ),
2856
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-border mx-1" }),
2857
+ /* @__PURE__ */ jsxRuntime.jsx(
2858
+ button.Button,
2859
+ {
2860
+ variant: "ghost",
2861
+ size: "icon",
2862
+ className: "h-7 w-7 text-muted-foreground hover:text-foreground",
2863
+ onClick: () => setIsSearchOpen(false),
2864
+ title: "Fechar busca",
2865
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4" })
2866
+ }
2867
+ )
2868
+ ] }),
2869
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block text-[10px] text-muted-foreground ml-auto uppercase tracking-wider font-medium", children: "Pressione Enter para buscar" })
2870
+ ] }),
2871
+ /* @__PURE__ */ jsxRuntime.jsx(
2872
+ "div",
2873
+ {
2874
+ className: "flex-1 overflow-y-auto p-4 sm:p-8 bg-background scrollbar-thin",
2875
+ style: { minHeight, maxHeight },
2876
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2877
+ "div",
2878
+ {
2879
+ ref: editorRef,
2880
+ contentEditable: isEditable,
2881
+ role: "textbox",
2882
+ "aria-multiline": "true",
2883
+ "aria-label": placeholder || "Editor de texto",
2884
+ "aria-readonly": readOnly,
2885
+ "aria-disabled": disabled,
2886
+ onInput: handleInput,
2887
+ onSelect: isEditable ? updateActiveFormats : void 0,
2888
+ onFocus: () => {
2889
+ updateActiveFormats();
2890
+ onFocus?.();
2891
+ },
2892
+ onBlur,
2893
+ className: "prose-editor min-h-full max-w-none focus:outline-none",
2894
+ "data-placeholder": placeholder
2895
+ }
2896
+ )
2897
+ }
2898
+ ),
2899
+ (showWordCount || showCharacterCount) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-2 border-t border-border bg-muted/20 flex items-center justify-between", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[10px] sm:text-xs text-muted-foreground font-medium uppercase tracking-wider flex items-center gap-2", children: [
2900
+ showWordCount && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
2901
+ wordCount,
2902
+ " ",
2903
+ wordCount === 1 ? "palavra" : "palavras"
2904
+ ] }),
2905
+ showWordCount && showCharacterCount && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "•" }),
2906
+ showCharacterCount && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
2907
+ characterCount,
2908
+ " ",
2909
+ characterCount === 1 ? "caractere" : "caracteres"
2910
+ ] })
2911
+ ] }) })
2912
+ ]
2913
+ }
2914
+ );
2915
+ }
2916
+
2917
+ exports.Alert = Alert;
2918
+ exports.AlertDescription = AlertDescription;
2919
+ exports.AlertTitle = AlertTitle;
2920
+ exports.ChartCard = ChartCard;
2921
+ exports.ChartContainer = ChartContainer;
2922
+ exports.ChartLegend = ChartLegend;
2923
+ exports.ChartLegendContent = ChartLegendContent;
2924
+ exports.ChartStyle = ChartStyle;
2925
+ exports.ChartTooltip = ChartTooltip;
2926
+ exports.ChartTooltipContent = ChartTooltipContent;
2927
+ exports.ComboMetricChart = ComboMetricChart;
2928
+ exports.DashboardBarChart = DashboardBarChart;
2929
+ exports.DashboardLineChart = DashboardLineChart;
2930
+ exports.Dialog = Dialog;
2931
+ exports.DialogBody = DialogBody;
2932
+ exports.DialogClose = DialogClose;
2933
+ exports.DialogContent = DialogContent;
2934
+ exports.DialogDescription = DialogDescription;
2935
+ exports.DialogFooter = DialogFooter;
2936
+ exports.DialogHeader = DialogHeader;
2937
+ exports.DialogOverlay = DialogOverlay;
2938
+ exports.DialogPortal = DialogPortal;
2939
+ exports.DialogTitle = DialogTitle;
2940
+ exports.DialogTrigger = DialogTrigger;
2941
+ exports.DonutBreakdownChart = DonutBreakdownChart;
2942
+ exports.Empty = Empty;
2943
+ exports.EmptyAction = EmptyAction;
2944
+ exports.EmptyDescription = EmptyDescription;
2945
+ exports.EmptyIcon = EmptyIcon;
2946
+ exports.EmptyImage = EmptyImage;
2947
+ exports.EmptyTitle = EmptyTitle;
2948
+ exports.GaugeChart = GaugeChart;
2949
+ exports.HorizontalBarChart = HorizontalBarChart;
2950
+ exports.InteractiveTimeSeriesChart = InteractiveTimeSeriesChart;
2951
+ exports.PieMetricChart = PieMetricChart;
2952
+ exports.RadarMetricChart = RadarMetricChart;
2953
+ exports.RadialBarMetricChart = RadialBarMetricChart;
2954
+ exports.RichTextEditor = RichTextEditor;
2955
+ exports.ScrollArea = ScrollArea;
2956
+ exports.ScrollBar = ScrollBar;
2957
+ exports.SparklineChart = SparklineChart;
2958
+ exports.Table = Table;
2959
+ exports.TableBody = TableBody;
2960
+ exports.TableCaption = TableCaption;
2961
+ exports.TableCell = TableCell;
2962
+ exports.TableFooter = TableFooter;
2963
+ exports.TableHead = TableHead;
2964
+ exports.TableHeader = TableHeader;
2965
+ exports.TableRow = TableRow;
2966
+ exports.Textarea = Textarea;
2967
+ exports.useChart = useChart;
2968
+ exports.useRichTextEditor = useRichTextEditor;