xertica-ui 2.1.3 → 2.1.4

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 (404) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +1 -1
  3. package/assets/xertica-logo.svg +37 -37
  4. package/assets/xertica-x-logo.svg +20 -20
  5. package/components/assistant/index.ts +6 -6
  6. package/components/assistant/xertica-assistant/parts/AssistantCollapsedView.tsx +97 -0
  7. package/components/assistant/xertica-assistant/parts/AssistantConversationList.tsx +104 -0
  8. package/components/assistant/xertica-assistant/parts/AssistantDocumentEditor.tsx +81 -0
  9. package/components/assistant/xertica-assistant/parts/AssistantFeedbackDialog.tsx +86 -0
  10. package/components/assistant/xertica-assistant/parts/AssistantHeader.tsx +77 -0
  11. package/components/assistant/xertica-assistant/parts/AssistantMessageBubble.tsx +573 -0
  12. package/components/assistant/xertica-assistant/parts/AssistantTabBar.tsx +65 -0
  13. package/components/assistant/xertica-assistant/parts/AssistantTypingIndicator.tsx +41 -0
  14. package/components/assistant/xertica-assistant/parts/AssistantWelcomeScreen.tsx +98 -0
  15. package/components/assistant/xertica-assistant/parts/index.ts +16 -0
  16. package/components/assistant/xertica-assistant/types.ts +139 -0
  17. package/components/assistant/xertica-assistant/use-assistant.ts +5 -10
  18. package/components/assistant/xertica-assistant/xertica-assistant.tsx +125 -1096
  19. package/components/blocks/card-patterns/ActivityCard.tsx +72 -72
  20. package/components/blocks/card-patterns/FeatureCard.tsx +100 -100
  21. package/components/blocks/card-patterns/NotificationCard.tsx +127 -127
  22. package/components/blocks/card-patterns/ProfileCard.tsx +84 -84
  23. package/components/blocks/card-patterns/ProjectCard.tsx +89 -89
  24. package/components/blocks/card-patterns/QuickActionCard.tsx +62 -62
  25. package/components/blocks/card-patterns/card-patterns.stories.tsx +445 -445
  26. package/components/blocks/card-patterns/index.ts +17 -17
  27. package/components/blocks/index.ts +1 -1
  28. package/components/brand/index.ts +6 -6
  29. package/components/brand/theme-toggle/ThemeToggle.tsx +8 -27
  30. package/components/brand/xertica-provider/XerticaProvider.tsx +48 -48
  31. package/components/brand/xertica-provider/xertica-provider.mdx +61 -61
  32. package/components/brand/xertica-provider/xertica-provider.test.tsx +52 -52
  33. package/components/examples/MapExamples.tsx +282 -282
  34. package/components/examples/SimpleFilterableMap.tsx +191 -191
  35. package/components/examples/index.ts +51 -51
  36. package/components/figma/ImageWithFallback.tsx +27 -27
  37. package/components/hooks/index.ts +10 -7
  38. package/components/hooks/use-layout-shortcuts.ts +46 -0
  39. package/components/index.ts +5 -5
  40. package/components/layout/header/header.test.tsx +8 -8
  41. package/components/layout/header/header.tsx +4 -4
  42. package/components/layout/index.ts +2 -2
  43. package/components/layout/sidebar/sidebar.mdx +1 -1
  44. package/components/layout/sidebar/sidebar.test.tsx +11 -11
  45. package/components/layout/sidebar/sidebar.tsx +1 -31
  46. package/components/layout/sidebar/use-sidebar.ts +2 -11
  47. package/components/media/FloatingMediaWrapper.tsx +11 -11
  48. package/components/media/audio-player/AudioPlayer.tsx +140 -215
  49. package/components/media/audio-player/use-audio-player.ts +298 -0
  50. package/components/media/index.ts +3 -3
  51. package/components/pages/home-content/HomeContent.tsx +7 -7
  52. package/components/pages/home-content/home-content.mdx +62 -62
  53. package/components/pages/home-page/HomePage.stories.tsx +39 -39
  54. package/components/pages/home-page/home-page.mdx +53 -53
  55. package/components/pages/index.ts +8 -8
  56. package/components/pages/template-content/template-content.mdx +61 -61
  57. package/components/pages/template-page/TemplatePage.stories.tsx +39 -39
  58. package/components/pages/template-page/template-page.mdx +53 -53
  59. package/components/public-api-smoke.test.tsx +52 -52
  60. package/components/shared/CustomTooltipContent.tsx +52 -0
  61. package/components/shared/assistant-utils.ts +43 -43
  62. package/components/ui/accordion/accordion.mdx +8 -8
  63. package/components/ui/accordion/accordion.stories.tsx +53 -53
  64. package/components/ui/alert/alert.mdx +8 -8
  65. package/components/ui/alert-dialog/alert-dialog.mdx +8 -8
  66. package/components/ui/aspect-ratio/aspect-ratio.mdx +8 -8
  67. package/components/ui/assistant-chart/assistant-chart.mdx +8 -8
  68. package/components/ui/avatar/avatar.mdx +8 -8
  69. package/components/ui/badge/badge.mdx +8 -8
  70. package/components/ui/badge/badge.tsx +9 -9
  71. package/components/ui/breadcrumb/breadcrumb.mdx +8 -8
  72. package/components/ui/button/button.mdx +8 -8
  73. package/components/ui/calendar/calendar.mdx +8 -8
  74. package/components/ui/calendar/calendar.tsx +258 -258
  75. package/components/ui/card/card.mdx +8 -8
  76. package/components/ui/card/card.stories.tsx +245 -245
  77. package/components/ui/carousel/carousel.mdx +8 -8
  78. package/components/ui/chart/chart.mdx +8 -8
  79. package/components/ui/chart/chart.stories.tsx +1303 -1303
  80. package/components/ui/chart/chart.test.tsx +154 -154
  81. package/components/ui/chart/chart.tsx +2367 -2367
  82. package/components/ui/checkbox/checkbox.mdx +8 -8
  83. package/components/ui/checkbox/checkbox.stories.tsx +20 -20
  84. package/components/ui/collapsible/collapsible.mdx +8 -8
  85. package/components/ui/command/command.mdx +8 -8
  86. package/components/ui/context-menu/context-menu.mdx +8 -8
  87. package/components/ui/dialog/dialog.mdx +8 -8
  88. package/components/ui/drawer/drawer.mdx +8 -8
  89. package/components/ui/dropdown-menu/dropdown-menu.mdx +8 -8
  90. package/components/ui/empty/empty.mdx +8 -8
  91. package/components/ui/file-upload/file-upload.mdx +8 -8
  92. package/components/ui/google-maps-loader/google-maps-loader.tsx +2 -2
  93. package/components/ui/hover-card/hover-card.mdx +8 -8
  94. package/components/ui/input/input.mdx +8 -8
  95. package/components/ui/input-otp/input-otp.mdx +8 -8
  96. package/components/ui/input-otp/input-otp.stories.tsx +6 -6
  97. package/components/ui/label/label.mdx +8 -8
  98. package/components/ui/map/map.mdx +8 -8
  99. package/components/ui/map/map.stories.tsx +51 -51
  100. package/components/ui/map/map.tsx +2 -2
  101. package/components/ui/menubar/menubar.mdx +8 -8
  102. package/components/ui/navigation-menu/navigation-menu.mdx +8 -8
  103. package/components/ui/notification-badge/notification-badge.mdx +8 -8
  104. package/components/ui/pagination/pagination.mdx +8 -8
  105. package/components/ui/popover/popover.mdx +8 -8
  106. package/components/ui/progress/progress.mdx +8 -8
  107. package/components/ui/progress/progress.tsx +68 -68
  108. package/components/ui/radio-group/radio-group.mdx +8 -8
  109. package/components/ui/rating/rating.mdx +8 -8
  110. package/components/ui/resizable/resizable.mdx +8 -8
  111. package/components/ui/route-map/route-map.mdx +8 -8
  112. package/components/ui/route-map/route-map.stories.tsx +54 -54
  113. package/components/ui/route-map/route-map.tsx +2 -2
  114. package/components/ui/scroll-area/scroll-area.mdx +8 -8
  115. package/components/ui/search/search.mdx +8 -8
  116. package/components/ui/select/select.mdx +8 -8
  117. package/components/ui/select/select.stories.tsx +9 -9
  118. package/components/ui/separator/separator.mdx +8 -8
  119. package/components/ui/sheet/sheet.mdx +8 -8
  120. package/components/ui/sheet/sheet.stories.tsx +95 -95
  121. package/components/ui/simple-map/simple-map.mdx +8 -8
  122. package/components/ui/simple-map/simple-map.stories.tsx +48 -48
  123. package/components/ui/skeleton/skeleton.mdx +8 -8
  124. package/components/ui/slider/slider.mdx +8 -8
  125. package/components/ui/sonner/sonner.mdx +8 -8
  126. package/components/ui/stats-card/stats-card.mdx +8 -8
  127. package/components/ui/stepper/stepper.mdx +8 -8
  128. package/components/ui/switch/switch.mdx +8 -8
  129. package/components/ui/switch/switch.stories.tsx +20 -20
  130. package/components/ui/table/table.mdx +8 -8
  131. package/components/ui/tabs/tabs.mdx +8 -8
  132. package/components/ui/tabs/tabs.stories.tsx +26 -26
  133. package/components/ui/textarea/textarea.mdx +8 -8
  134. package/components/ui/timeline/timeline.mdx +8 -8
  135. package/components/ui/toggle/toggle.mdx +8 -8
  136. package/components/ui/toggle-group/toggle-group.mdx +8 -8
  137. package/components/ui/tooltip/tooltip.mdx +8 -8
  138. package/components/ui/tree-view/tree-view.mdx +8 -8
  139. package/components.json +1512 -1512
  140. package/contexts/ApiKeyContext.tsx +72 -72
  141. package/contexts/AssistenteContext.tsx +17 -54
  142. package/contexts/BrandColorsContext.tsx +32 -43
  143. package/contexts/LanguageContext.tsx +13 -13
  144. package/contexts/LayoutContext.test.tsx +11 -11
  145. package/contexts/LayoutContext.tsx +24 -50
  146. package/contexts/ThemeContext.tsx +26 -26
  147. package/contexts/theme-data.ts +4 -4
  148. package/dist/{AssistantChart-DoZCyS5r.cjs → AssistantChart-9w31gdAb.cjs} +4 -4
  149. package/dist/{AssistantChart-CldVCVDe.cjs → AssistantChart-BAudAfne.cjs} +5 -5
  150. package/dist/{use-mobile-DRB3BQgD.cjs → AssistantChart-BAx9VQvb.cjs} +209 -1070
  151. package/dist/{AssistantChart-Cu3m7RBo.js → AssistantChart-BP8upjMk.js} +5 -5
  152. package/dist/{use-mobile-BvYdisLP.js → AssistantChart-CVko2A1W.js} +171 -1025
  153. package/dist/{AssistantChart-C_hwFRRr.js → AssistantChart-CVzmmhx4.js} +4 -4
  154. package/dist/{AudioPlayer-C12BjQBV.cjs → AudioPlayer-1ypwE2Wh.cjs} +126 -187
  155. package/dist/{AudioPlayer-DcFKRJE_.js → AudioPlayer-DuKXrCfy.js} +80 -141
  156. package/dist/CustomTooltipContent-DHjkY0ww.js +40 -0
  157. package/dist/CustomTooltipContent-c_K-DWRr.cjs +56 -0
  158. package/dist/{ThemeContext-BoH4NLfN.js → LanguageContext-BwhwC3G2.js} +27 -104
  159. package/dist/{ThemeContext-r69W20Xg.cjs → LanguageContext-DvUt5jBg.cjs} +27 -104
  160. package/dist/{LayoutContext-BvK-ggDa.cjs → LayoutContext-BDmcZfMH.cjs} +8 -20
  161. package/dist/{LayoutContext-BAql6ZRY.js → LayoutContext-dbQvdC4O.js} +8 -20
  162. package/dist/{ThemeContext-C2EwAPDt.js → ThemeContext-BbBNoFTG.js} +2 -2
  163. package/dist/{ThemeContext-vTjumZeM.cjs → ThemeContext-Cmr8Ex8H.cjs} +2 -2
  164. package/dist/ThemeContext-RTy1m2Uq.js +82 -0
  165. package/dist/ThemeContext-bSzuOit2.cjs +81 -0
  166. package/dist/VerifyEmailPage-BE-L9mB7.js +2828 -0
  167. package/dist/{VerifyEmailPage-Cwi3kbol.cjs → VerifyEmailPage-Bae2cBXT.cjs} +7 -7
  168. package/dist/VerifyEmailPage-CR7kb5df.cjs +2827 -0
  169. package/dist/{VerifyEmailPage-C0c2e5n0.js → VerifyEmailPage-C_ihbcth.js} +6 -6
  170. package/dist/VerifyEmailPage-CbgjOF0v.js +2828 -0
  171. package/dist/{VerifyEmailPage-DvMLZgFt.js → VerifyEmailPage-CdYPSJoO.js} +1 -1
  172. package/dist/{VerifyEmailPage-CYXtbKi3.cjs → VerifyEmailPage-DMBh4NM9.cjs} +1 -1
  173. package/dist/VerifyEmailPage-Dt7zgA4w.cjs +2827 -0
  174. package/dist/{XerticaProvider-CEoWMTxu.js → XerticaProvider-BITjgC5p.js} +2 -2
  175. package/dist/{XerticaProvider-CllrbMEJ.cjs → XerticaProvider-By8q3Roe.cjs} +2 -2
  176. package/dist/{XerticaProvider-cI9hSs27.cjs → XerticaProvider-CW9hpCdF.cjs} +9 -8
  177. package/dist/{XerticaProvider-DDuiIcKo.js → XerticaProvider-siSt9uG2.js} +5 -4
  178. package/dist/{LanguageSelector-D6uacAIM.cjs → XerticaXLogo-D8jf0SNv.cjs} +86 -102
  179. package/dist/{LanguageSelector-B5YfbHra.js → XerticaXLogo-fAJMy3H4.js} +87 -103
  180. package/dist/{alert-dialog-s-vmNkJ_.js → alert-dialog-iDe5VE5o.js} +3 -3
  181. package/dist/{alert-dialog-DSKByiKZ.cjs → alert-dialog-yckpaOpy.cjs} +3 -3
  182. package/dist/assistant.cjs.js +1 -1
  183. package/dist/assistant.es.js +1 -1
  184. package/dist/brand.cjs.js +2 -2
  185. package/dist/brand.es.js +2 -2
  186. package/dist/components/assistant/xertica-assistant/parts/AssistantCollapsedView.d.ts +13 -0
  187. package/dist/components/assistant/xertica-assistant/parts/AssistantConversationList.d.ts +16 -0
  188. package/dist/components/assistant/xertica-assistant/parts/AssistantDocumentEditor.d.ts +17 -0
  189. package/dist/components/assistant/xertica-assistant/parts/AssistantFeedbackDialog.d.ts +19 -0
  190. package/dist/components/assistant/xertica-assistant/parts/AssistantHeader.d.ts +11 -0
  191. package/dist/components/assistant/xertica-assistant/parts/AssistantMessageBubble.d.ts +29 -0
  192. package/dist/components/assistant/xertica-assistant/parts/AssistantTabBar.d.ts +13 -0
  193. package/dist/components/assistant/xertica-assistant/parts/AssistantTypingIndicator.d.ts +4 -0
  194. package/dist/components/assistant/xertica-assistant/parts/AssistantWelcomeScreen.d.ts +17 -0
  195. package/dist/components/assistant/xertica-assistant/parts/index.d.ts +16 -0
  196. package/dist/components/assistant/xertica-assistant/types.d.ts +106 -0
  197. package/dist/components/assistant/xertica-assistant/use-assistant.d.ts +1 -2
  198. package/dist/components/assistant/xertica-assistant/xertica-assistant.d.ts +2 -96
  199. package/dist/components/hooks/index.d.ts +3 -0
  200. package/dist/components/hooks/use-layout-shortcuts.d.ts +22 -0
  201. package/dist/components/media/audio-player/AudioPlayer.d.ts +4 -1
  202. package/dist/components/media/audio-player/use-audio-player.d.ts +72 -0
  203. package/dist/components/shared/CustomTooltipContent.d.ts +20 -0
  204. package/dist/components/ui/alert/alert.d.ts +1 -1
  205. package/dist/components/ui/badge/badge.d.ts +1 -1
  206. package/dist/components/ui/button/button.d.ts +2 -2
  207. package/dist/contexts/AssistenteContext.d.ts +10 -49
  208. package/dist/{google-maps-loader-Y-QkD-Li.cjs → google-maps-loader-BqsYL48U.cjs} +0 -5
  209. package/dist/{google-maps-loader-CTYySAun.js → google-maps-loader-t2IlYBzw.js} +0 -4
  210. package/dist/hooks.cjs.js +30 -10
  211. package/dist/hooks.es.js +25 -4
  212. package/dist/index-CkTUgOwX.js +8 -0
  213. package/dist/{index-COtD8bRW.cjs → index-D3RLKRAs.cjs} +1 -1
  214. package/dist/index.cjs.js +11 -11
  215. package/dist/index.es.js +11 -11
  216. package/dist/index.umd.js +454 -1027
  217. package/dist/layout.cjs.js +3 -10
  218. package/dist/layout.es.js +3 -10
  219. package/dist/media.cjs.js +1 -1
  220. package/dist/media.es.js +1 -1
  221. package/dist/pages.cjs.js +1 -1
  222. package/dist/pages.es.js +1 -1
  223. package/dist/{sidebar-CK_0ZQHj.cjs → sidebar-CVUGHOS_.cjs} +10 -57
  224. package/dist/{sidebar-CUuOvYhK.js → sidebar-CmvwjnVb.js} +10 -40
  225. package/dist/ui.cjs.js +4 -4
  226. package/dist/ui.es.js +4 -4
  227. package/dist/use-audio-player-Bkh23vQ3.js +177 -0
  228. package/dist/use-audio-player-Dn1NR9xN.cjs +176 -0
  229. package/dist/utils/color-utils.d.ts +51 -0
  230. package/dist/{xertica-assistant-dyP7KHM5.cjs → xertica-assistant-B1IaHXnB.cjs} +388 -529
  231. package/dist/xertica-assistant-BMqdyRVi.js +2082 -0
  232. package/dist/xertica-assistant-Bj3vBCq_.cjs +2081 -0
  233. package/dist/{xertica-assistant-yX1CFBBo.js → xertica-assistant-DPsESB6t.js} +390 -531
  234. package/dist/{CodeBlock-BgfYL_rD.cjs → xertica-assistant-Qp3ydksa.cjs} +51 -263
  235. package/dist/{CodeBlock-DnYNI8rQ.js → xertica-assistant-gnCJdcZY.js} +7 -219
  236. package/dist/xertica-ui.css +2 -2
  237. package/docs/architecture-improvements.md +463 -0
  238. package/docs/architecture.md +1 -1
  239. package/docs/components/assistant-chart.md +1 -1
  240. package/docs/components/audio-player.md +46 -0
  241. package/docs/components/branding.md +251 -0
  242. package/docs/components/calendar.md +154 -154
  243. package/docs/components/card-patterns.md +337 -337
  244. package/docs/components/card.md +235 -235
  245. package/docs/components/code-block.md +108 -0
  246. package/docs/components/formatted-document.md +113 -0
  247. package/docs/components/hooks.md +430 -0
  248. package/docs/components/image-with-fallback.md +106 -0
  249. package/docs/components/map-layers.md +140 -0
  250. package/docs/components/map.md +84 -84
  251. package/docs/components/modern-chat-input.md +163 -0
  252. package/docs/components/pages.md +351 -0
  253. package/docs/components/xertica-provider.md +24 -24
  254. package/docs/decision-tree.md +287 -287
  255. package/docs/doc-audit.md +223 -0
  256. package/docs/getting-started.md +154 -0
  257. package/docs/llms.md +25 -5
  258. package/docs/patterns/detail-page.md +276 -0
  259. package/docs/patterns/settings.md +346 -0
  260. package/docs/patterns/wizard.md +217 -0
  261. package/guidelines/Guidelines.md +252 -252
  262. package/hooks/useTheme.ts +3 -3
  263. package/imports/Podcast.tsx +388 -388
  264. package/imports/XerticaAi.tsx +45 -45
  265. package/imports/XerticaX.tsx +19 -19
  266. package/imports/svg-aueiaqngck.ts +11 -11
  267. package/imports/svg-v9krss1ozd.ts +16 -16
  268. package/imports/svg-vhrdofe3qe.ts +5 -5
  269. package/llms-compact.txt +327 -327
  270. package/llms.txt +160 -160
  271. package/package.json +203 -203
  272. package/styles/xertica/app-overrides/chat.css +61 -61
  273. package/styles/xertica/app-overrides/scrollbar.css +33 -33
  274. package/styles/xertica/integrations/google-maps.css +76 -76
  275. package/styles/xertica/integrations/sonner.css +73 -73
  276. package/templates/CLAUDE.md +182 -182
  277. package/templates/guidelines/Guidelines.md +325 -325
  278. package/templates/package.json +2 -2
  279. package/templates/src/features/auth/index.ts +4 -4
  280. package/templates/src/features/auth/ui/AuthPageShell.tsx +34 -34
  281. package/templates/src/features/auth/ui/ForgotPasswordContent.tsx +70 -70
  282. package/templates/src/features/auth/ui/LoginContent.tsx +90 -90
  283. package/templates/src/features/auth/ui/ResetPasswordContent.tsx +151 -151
  284. package/templates/src/features/auth/ui/SocialLoginButtons.tsx +59 -59
  285. package/templates/src/features/auth/ui/VerifyEmailContent.tsx +82 -82
  286. package/templates/src/features/home/index.ts +1 -1
  287. package/templates/src/features/home/ui/HomeContent.tsx +100 -100
  288. package/templates/src/features/template/index.ts +5 -5
  289. package/templates/src/features/template/ui/CrudTemplate.tsx +3 -3
  290. package/templates/src/features/template/ui/DashboardTemplate.tsx +3 -3
  291. package/templates/src/features/template/ui/FormTemplate.tsx +120 -120
  292. package/templates/src/features/template/ui/LoginTemplate.tsx +3 -3
  293. package/templates/src/pages/AssistantPage.tsx +328 -328
  294. package/templates/src/pages/ForgotPasswordPage.tsx +6 -6
  295. package/templates/src/pages/HomePage.tsx +57 -57
  296. package/templates/src/pages/LoginPage.tsx +10 -10
  297. package/templates/src/pages/ResetPasswordPage.tsx +6 -6
  298. package/templates/src/pages/TemplatePage.tsx +30 -30
  299. package/templates/src/pages/VerifyEmailPage.tsx +6 -6
  300. package/templates/src/shared/config/navigation.ts +20 -20
  301. package/templates/src/shared/lib/auth.ts +20 -20
  302. package/templates/src/shared/types/auth.ts +3 -3
  303. package/templates/tsconfig.json +5 -5
  304. package/utils/color-utils.ts +72 -0
  305. package/utils/gemini.ts +140 -140
  306. package/dist/AudioPlayer-B1lt5cPl.cjs +0 -989
  307. package/dist/AudioPlayer-BZ7bibzU.cjs +0 -982
  308. package/dist/AudioPlayer-DMcG_c7L.js +0 -990
  309. package/dist/AudioPlayer-e8LfNoqO.js +0 -983
  310. package/dist/CodeBlock-7TTgmdGG.cjs +0 -2094
  311. package/dist/CodeBlock-BeSt1h5P.js +0 -2078
  312. package/dist/CodeBlock-BlcqlA9M.cjs +0 -2094
  313. package/dist/CodeBlock-Bnmeu5ez.cjs +0 -2094
  314. package/dist/CodeBlock-BtfPlbAI.js +0 -2078
  315. package/dist/CodeBlock-CIySIuYr.js +0 -2078
  316. package/dist/CodeBlock-CuPtUM-7.cjs +0 -2094
  317. package/dist/CodeBlock-D6ffWXgc.js +0 -2078
  318. package/dist/CodeBlock-D8dcwbit.cjs +0 -2094
  319. package/dist/CodeBlock-DMZrFnlw.cjs +0 -2094
  320. package/dist/CodeBlock-DlBehYN8.js +0 -2078
  321. package/dist/CodeBlock-DvKWbSnE.cjs +0 -2094
  322. package/dist/CodeBlock-DwMCfkFY.js +0 -2078
  323. package/dist/CodeBlock-Dy6CNYyj.js +0 -2078
  324. package/dist/CodeBlock-U1pPOQI7.cjs +0 -2094
  325. package/dist/CodeBlock-f_GpNhEB.js +0 -2078
  326. package/dist/CodeBlock-oB6u8nI1.js +0 -2078
  327. package/dist/CodeBlock-tZC31B73.cjs +0 -2094
  328. package/dist/ImageWithFallback-CGtidP6B.cjs +0 -4542
  329. package/dist/ImageWithFallback-lsg3pdFg.js +0 -4508
  330. package/dist/XerticaOrbe-KL1RBHzw.cjs +0 -1354
  331. package/dist/XerticaOrbe-zwS1p2a8.js +0 -1355
  332. package/dist/XerticaProvider-6btlAlzc.js +0 -17
  333. package/dist/XerticaProvider-BNoNOxQ5.cjs +0 -16
  334. package/dist/XerticaProvider-BlY2limY.cjs +0 -38
  335. package/dist/XerticaProvider-hSwhNQex.js +0 -39
  336. package/dist/breadcrumb-CqJ7bHY5.js +0 -161
  337. package/dist/breadcrumb-m9Hb2_XN.cjs +0 -177
  338. package/dist/components/blocks/audio-player/AudioPlayer.d.ts +0 -35
  339. package/dist/components/blocks/audio-player/index.d.ts +0 -1
  340. package/dist/components/blocks/document-editor/DocumentEditor.d.ts +0 -26
  341. package/dist/components/blocks/document-editor/index.d.ts +0 -1
  342. package/dist/components/blocks/podcast-player/PodcastPlayer.d.ts +0 -41
  343. package/dist/components/blocks/podcast-player/index.d.ts +0 -1
  344. package/dist/dropdown-menu-BDB5CmQs.cjs +0 -247
  345. package/dist/dropdown-menu-DQidbKBD.js +0 -231
  346. package/dist/google-maps-loader-BFWp6VPd.js +0 -287
  347. package/dist/google-maps-loader-eS3uQ5TA.cjs +0 -287
  348. package/dist/header-Cgy6vYPk.cjs +0 -731
  349. package/dist/header-DRlT4jgI.js +0 -715
  350. package/dist/header-Dux00SI4.cjs +0 -731
  351. package/dist/header-EkGKXPsD.js +0 -715
  352. package/dist/header-WfEywpyc.cjs +0 -731
  353. package/dist/header-tifNQn2U.js +0 -715
  354. package/dist/index-BhapVLVj.js +0 -8
  355. package/dist/index-D6fxYEY8.cjs +0 -7
  356. package/dist/index-DW5tYe26.js +0 -8
  357. package/dist/input-2R4loU86.js +0 -127
  358. package/dist/input-DWANSKGb.cjs +0 -145
  359. package/dist/rich-text-editor-0mraWT5y.cjs +0 -2376
  360. package/dist/rich-text-editor-B6jMRLzk.cjs +0 -1939
  361. package/dist/rich-text-editor-B8_oYcIR.js +0 -1730
  362. package/dist/rich-text-editor-B9UbSXNb.js +0 -1203
  363. package/dist/rich-text-editor-BYuRBNBU.js +0 -2373
  364. package/dist/rich-text-editor-Bb9pySTs.cjs +0 -2374
  365. package/dist/rich-text-editor-BcL6L3cm.cjs +0 -2374
  366. package/dist/rich-text-editor-BoVZYtTs.cjs +0 -2391
  367. package/dist/rich-text-editor-CPV1lEPH.cjs +0 -1748
  368. package/dist/rich-text-editor-CoKqbCtu.cjs +0 -1799
  369. package/dist/rich-text-editor-Cw56T_mB.js +0 -2356
  370. package/dist/rich-text-editor-Cyt8qs2b.js +0 -1921
  371. package/dist/rich-text-editor-D6H84OcX.cjs +0 -1220
  372. package/dist/rich-text-editor-D76gD-QI.js +0 -2328
  373. package/dist/rich-text-editor-DKkokOnA.js +0 -1781
  374. package/dist/rich-text-editor-DNsdpN64.cjs +0 -2359
  375. package/dist/rich-text-editor-DfG8bCyY.js +0 -2358
  376. package/dist/rich-text-editor-Dxjw31Z4.js +0 -2341
  377. package/dist/rich-text-editor-DzP0Epmb.js +0 -2356
  378. package/dist/rich-text-editor-skplNlBM.cjs +0 -2345
  379. package/dist/select-Bkbr0f-Z.cjs +0 -162
  380. package/dist/select-CvIVdX2n.js +0 -145
  381. package/dist/slider-Bc5Hd0y1.js +0 -56
  382. package/dist/slider-N7hFFj6X.cjs +0 -73
  383. package/dist/tooltip-Ded96neP.cjs +0 -137
  384. package/dist/tooltip-HDOoD2-0.js +0 -120
  385. package/dist/use-mobile-B0hNy_Y6.cjs +0 -4303
  386. package/dist/use-mobile-BXuYROXM.js +0 -4202
  387. package/dist/use-mobile-Bbd51ASU.cjs +0 -4392
  388. package/dist/use-mobile-Bk6CX-TC.js +0 -4359
  389. package/dist/use-mobile-BzuxjzNX.cjs +0 -4392
  390. package/dist/use-mobile-CG2-SdXV.cjs +0 -4235
  391. package/dist/use-mobile-CKb5pqTs.js +0 -4269
  392. package/dist/use-mobile-CYuAuGDl.js +0 -4202
  393. package/dist/use-mobile-CaENcqm-.js +0 -4508
  394. package/dist/use-mobile-CbrYgJGJ.js +0 -4203
  395. package/dist/use-mobile-DMOvImGQ.cjs +0 -4542
  396. package/dist/use-mobile-DZvv7QMR.js +0 -4359
  397. package/dist/use-mobile-DdI_TXam.cjs +0 -4235
  398. package/dist/use-mobile-DlceKf8a.js +0 -4359
  399. package/dist/use-mobile-DsOnow1o.cjs +0 -4236
  400. package/dist/use-mobile-Kcj6jSnK.cjs +0 -4392
  401. package/dist/use-mobile-bnKcua_i.js +0 -4202
  402. package/dist/use-mobile-ncXBeE2z.cjs +0 -4235
  403. package/dist/{rich-text-editor-DgF8s7xW.js → rich-text-editor-BmsjY03B.js} +26 -26
  404. package/dist/{rich-text-editor-mWoaSCE4.cjs → rich-text-editor-GS2kpTAK.cjs} +26 -26
