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