@@ -1,243 +1,59 @@
1
1
  import React from 'react';
2
- import { type MockResponse } from '../../shared/assistant-utils';
3
2
  import { useAssistant } from './use-assistant';
4
3
  import { motion, AnimatePresence } from 'framer-motion';
5
- import {
6
- MessageSquare,
7
- Heart,
8
- History,
9
- MoreHorizontal,
10
- X,
11
- ChevronLeft,
12
- ChevronRight,
13
- PanelRight,
14
- Plus,
15
- Copy,
16
- Check,
17
- FileText,
18
- Music,
19
- Image as ImageIcon,
20
- Radio,
21
- Loader2,
22
- Edit,
23
- Download,
24
- Search,
25
- Folder,
26
- Users,
27
- ExternalLink,
28
- Star,
29
- Clock,
30
- FolderOpen,
31
- Filter,
32
- Mail,
33
- BarChart3,
34
- Bookmark,
35
- Maximize2,
36
- AlertCircle,
37
- ThumbsUp,
38
- ThumbsDown,
39
- Table as TableIcon,
40
- ArrowLeft,
41
- Bold,
42
- Italic,
43
- Underline,
44
- AlignLeft,
45
- AlignCenter,
46
- AlignRight,
47
- List,
48
- Type
49
- } from 'lucide-react';
50
- import {
51
- Bar,
52
- BarChart,
53
- CartesianGrid,
54
- XAxis,
55
- Tooltip as RechartsTooltip,
56
- ResponsiveContainer
57
- } from "recharts";
58
- import {
59
- ChartConfig,
60
- ChartContainer,
61
- ChartTooltip,
62
- ChartTooltipContent,
63
- ChartLegend,
64
- ChartLegendContent
65
- } from '../../ui/chart';
66
- import {
67
- Table,
68
- TableBody,
69
- TableCaption,
70
- TableCell,
71
- TableHead,
72
- TableHeader,
73
- TableRow,
74
- } from '../../ui/table';
75
- import {
76
- Dialog,
77
- DialogContent,
78
- DialogDescription,
79
- DialogFooter,
80
- DialogHeader,
81
- DialogTitle,
82
- } from '../../ui/dialog';
83
- import {
84
- DropdownMenu,
85
- DropdownMenuContent,
86
- DropdownMenuItem,
87
- DropdownMenuTrigger,
88
- } from '../../ui/dropdown-menu';
89
- import { Textarea } from '../../ui/textarea';
90
- import { Button } from '../../ui/button';
91
4
  import { ScrollArea } from '../../ui/scroll-area';
92
- import { Separator } from '../../ui/separator';
93
- import { RichTextEditor } from '../../ui/rich-text-editor';
94
- import { MarkdownMessage } from '../markdown-message';
95
- import { FormattedDocument } from '../formatted-document';
96
5
  import { ModernChatInput } from '../modern-chat-input';
97
- import type { ActionType } from '../modern-chat-input';
98
6
  import { XerticaOrbe } from '../../brand/xertica-orbe';
99
- import { Tooltip, TooltipTrigger } from '../../ui/tooltip';
100
- import * as TooltipPrimitive from '@radix-ui/react-tooltip';
7
+ import { Button } from '../../ui/button';
101
8
  import { cn } from '../../shared/utils';
102
- import { toast } from 'sonner';
103
9
 
104
- // Tooltip customizado estilo sidebar (branco)
105
- function AssistantTooltipContent({
106
- className,
107
- sideOffset = 0,
108
- children,
109
- ...props
110
- }: React.ComponentProps<typeof TooltipPrimitive.Content>) {
111
- return (
112
- <TooltipPrimitive.Portal>
113
- <TooltipPrimitive.Content
114
- data-slot="tooltip-content"
115
- sideOffset={sideOffset}
116
- className={cn(
117
- "bg-popover text-popover-foreground shadow-lg animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
118
- className,
119
- )}
120
- {...props}
121
- >
122
- {children}
123
- <TooltipPrimitive.Arrow
124
- className="fill-popover z-50 drop-shadow-sm"
125
- width={8}
126
- height={4}
127
- />
128
- </TooltipPrimitive.Content>
129
- </TooltipPrimitive.Portal>
130
- );
131
- }
10
+ // Sub-components
11
+ import {
12
+ AssistantCollapsedView,
13
+ AssistantHeader,
14
+ AssistantTabBar,
15
+ AssistantWelcomeScreen,
16
+ AssistantMessageBubble,
17
+ AssistantTypingIndicator,
18
+ AssistantConversationList,
19
+ AssistantFeedbackDialog,
20
+ AssistantDocumentEditor,
21
+ } from './parts';
22
+ import type { EvaluationState } from './parts';
132
23
 
133
24
  // ============================================================================
134
- // TypeScript Interfaces & Types
25
+ // TypeScript Interfaces & Types — imported from shared types.ts and re-exported
26
+ // for backward compatibility with consumers that import from xertica-assistant.
135
27
  // ============================================================================
136
-
137
- /**
138
- * Supported message sender types in the assistant
139
- */
140
- export type MessageType = 'user' | 'assistant' | 'system';
141
-
142
- /**
143
- * Supported attachment types that can be included in messages
144
- */
145
- export type AttachmentType = 'file' | 'audio' | 'image' | 'video' | 'document' | 'podcast' | 'search';
146
-
147
- /**
148
- * Supported search result categories
149
- */
150
- export type SearchResultType = 'document' | 'project' | 'conversation' | 'file' | 'contact';
151
-
152
- /**
153
- * Individual search result item returned by an assistant search query
154
- */
155
- export interface SearchResult {
156
- id: string;
157
- type: SearchResultType;
158
- title: string;
159
- description: string;
160
- path: string;
161
- relevance: number;
162
- lastModified?: string;
163
- }
164
-
165
- /**
166
- * Metadata about a search source (e.g., a document repository or knowledge base)
167
- */
168
- export interface SearchSource {
169
- name: string;
170
- count: number;
171
- }
172
-
173
- /**
174
- * A quick-action command shown below a search result message
175
- */
176
- export interface SearchCommand {
177
- id: string;
178
- icon: string;
179
- label: string;
180
- description: string;
181
- }
182
-
183
- /**
184
- * A single chat message in the assistant conversation
185
- */
186
- export interface Message {
187
- id: string;
188
- type: MessageType;
189
- content: string;
190
- timestamp: Date;
191
- isFavorite?: boolean;
192
- attachmentType?: AttachmentType;
193
- attachmentName?: string;
194
- documentContent?: string;
195
- documentTitle?: string;
196
- audioUrl?: string;
197
- searchResults?: SearchResult[];
198
- searchSources?: SearchSource[];
199
- searchCommands?: SearchCommand[];
200
- chartData?: any[];
201
- chartConfig?: any;
202
- tableData?: {
203
- caption?: string;
204
- headers: string[];
205
- rows: (string | React.ReactNode)[][];
206
- };
207
- evaluation?: 'like' | 'dislike';
208
- evaluationReason?: string;
209
- }
210
-
211
- /**
212
- * A saved conversation entry shown in the history panel
213
- */
214
- export interface Conversation {
215
- id: string;
216
- title: string;
217
- lastMessage?: string;
218
- timestamp: string;
219
- isFavorite: boolean;
220
- messages: Message[];
221
- }
222
-
223
- /**
224
- * A suggested prompt shown to the user in the chat input area
225
- */
226
- export interface Suggestion {
227
- id: string;
228
- text: string;
229
- icon?: React.ReactNode;
230
- }
231
-
232
- /**
233
- * Layout mode for the assistant panel
234
- */
235
- export type AssistantMode = 'collapsed' | 'expanded' | 'fullPage';
236
-
237
- /**
238
- * Available tabs in the assistant panel
239
- */
240
- export type AssistantTab = 'chat' | 'historico' | 'favoritos';
28
+ import type {
29
+ MessageType,
30
+ AttachmentType,
31
+ SearchResultType,
32
+ AssistantMode,
33
+ AssistantTab,
34
+ SearchResult,
35
+ SearchSource,
36
+ SearchCommand,
37
+ Message,
38
+ Conversation,
39
+ Suggestion,
40
+ MockResponse,
41
+ } from './types';
42
+
43
+ export type {
44
+ MessageType,
45
+ AttachmentType,
46
+ SearchResultType,
47
+ AssistantMode,
48
+ AssistantTab,
49
+ SearchResult,
50
+ SearchSource,
51
+ SearchCommand,
52
+ Message,
53
+ Conversation,
54
+ Suggestion,
55
+ MockResponse,
56
+ };
241
57
 
242
58
  // ============================================================================
243
59
  // Component Props
@@ -277,8 +93,6 @@ export interface XerticaAssistantProps {
277
93
  */
278
94
  customResponses?: MockResponse[];
279
95
 
280
-
281
-
282
96
  /**
283
97
  * Callback fired when the user navigates to the settings page
284
98
  */
@@ -510,10 +324,8 @@ export function XerticaAssistant({
510
324
  abaSelecionada,
511
325
  setAbaSelecionada,
512
326
  mensagens,
513
- setMensagens,
514
327
  mensagem,
515
328
  setMensagem,
516
- conversas,
517
329
  conversaAtual,
518
330
  conversasFiltradas,
519
331
  copiedId,
@@ -574,11 +386,12 @@ export function XerticaAssistant({
574
386
  isFullPage
575
387
  ? '100%'
576
388
  : isExpanded
577
- ? (editingDocument ? '420px' : '420px')
389
+ ? '420px'
578
390
  : '80px' // Compacto quando fechado - apenas ícones
579
391
  );
580
392
  const containerHeight = height ?? 'h-full';
581
393
 
394
+ // Mobile floating button — shown when collapsed on mobile
582
395
  if (isMobile && !isExpanded) {
583
396
  return (
584
397
  <Button
@@ -638,193 +451,35 @@ export function XerticaAssistant({
638
451
  >
639
452
  {/* Document Editor Overlay */}
640
453
  {editingDocument && !isFullPage && (
641
- <div
642
- className={cn(
643
- "flex flex-col border-border bg-background overflow-hidden transition-all duration-300",
644
- isMobile ? "fixed inset-0 z-[110] w-full h-[100dvh]" : "absolute top-0 bottom-0 right-full w-[800px] border-l border-r border-border shadow-[-25px_0_50px_-15px_rgba(0,0,0,0.15)] z-[90]"
645
- )}
646
- style={{ maxWidth: isMobile ? 'none' : `calc(100vw - ${containerWidth})` }}
647
- >
648
- <div className="h-full flex flex-col">
649
- {/* Header Toolbar */}
650
- <div className="px-4 h-[64px] border-b border-border bg-card flex items-center justify-between">
651
- <div className="flex items-center gap-3">
652
- <div className="p-2 bg-primary/10 rounded-md">
653
- <FileText className="w-4 h-4 text-primary" />
654
- </div>
655
- <h3 className="font-semibold text-card-foreground text-sm">{editingDocument.title}</h3>
656
- </div>
657
- <Button
658
- variant="ghost"
659
- size="icon"
660
- className="h-8 w-8 rounded-full"
661
- onClick={() => setEditingDocument(null)}
662
- aria-label="Fechar editor de documento"
663
- >
664
- <X className="w-4 h-4" />
665
- </Button>
666
- </div>
667
-
668
- {/* Rich Text Editor */}
669
- <div className="flex-1 bg-muted/20 p-0 sm:p-6 overflow-hidden">
670
- <RichTextEditor
671
- value={editingDocument.content || ''}
672
- onChange={(newVal) => setEditingDocument(editingDocument ? { ...editingDocument, content: newVal } : null)}
673
- placeholder="Comece a digitar o conteúdo do seu documento aqui..."
674
- className="max-w-4xl mx-auto h-full"
675
- actionButton={
676
- <Button size="sm" className="gap-2 h-8">
677
- <Check className="w-3.5 h-3.5" />
678
- Salvar
679
- </Button>
680
- }
681
- />
682
- </div>
683
- </div>
684
- </div>
454
+ <AssistantDocumentEditor
455
+ document={editingDocument}
456
+ isMobile={isMobile}
457
+ containerWidth={containerWidth}
458
+ onClose={() => setEditingDocument(null)}
459
+ onChange={(doc) => setEditingDocument(doc)}
460
+ />
685
461
  )}
686
- {/* Header - Toggle Button - Apenas visível quando não está em fullPage */}
687
- {!isFullPage && (
688
- <div
689
- className={cn(
690
- "border-b border-border flex items-center h-[64px]",
691
- isExpanded ? "justify-between px-4" : "justify-center px-0"
692
- )}
693
- >
694
- {isExpanded && (
695
- <motion.div
696
- initial={{ opacity: 0, x: -10 }}
697
- animate={{ opacity: 1, x: 0 }}
698
- exit={{ opacity: 0, x: -10 }}
699
- className="flex items-center gap-2 overflow-hidden"
700
- >
701
- <div className="flex-shrink-0">
702
- <XerticaOrbe size={32} />
703
- </div>
704
- <span className="text-foreground font-medium truncate">Assistente Xertica</span>
705
- </motion.div>
706
- )}
707
462
 
708
- <div className="flex items-center gap-1">
709
- {isExpanded && onNavigateFullPage && (
710
- <Button
711
- variant="ghost"
712
- size="sm"
713
- onClick={onNavigateFullPage}
714
- className="h-8 w-8 p-0 text-muted-foreground hover:bg-accent hover:text-accent-foreground rounded-full"
715
- title="Expandir assistente"
716
- aria-label="Expandir assistente"
717
- >
718
- <Maximize2 className="w-4 h-4" />
719
- </Button>
720
- )}
721
-
722
- <Button
723
- variant="ghost"
724
- size="sm"
725
- onClick={handleToggle}
726
- className={cn(
727
- "h-8 w-8 p-0 text-muted-foreground hover:bg-accent hover:text-accent-foreground rounded-full",
728
- !isExpanded && "w-10 h-10" // Slightly larger touch target when collapsed if desired, or keep consistent
729
- )}
730
- aria-label={isExpanded ? "Recolher assistente" : "Expandir assistente"}
731
- >
732
- {isExpanded ? (
733
- <ChevronRight className="w-4 h-4" />
734
- ) : (
735
- <PanelRight className="w-4 h-4" />
736
- )}
737
- </Button>
738
- </div>
739
- </div>
463
+ {/* Header only visible when not in fullPage mode */}
464
+ {!isFullPage && (
465
+ <AssistantHeader
466
+ isExpanded={isExpanded}
467
+ onToggle={handleToggle}
468
+ onNavigateFullPage={onNavigateFullPage}
469
+ />
740
470
  )}
741
471
 
742
- {/* Collapsed State - Icons Only */}
472
+ {/* Collapsed State Icons Only */}
743
473
  {!isExpanded && !isFullPage && (
744
- <div className="flex flex-col items-center p-4 space-y-4">
745
- {/* Ícone do Assistente - Xertica Orbe */}
746
- <Tooltip>
747
- <TooltipTrigger asChild>
748
- <button
749
- onClick={handleToggle}
750
- className="w-10 h-10 rounded-full flex items-center justify-center hover:bg-accent/50 transition-colors duration-200 cursor-pointer mx-auto"
751
- aria-label="Abrir assistente"
752
- >
753
- <XerticaOrbe size={32} />
754
- </button>
755
- </TooltipTrigger>
756
- <AssistantTooltipContent
757
- side="left"
758
- sideOffset={8}
759
- >
760
- <p>Assistente Xertica</p>
761
- </AssistantTooltipContent>
762
- </Tooltip>
763
-
764
- <Tooltip>
765
- <TooltipTrigger asChild>
766
- <Button
767
- variant="ghost"
768
- size="sm"
769
- onClick={() => handleExpandWithTab('chat')}
770
- className="w-8 h-8 p-0 text-muted-foreground"
771
- >
772
- <MessageSquare className="w-4 h-4" />
773
- </Button>
774
- </TooltipTrigger>
775
- <AssistantTooltipContent
776
- side="left"
777
- sideOffset={8}
778
- >
779
- <p>Chat</p>
780
- </AssistantTooltipContent>
781
- </Tooltip>
782
-
783
- {showFavorites && (
784
- <Tooltip>
785
- <TooltipTrigger asChild>
786
- <Button
787
- variant="ghost"
788
- size="sm"
789
- onClick={() => handleExpandWithTab('favoritos')}
790
- className="w-8 h-8 p-0 text-muted-foreground"
791
- >
792
- <Heart className="w-4 h-4" />
793
- </Button>
794
- </TooltipTrigger>
795
- <AssistantTooltipContent
796
- side="left"
797
- sideOffset={8}
798
- >
799
- <p>Favoritos</p>
800
- </AssistantTooltipContent>
801
- </Tooltip>
802
- )}
803
-
804
- {showHistory && (
805
- <Tooltip>
806
- <TooltipTrigger asChild>
807
- <Button
808
- variant="ghost"
809
- size="sm"
810
- onClick={() => handleExpandWithTab('historico')}
811
- className="w-8 h-8 p-0 text-muted-foreground"
812
- >
813
- <History className="w-4 h-4" />
814
- </Button>
815
- </TooltipTrigger>
816
- <AssistantTooltipContent
817
- side="left"
818
- sideOffset={8}
819
- >
820
- <p>Histórico</p>
821
- </AssistantTooltipContent>
822
- </Tooltip>
823
- )}
824
- </div>
474
+ <AssistantCollapsedView
475
+ showHistory={showHistory}
476
+ showFavorites={showFavorites}
477
+ onToggle={handleToggle}
478
+ onExpandWithTab={handleExpandWithTab}
479
+ />
825
480
  )}
826
481
 
827
- {/* Expanded State - Full Content */}
482
+ {/* Expanded State Full Content */}
828
483
  <AnimatePresence>
829
484
  {(isExpanded || isFullPage) && (
830
485
  <motion.div
@@ -834,600 +489,61 @@ export function XerticaAssistant({
834
489
  transition={{ duration: 0.2 }}
835
490
  className="flex-1 flex flex-col overflow-hidden"
836
491
  >
837
- {/* Navigation Tabs - Oculto em modo fullPage e quando não abas alternativas */}
492
+ {/* Navigation Tabs hidden in fullPage mode and when no secondary tabs are enabled */}
838
493
  {!isFullPage && (showHistory || showFavorites) && (
839
- <div
840
- className="px-4 py-2 border-b border-border"
841
- >
842
- <div className="flex gap-1">
843
- <Button
844
- variant={abaSelecionada === 'chat' ? 'default' : 'ghost'}
845
- size="sm"
846
- onClick={() => setAbaSelecionada('chat')}
847
- className="flex-1 h-8"
848
- aria-label="Ver chat"
849
- >
850
- <MessageSquare className="w-3 h-3 mr-1" />
851
- Chat
852
- </Button>
853
- {showHistory && (
854
- <Button
855
- variant={abaSelecionada === 'historico' ? 'default' : 'ghost'}
856
- size="sm"
857
- onClick={() => setAbaSelecionada('historico')}
858
- className="flex-1 h-8"
859
- aria-label="Ver histórico de conversas"
860
- >
861
- <History className="w-3 h-3 mr-1" />
862
- Histórico
863
- </Button>
864
- )}
865
- {showFavorites && (
866
- <Button
867
- variant={abaSelecionada === 'favoritos' ? 'default' : 'ghost'}
868
- size="sm"
869
- onClick={() => setAbaSelecionada('favoritos')}
870
- className="flex-1 h-8"
871
- aria-label="Ver mensagens favoritas"
872
- >
873
- <Heart className="w-3 h-3 mr-1" />
874
- Favoritos
875
- </Button>
876
- )}
877
- </div>
878
- </div>
494
+ <AssistantTabBar
495
+ activeTab={abaSelecionada}
496
+ showHistory={showHistory}
497
+ showFavorites={showFavorites}
498
+ onTabChange={setAbaSelecionada}
499
+ />
879
500
  )}
880
501
 
881
502
  {/* Content Area */}
882
503
  <div className="flex-1 overflow-hidden flex flex-col">
504
+
505
+ {/* Chat Tab */}
883
506
  {abaSelecionada === 'chat' && (
884
507
  <div className={`flex-1 flex flex-col min-h-0 ${isFullPage ? 'mx-auto w-full max-w-6xl' : ''}`}>
885
- {/* API Key Warning Banner */}
886
-
887
-
888
508
  {mensagens.length === 0 ? (
889
- <div className="flex-1 overflow-y-auto min-h-0">
890
- {/* Welcome Message */}
891
- <div className="p-6 text-center">
892
- <div className="mx-auto mb-4 flex items-center justify-center">
893
- <XerticaOrbe size={64} />
894
- </div>
895
- <h3 className="mb-2 text-foreground">
896
- Olá, {userName}
897
- </h3>
898
- <p className="text-muted-foreground">
899
- {welcomeMessage}
900
- </p>
901
- </div>
902
-
903
- {/* Suggestions */}
904
- {(sugestoes.length > 0 || richSuggestions.length > 0) && (
905
- <div className="px-4 pb-4 space-y-2">
906
- {sugestoes.map((sugestao) => (
907
- <button
908
- key={sugestao.id}
909
- onClick={() => handleEnviarMensagem(sugestao.text)}
910
- className="w-full p-3 text-left rounded-[var(--radius-card)] bg-muted text-foreground transition-colors duration-200 hover:bg-muted/80"
911
- >
912
- {sugestao.text}
913
- </button>
914
- ))}
915
-
916
- {richSuggestions.length > 0 && (
917
- !showMoreSuggestions ? (
918
- <Button
919
- variant="ghost"
920
- size="sm"
921
- onClick={() => setShowMoreSuggestions(true)}
922
- className="w-full justify-start text-muted-foreground"
923
- >
924
- <MoreHorizontal className="w-4 h-4 mr-2" />
925
- Mais sugestões
926
- </Button>
927
- ) : (
928
- <div className="space-y-2 pt-2 border-t border-border mt-2 animate-in slide-in-from-top-2">
929
- {richSuggestions.map((sugestao) => (
930
- <button
931
- key={sugestao.id}
932
- onClick={() => handleRichSuggestionClick(sugestao)}
933
- className="w-full p-3 text-left rounded-[var(--radius-card)] bg-muted/50 border border-border text-foreground transition-all duration-200 hover:bg-primary/5 hover:border-primary/50 group"
934
- >
935
- <div className="flex items-center gap-2">
936
- {sugestao.id.includes('chart') && <BarChart3 className="w-4 h-4 text-primary" />}
937
- {sugestao.id.includes('table') && <TableIcon className="w-4 h-4 text-primary" />}
938
- <span className="font-medium">{sugestao.text}</span>
939
- </div>
940
- </button>
941
- ))}
942
- <Button
943
- variant="ghost"
944
- size="sm"
945
- onClick={() => setShowMoreSuggestions(false)}
946
- className="w-full justify-center text-muted-foreground mt-2"
947
- >
948
- <ChevronLeft className="w-4 h-4 mr-2" />
949
- Voltar
950
- </Button>
951
- </div>
952
- )
953
- )}
954
- </div>
955
- )}
956
- </div>
509
+ <AssistantWelcomeScreen
510
+ userName={userName}
511
+ welcomeMessage={welcomeMessage}
512
+ suggestions={sugestoes}
513
+ richSuggestions={richSuggestions}
514
+ showMoreSuggestions={showMoreSuggestions}
515
+ onSetShowMoreSuggestions={setShowMoreSuggestions}
516
+ onSendSuggestion={handleEnviarMensagem}
517
+ onRichSuggestionClick={handleRichSuggestionClick}
518
+ />
957
519
  ) : (
958
520
  <ScrollArea className="flex-1 min-h-0 overflow-x-hidden [&_[data-radix-scroll-area-viewport]>div]:!block">
959
521
  <div className="space-y-4 px-4 py-4 max-w-6xl mx-auto !block !w-full">
960
522
  {mensagens.map((msg) => (
961
- <motion.div
523
+ <AssistantMessageBubble
962
524
  key={msg.id}
963
- initial={{ opacity: 0, y: 10 }}
964
- animate={{ opacity: 1, y: 0 }}
965
- className={`flex gap-2 w-full min-w-0 ${msg.type === 'user' ? 'justify-end' : 'justify-start'}`}
966
- >
967
- {/* Avatar do Assistente */}
968
- {msg.type === 'assistant' && (
969
- <div className="flex-shrink-0 pt-1">
970
- <XerticaOrbe size={32} />
971
- </div>
972
- )}
973
-
974
- <div className={cn(
975
- "flex flex-col min-w-0 transition-all duration-300",
976
- msg.type === 'user'
977
- ? "max-w-[85%] md:max-w-[70%] items-end w-fit"
978
- : cn(
979
- "items-start",
980
- (msg.tableData || msg.chartData || msg.searchResults || msg.attachmentType === 'document')
981
- ? "w-full max-w-full"
982
- : "w-fit max-w-[95%] md:max-w-[90%]"
983
- )
984
- )}>
985
- <div
986
- className={cn(
987
- "px-4 py-2 break-words overflow-hidden overflow-x-hidden w-full min-w-0 rounded-2xl",
988
- msg.type === 'user'
989
- ? "bg-primary text-primary-foreground shadow-sm"
990
- : "bg-muted text-foreground"
991
- )}
992
- >
993
- {/* Document Header with Edit and Download Buttons */}
994
- {msg.attachmentType === 'document' && (
995
- <div
996
- className="flex items-center justify-between mb-2 pb-2 border-b border-border min-w-0 overflow-hidden"
997
- >
998
- <div className="flex items-center gap-2 min-w-0 flex-1 overflow-hidden">
999
- <FileText className="w-4 h-4 flex-shrink-0" />
1000
- <span className="text-sm font-medium break-words">{msg.attachmentName}</span>
1001
- </div>
1002
- <div className="flex items-center gap-1 flex-shrink-0">
1003
- <Button
1004
- variant="ghost"
1005
- size="sm"
1006
- onClick={() => msg.documentContent && msg.attachmentName && handleDownloadDocument(msg.documentContent, msg.attachmentName)}
1007
- className="h-6 px-2"
1008
- title="Baixar"
1009
- >
1010
- <Download className="w-3 h-3" />
1011
- </Button>
1012
- <Button
1013
- variant="ghost"
1014
- size="sm"
1015
- onClick={() => msg.documentContent && msg.documentTitle && handleEditDocument(msg.documentContent, msg.documentTitle)}
1016
- className="h-6 px-2"
1017
- >
1018
- <Edit className="w-3 h-3 mr-1" />
1019
- Editar
1020
- </Button>
1021
- </div>
1022
- </div>
1023
- )}
1024
-
1025
- {/* Attachments */}
1026
- {msg.attachmentType && msg.attachmentType !== 'podcast' && msg.attachmentType !== 'document' && (
1027
- <div
1028
- className="flex items-center gap-2 mb-2 pb-2 border-b border-border min-w-0 overflow-hidden"
1029
- >
1030
- {msg.attachmentType === 'file' && <FileText className="w-4 h-4 flex-shrink-0" />}
1031
- {msg.attachmentType === 'audio' && <Music className="w-4 h-4 flex-shrink-0" />}
1032
- {msg.attachmentType === 'image' && <ImageIcon className="w-4 h-4 flex-shrink-0" />}
1033
- <span className="text-small break-words">{msg.attachmentName}</span>
1034
- </div>
1035
- )}
1036
-
1037
- {/* Message Content */}
1038
- {msg.type === 'user' ? (
1039
- <p className="whitespace-pre-wrap break-words">{msg.content}</p>
1040
- ) : (
1041
- <>
1042
- {(msg.content.includes('🔐') || msg.content.includes('❌')) && (
1043
- <div
1044
- className="mb-3 p-3 border rounded-[var(--radius)] overflow-hidden bg-[var(--toast-error-bg)]/20 border-[var(--toast-error-border)]/30"
1045
- >
1046
- <div className="flex items-start gap-2 min-w-0">
1047
- <AlertCircle className="w-5 h-5 flex-shrink-0 mt-0.5 text-[var(--toast-error-icon)]" />
1048
- <div className="flex-1 min-w-0 overflow-hidden">
1049
- <MarkdownMessage
1050
- content={msg.content}
1051
- className="text-foreground"
1052
- />
1053
- </div>
1054
- </div>
1055
- </div>
1056
- )}
1057
- {!(msg.content.includes('🔐') || msg.content.includes('❌')) && (
1058
- <MarkdownMessage
1059
- content={msg.content}
1060
- className="text-foreground"
1061
- />
1062
- )}
1063
- </>
1064
- )}
1065
-
1066
- {/* Chart Rendering */}
1067
- {msg.chartData && msg.chartConfig && (
1068
- <div className="mt-4 w-full h-[300px] min-w-[300px]">
1069
- <ChartContainer config={msg.chartConfig} className="h-full w-full">
1070
- <BarChart accessibilityLayer data={msg.chartData}>
1071
- <CartesianGrid vertical={false} />
1072
- <XAxis
1073
- dataKey="month"
1074
- tickLine={false}
1075
- tickMargin={10}
1076
- axisLine={false}
1077
- tickFormatter={(value) => value.slice(0, 3)}
1078
- />
1079
- <ChartTooltip content={<ChartTooltipContent />} />
1080
- <ChartLegend content={<ChartLegendContent />} />
1081
- {Object.keys(msg.chartConfig).map((key) => (
1082
- <Bar key={key} dataKey={key} fill={`var(--color-${key})`} radius={4} />
1083
- ))}
1084
- </BarChart>
1085
- </ChartContainer>
1086
- </div>
1087
- )}
1088
-
1089
- {/* Table Rendering */}
1090
- {msg.tableData && (
1091
- <div className="mt-4 w-full max-w-full border rounded-[var(--radius)] overflow-x-auto custom-scrollbar relative">
1092
- <Table>
1093
- {msg.tableData.caption && <TableCaption>{msg.tableData.caption}</TableCaption>}
1094
- <TableHeader>
1095
- <TableRow>
1096
- {msg.tableData.headers.map((header, i) => (
1097
- <TableHead key={i}>{header}</TableHead>
1098
- ))}
1099
- </TableRow>
1100
- </TableHeader>
1101
- <TableBody>
1102
- {msg.tableData.rows.map((row, i) => (
1103
- <TableRow key={i}>
1104
- {row.map((cell, j) => (
1105
- <TableCell key={j}>{cell}</TableCell>
1106
- ))}
1107
- </TableRow>
1108
- ))}
1109
- </TableBody>
1110
- </Table>
1111
- </div>
1112
- )}
1113
-
1114
- {/* Document Preview */}
1115
- {msg.attachmentType === 'document' && msg.documentContent && (
1116
- <div
1117
- className="mt-3 pt-3 border-t border-border overflow-hidden"
1118
- >
1119
- <FormattedDocument
1120
- content={msg.documentContent}
1121
- maxPreviewLength={250}
1122
- />
1123
- </div>
1124
- )}
1125
-
1126
- {/* Podcast Player */}
1127
- {msg.attachmentType === 'podcast' && msg.audioUrl && (
1128
- <div
1129
- className="mt-3 pt-3 border-t border-border overflow-hidden"
1130
- >
1131
- <div className="flex items-center justify-between mb-3 min-w-0 overflow-hidden">
1132
- <div className="flex items-center gap-2 min-w-0 flex-1 overflow-hidden">
1133
- <div
1134
- className="w-6 h-6 flex items-center justify-center flex-shrink-0 rounded-[var(--radius-button)] bg-gradient-to-br from-[var(--chart-1)] via-[var(--chart-4)] to-[var(--chart-1)]"
1135
- >
1136
- <Radio className="w-3 h-3 text-white" />
1137
- </div>
1138
- <span className="text-sm font-medium break-words">
1139
- {msg.attachmentName}
1140
- </span>
1141
- </div>
1142
- <Button
1143
- variant="ghost"
1144
- size="sm"
1145
- onClick={() => msg.audioUrl && msg.attachmentName && handleDownloadPodcast(msg.audioUrl, msg.attachmentName)}
1146
- className="h-6 px-2 flex-shrink-0"
1147
- title="Baixar"
1148
- >
1149
- <Download className="w-3 h-3" />
1150
- </Button>
1151
- </div>
1152
- <div
1153
- className="rounded-[var(--radius)] p-2 overflow-hidden bg-gradient-to-r from-[var(--chart-1)]/10 to-[var(--chart-4)]/10"
1154
- >
1155
- <audio
1156
- controls
1157
- className="w-full max-w-full h-10 outline-none"
1158
- >
1159
- <source src={msg.audioUrl} type="audio/mpeg" />
1160
- Seu navegador não suporta o elemento de áudio.
1161
- </audio>
1162
- </div>
1163
- </div>
1164
- )}
1165
-
1166
- {/* Search Results */}
1167
- {msg.attachmentType === 'search' && msg.searchResults && (
1168
- <div
1169
- className="mt-3 pt-3 border-t border-border space-y-4 overflow-hidden"
1170
- >
1171
- <div className="overflow-hidden">
1172
- <div className="flex items-center gap-2 mb-3">
1173
- <Search className="w-4 h-4 text-[var(--chart-4)]" />
1174
- <h4 className="text-foreground">
1175
- Resultados Encontrados ({msg.searchResults.length})
1176
- </h4>
1177
- </div>
1178
- <div className="space-y-2 overflow-hidden">
1179
- {msg.searchResults.map((result) => (
1180
- <div
1181
- key={result.id}
1182
- onClick={() => handleOpenSearchResult(result)}
1183
- className="p-3 rounded-[var(--radius)] border border-border transition-all cursor-pointer group overflow-hidden hover:bg-muted/50"
1184
- >
1185
- <div className="flex items-start justify-between gap-2 min-w-0">
1186
- <div className="flex items-start gap-2 flex-1 min-w-0 overflow-hidden">
1187
- <div className="mt-0.5 flex-shrink-0">
1188
- {result.type === 'document' && <FileText className="w-4 h-4 text-[var(--chart-4)]" />}
1189
- {result.type === 'project' && <FolderOpen className="w-4 h-4 text-[var(--chart-1)]" />}
1190
- {result.type === 'conversation' && <MessageSquare className="w-4 h-4 text-[var(--chart-2)]" />}
1191
- {result.type === 'file' && <Folder className="w-4 h-4 text-[var(--chart-3)]" />}
1192
- {result.type === 'contact' && <Users className="w-4 h-4 text-[var(--chart-5)]" />}
1193
- </div>
1194
- <div className="flex-1 min-w-0 overflow-hidden">
1195
- <div className="flex items-start gap-2 min-w-0">
1196
- <h5 className="text-sm font-medium break-words flex-1 min-w-0 text-foreground">
1197
- {result.title}
1198
- </h5>
1199
- <span
1200
- className="px-1.5 py-0.5 rounded-sm flex-shrink-0 self-start bg-[var(--chart-4)]/10 text-[var(--chart-4)]"
1201
- >
1202
- {result.relevance}%
1203
- </span>
1204
- </div>
1205
- <p className="text-sm text-muted-foreground mt-1 line-clamp-2 break-words">
1206
- {result.description}
1207
- </p>
1208
- <div className="flex items-center gap-3 mt-2 flex-wrap min-w-0">
1209
- <span className="text-sm text-muted-foreground flex items-center gap-1 min-w-0 max-w-full">
1210
- <ExternalLink className="w-3 h-3 flex-shrink-0" />
1211
- <span className="truncate">{result.path}</span>
1212
- </span>
1213
- {result.lastModified && (
1214
- <span className="text-sm text-muted-foreground flex items-center gap-1 flex-shrink-0">
1215
- <Clock className="w-3 h-3" />
1216
- {result.lastModified}
1217
- </span>
1218
- )}
1219
- </div>
1220
- </div>
1221
- </div>
1222
- </div>
1223
- </div>
1224
- ))}
1225
- </div>
1226
- </div>
1227
-
1228
- {/* Search Sources */}
1229
- {msg.searchSources && (
1230
- <div>
1231
- <h4 className="mb-2 text-foreground">
1232
- Fontes Consultadas
1233
- </h4>
1234
- <div className="flex flex-wrap gap-2 overflow-hidden">
1235
- {msg.searchSources.map((source, index) => (
1236
- <div
1237
- key={index}
1238
- className="px-3 py-1.5 border max-w-full rounded-[var(--radius-button)] bg-muted border-border"
1239
- >
1240
- <span className="text-sm font-medium text-foreground break-words">{source.name}</span>
1241
- <span className="text-sm text-muted-foreground ml-1 whitespace-nowrap">({source.count})</span>
1242
- </div>
1243
- ))}
1244
- </div>
1245
- </div>
1246
- )}
1247
-
1248
- {/* Search Commands */}
1249
- {msg.searchCommands && msg.searchResults && (
1250
- <div>
1251
- <h4 className="mb-2 text-foreground">
1252
- O que você pode fazer com estes resultados
1253
- </h4>
1254
- <div className="grid grid-cols-1 gap-2">
1255
- {msg.searchCommands.map((command) => (
1256
- <button
1257
- key={command.id}
1258
- onClick={() => handleExecuteSearchCommand(
1259
- command.id,
1260
- msg.content.replace('🔍 Pesquisa realizada com sucesso!', '').split('"')[1] || 'pesquisa',
1261
- msg.searchResults!,
1262
- msg.id
1263
- )}
1264
- disabled={executingCommand === command.id}
1265
- className={cn(
1266
- "flex items-start gap-2 p-2 rounded-[var(--radius)] border transition-all text-left disabled:opacity-50 disabled:cursor-not-allowed",
1267
- savedSearches.includes(msg.id) && command.id === '5'
1268
- ? "border-[var(--toast-warning-border)] bg-[var(--toast-warning-bg)]/20"
1269
- : "border-border bg-transparent hover:bg-muted/50"
1270
- )}
1271
- >
1272
- {executingCommand === command.id ? (
1273
- <Loader2 className="w-5 h-5 animate-spin flex-shrink-0 text-primary" />
1274
- ) : (
1275
- <span className="flex-shrink-0">{command.icon}</span>
1276
- )}
1277
- <div className="flex-1 min-w-0 overflow-hidden">
1278
- <div className="text-sm font-medium text-foreground break-words">
1279
- {command.id === '5' && savedSearches.includes(msg.id) ? '⭐ Pesquisa salva' : command.label}
1280
- </div>
1281
- <div className="text-sm text-muted-foreground break-words">
1282
- {executingCommand === command.id ? 'Processando...' : command.description}
1283
- </div>
1284
- </div>
1285
- </button>
1286
- ))}
1287
- </div>
1288
- </div>
1289
- )}
1290
- </div>
1291
- )}
1292
- </div>
1293
-
1294
- {/* Message Actions */}
1295
- <div className="flex items-center gap-2 mt-1 px-2">
1296
- <span className="text-sm text-muted-foreground">
1297
- {msg.timestamp.toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' })}
1298
- </span>
1299
-
1300
-
1301
- {enablePodcastGeneration && msg.type === 'assistant' && msg.attachmentType !== 'podcast' && (
1302
- <Button
1303
- variant="ghost"
1304
- size="sm"
1305
- onClick={() => handleGeneratePodcast(msg.id, msg.content)}
1306
- disabled={generatingPodcastId === msg.id}
1307
- className="h-6 w-6 p-0 disabled:opacity-50 text-muted-foreground"
1308
- title="Gerar Podcast"
1309
- aria-label="Gerar Podcast"
1310
- >
1311
- {generatingPodcastId === msg.id ? (
1312
- <Loader2 className="w-3 h-3 animate-spin" />
1313
- ) : (
1314
- <Radio className="w-3 h-3" />
1315
- )}
1316
- </Button>
1317
- )}
1318
-
1319
- {msg.type === 'assistant' && (
1320
- <div className="flex items-center gap-1 border-l border-border pl-2 ml-1">
1321
- <Button
1322
- variant="ghost"
1323
- size="icon"
1324
- className={cn(
1325
- "h-6 w-6 rounded-full hover:bg-green-100 dark:hover:bg-green-900/20 hover:text-green-600",
1326
- msg.evaluation === 'like' && "text-green-600 bg-green-100 dark:bg-green-900/20"
1327
- )}
1328
- onClick={() => handleEvaluationClick(msg.id, 'like')}
1329
- title="Gostei"
1330
- aria-label="Gostei"
1331
- >
1332
- <ThumbsUp className="h-3.5 w-3.5" />
1333
- </Button>
1334
-
1335
- <DropdownMenu>
1336
- <DropdownMenuTrigger asChild>
1337
- <Button
1338
- variant="ghost"
1339
- size="icon"
1340
- className={cn(
1341
- "h-6 w-6 rounded-full hover:bg-red-100 dark:hover:bg-red-900/20 hover:text-red-600",
1342
- msg.evaluation === 'dislike' && "text-red-600 bg-red-100 dark:bg-red-900/20"
1343
- )}
1344
- title="Não gostei"
1345
- aria-label="Não gostei"
1346
- >
1347
- <ThumbsDown className="h-3.5 w-3.5" />
1348
- </Button>
1349
- </DropdownMenuTrigger>
1350
- <DropdownMenuContent align="start">
1351
- {feedbackOptions && feedbackOptions.length > 0 ? (
1352
- feedbackOptions.map((option, idx) => (
1353
- <DropdownMenuItem key={idx} onClick={() => openFeedbackDialog(msg.id, option)}>
1354
- {option}
1355
- </DropdownMenuItem>
1356
- ))
1357
- ) : (
1358
- <>
1359
- <DropdownMenuItem onClick={() => openFeedbackDialog(msg.id, 'Não era o que eu procurava')}>
1360
- Não era o que eu procurava
1361
- </DropdownMenuItem>
1362
- <DropdownMenuItem onClick={() => openFeedbackDialog(msg.id, 'Informação incorreta')}>
1363
- Informação incorreta
1364
- </DropdownMenuItem>
1365
- <DropdownMenuItem onClick={() => openFeedbackDialog(msg.id, 'Resposta incompleta')}>
1366
- Resposta incompleta
1367
- </DropdownMenuItem>
1368
- </>
1369
- )}
1370
- <DropdownMenuItem onClick={() => openFeedbackDialog(msg.id, null)}>
1371
- Outros...
1372
- </DropdownMenuItem>
1373
- </DropdownMenuContent>
1374
- </DropdownMenu>
1375
- </div>
1376
- )}
1377
-
1378
- <Button
1379
- variant="ghost"
1380
- size="sm"
1381
- onClick={() => handleCopyMessage(msg.content, msg.id)}
1382
- className={`h-6 w-6 p-0 ${copiedId === msg.id ? 'text-[var(--toast-success-icon)]' : 'text-muted-foreground'}`}
1383
- aria-label={copiedId === msg.id ? "Copiado" : "Copiar mensagem"}
1384
- >
1385
- {copiedId === msg.id ? (
1386
- <Check className="w-3 h-3" />
1387
- ) : (
1388
- <Copy className="w-3 h-3" />
1389
- )}
1390
- </Button>
1391
- </div>
1392
- </div>
1393
- </motion.div>
525
+ msg={msg}
526
+ copiedId={copiedId}
527
+ generatingPodcastId={generatingPodcastId}
528
+ executingCommand={executingCommand}
529
+ savedSearches={savedSearches}
530
+ enablePodcastGeneration={enablePodcastGeneration}
531
+ feedbackOptions={feedbackOptions}
532
+ onCopyMessage={handleCopyMessage}
533
+ onToggleFavorite={handleToggleFavorite}
534
+ onGeneratePodcast={handleGeneratePodcast}
535
+ onDownloadDocument={handleDownloadDocument}
536
+ onDownloadPodcast={handleDownloadPodcast}
537
+ onEditDocument={handleEditDocument}
538
+ onOpenSearchResult={handleOpenSearchResult}
539
+ onExecuteSearchCommand={handleExecuteSearchCommand}
540
+ onEvaluationClick={handleEvaluationClick}
541
+ onOpenFeedbackDialog={openFeedbackDialog}
542
+ />
1394
543
  ))}
1395
544
 
1396
545
  {/* Typing Indicator */}
1397
- {isProcessing && (
1398
- <motion.div
1399
- initial={{ opacity: 0, y: 10 }}
1400
- animate={{ opacity: 1, y: 0 }}
1401
- className="flex gap-2 justify-start"
1402
- >
1403
- {/* Avatar do Assistente */}
1404
- <div className="flex-shrink-0 pt-1">
1405
- <XerticaOrbe size={32} />
1406
- </div>
1407
-
1408
- <div
1409
- className="px-4 py-3 bg-muted rounded-2xl"
1410
- >
1411
- <div className="flex gap-1">
1412
- <motion.div
1413
- className="w-2 h-2 rounded-full bg-muted-foreground"
1414
- animate={{ y: [0, -8, 0] }}
1415
- transition={{ repeat: Infinity, duration: 0.6, delay: 0 }}
1416
- />
1417
- <motion.div
1418
- className="w-2 h-2 rounded-full bg-muted-foreground"
1419
- animate={{ y: [0, -8, 0] }}
1420
- transition={{ repeat: Infinity, duration: 0.6, delay: 0.2 }}
1421
- />
1422
- <motion.div
1423
- className="w-2 h-2 rounded-full bg-muted-foreground"
1424
- animate={{ y: [0, -8, 0] }}
1425
- transition={{ repeat: Infinity, duration: 0.6, delay: 0.4 }}
1426
- />
1427
- </div>
1428
- </div>
1429
- </motion.div>
1430
- )}
546
+ {isProcessing && <AssistantTypingIndicator />}
1431
547
 
1432
548
  <div ref={messagesEndRef} />
1433
549
  </div>
@@ -1436,82 +552,21 @@ export function XerticaAssistant({
1436
552
  </div>
1437
553
  )}
1438
554
 
555
+ {/* History / Favorites Tab */}
1439
556
  {((abaSelecionada === 'historico' && showHistory) || (abaSelecionada === 'favoritos' && showFavorites)) && (
1440
- <ScrollArea className="flex-1 min-h-0">
1441
- <div className={`p-4 ${isFullPage ? 'mx-auto w-full max-w-6xl' : ''}`}>
1442
- {/* New Conversation Button */}
1443
- <Button
1444
- variant="outline"
1445
- size="sm"
1446
- onClick={handleNovaConversa}
1447
- className="w-full mb-4 justify-start"
1448
- >
1449
- <Plus className="w-4 h-4 mr-2" />
1450
- Nova Conversa
1451
- </Button>
1452
-
1453
- {/* Conversations List */}
1454
- <div className="space-y-2">
1455
- {conversasFiltradas.length === 0 ? (
1456
- <div className="text-center py-8">
1457
- <Heart className="w-12 h-12 mx-auto text-muted-foreground/50 mb-2" />
1458
- <p className="text-muted-foreground">
1459
- {abaSelecionada === 'favoritos'
1460
- ? 'Nenhuma conversa favorita ainda'
1461
- : 'Nenhuma conversa no histórico'}
1462
- </p>
1463
- </div>
1464
- ) : (
1465
- conversasFiltradas.map((conversa) => (
1466
- <div
1467
- key={conversa.id}
1468
- onClick={() => handleSelecionarConversa(conversa.id)}
1469
- className={cn(
1470
- "p-3 rounded-[var(--radius)] cursor-pointer transition-colors duration-200 border",
1471
- conversa.id === conversaAtual
1472
- ? "border-primary bg-primary/10"
1473
- : "border-border hover:bg-muted"
1474
- )}
1475
- >
1476
- <div className="flex items-start justify-between mb-1">
1477
- <h4 className="text-sm font-medium text-foreground truncate flex-1">
1478
- {conversa.title}
1479
- </h4>
1480
- <Button
1481
- variant="ghost"
1482
- size="sm"
1483
- onClick={(e) => {
1484
- e.stopPropagation();
1485
- handleToggleFavoritaConversa(conversa.id);
1486
- }}
1487
- className="h-6 w-6 p-0 flex-shrink-0 ml-1"
1488
- >
1489
- <Heart
1490
- className={cn(
1491
- "w-3 h-3",
1492
- conversa.isFavorite ? "text-destructive fill-current" : "text-muted-foreground"
1493
- )}
1494
- />
1495
- </Button>
1496
- </div>
1497
- {conversa.lastMessage && (
1498
- <p className="text-sm text-muted-foreground truncate mb-1">
1499
- {conversa.lastMessage}
1500
- </p>
1501
- )}
1502
- <p className="text-sm text-muted-foreground">
1503
- {conversa.timestamp}
1504
- </p>
1505
- </div>
1506
- ))
1507
- )}
1508
- </div>
1509
- </div>
1510
- </ScrollArea>
557
+ <AssistantConversationList
558
+ conversations={conversasFiltradas}
559
+ currentConversationId={conversaAtual}
560
+ activeTab={abaSelecionada}
561
+ isFullPage={isFullPage}
562
+ onNewConversation={handleNovaConversa}
563
+ onSelectConversation={handleSelecionarConversa}
564
+ onToggleFavorite={handleToggleFavoritaConversa}
565
+ />
1511
566
  )}
1512
567
  </div>
1513
568
 
1514
- {/* Modern Input Area - Only visible in chat mode */}
569
+ {/* Modern Input Area only visible in chat mode */}
1515
570
  {abaSelecionada === 'chat' && (
1516
571
  <ModernChatInput
1517
572
  value={mensagem}
@@ -1535,38 +590,12 @@ export function XerticaAssistant({
1535
590
  </div>
1536
591
 
1537
592
  {/* Feedback Dialog */}
1538
- <Dialog open={evaluationState.isOpen} onOpenChange={(open) => !open && setEvaluationState(prev => ({ ...prev, isOpen: false }))}>
1539
- <DialogContent className="sm:max-w-[600px]">
1540
- <DialogHeader>
1541
- <DialogTitle className="pr-8">
1542
- {evaluationState.category ? `Enviar feedback: ${evaluationState.category}` : 'Enviar feedback'}
1543
- </DialogTitle>
1544
- <DialogDescription>
1545
- {evaluationState.category
1546
- ? "Gostaria de adicionar algum comentário? (Opcional)"
1547
- : "Conte-nos por que essa resposta não foi útil para que possamos melhorar."}
1548
- </DialogDescription>
1549
- </DialogHeader>
1550
- <div className="grid gap-4 py-4 px-6">
1551
- <Textarea
1552
- className="min-h-[100px]"
1553
- placeholder={evaluationState.category ? "Comentário adicional..." : "Descreva o motivo..."}
1554
- aria-label={evaluationState.category ? "Comentário adicional" : "Descreva o motivo"}
1555
- value={evaluationState.reason}
1556
- onChange={(e) => setEvaluationState(prev => ({ ...prev, reason: e.target.value }))}
1557
- rows={4}
1558
- />
1559
- </div>
1560
- <DialogFooter>
1561
- <Button variant="outline" onClick={() => setEvaluationState(prev => ({ ...prev, isOpen: false }))}>
1562
- Cancelar
1563
- </Button>
1564
- <Button onClick={handleSubmitDislike} disabled={!evaluationState.category && !evaluationState.reason.trim()}>
1565
- {evaluationState.category ? 'Confirmar e Enviar' : 'Enviar Feedback'}
1566
- </Button>
1567
- </DialogFooter>
1568
- </DialogContent>
1569
- </Dialog>
593
+ <AssistantFeedbackDialog
594
+ state={evaluationState}
595
+ onReasonChange={(reason) => setEvaluationState(prev => ({ ...prev, reason }))}
596
+ onClose={() => setEvaluationState(prev => ({ ...prev, isOpen: false }))}
597
+ onSubmit={handleSubmitDislike}
598
+ />
1570
599
  </>
1571
600
  );
1572
601
  }