xertica-ui 1.2.5 → 1.2.7

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 (126) hide show
  1. package/components/CodeBlock.tsx +9 -9
  2. package/components/Header.tsx +58 -0
  3. package/components/HomeContent.tsx +13 -37
  4. package/components/HomePage.tsx +4 -2
  5. package/components/Sidebar.tsx +27 -17
  6. package/components/TemplatePage.tsx +4 -2
  7. package/components/index.ts +19 -2
  8. package/components/media/AudioPlayer.tsx +79 -79
  9. package/components/media/VideoPlayer.tsx +36 -36
  10. package/components/ui/drawer.tsx +12 -0
  11. package/components/ui/index.ts +132 -132
  12. package/components/ui/input.tsx +1 -1
  13. package/components/ui/map.tsx +1 -1
  14. package/components/ui/page-header.tsx +42 -12
  15. package/components/ui/sheet.tsx +5 -4
  16. package/components/ui/tree-view.tsx +1 -1
  17. package/contexts/index.ts +6 -0
  18. package/dist/components/AssistenteXertica.d.ts +8 -0
  19. package/dist/components/AudioPlayer.d.ts +12 -0
  20. package/dist/components/CodeBlock.d.ts +8 -0
  21. package/dist/components/DocumentEditor.d.ts +7 -0
  22. package/dist/components/ForgotPasswordPage.d.ts +1 -0
  23. package/dist/components/FormattedDocument.d.ts +7 -0
  24. package/dist/components/Header.d.ts +10 -0
  25. package/dist/components/HomeContent.d.ts +8 -0
  26. package/dist/components/HomePage.d.ts +8 -0
  27. package/dist/components/LanguageSelector.d.ts +7 -0
  28. package/dist/components/LoginPage.d.ts +5 -0
  29. package/dist/components/MarkdownMessage.d.ts +6 -0
  30. package/dist/components/ModernChatInput.d.ts +14 -0
  31. package/dist/components/PodcastPlayer.d.ts +15 -0
  32. package/dist/components/ResetPasswordPage.d.ts +1 -0
  33. package/dist/components/Sidebar.d.ts +22 -0
  34. package/dist/components/TemplateContent.d.ts +8 -0
  35. package/dist/components/TemplatePage.d.ts +8 -0
  36. package/dist/components/ThemeToggle.d.ts +8 -0
  37. package/dist/components/VerifyEmailPage.d.ts +1 -0
  38. package/dist/components/XerticaLogo.d.ts +7 -0
  39. package/dist/components/XerticaOrbe.d.ts +6 -0
  40. package/dist/components/XerticaXLogo.d.ts +7 -0
  41. package/dist/components/figma/ImageWithFallback.d.ts +2 -0
  42. package/dist/components/index.d.ts +23 -0
  43. package/dist/components/media/AudioPlayer.d.ts +9 -0
  44. package/dist/components/media/FloatingMediaWrapper.d.ts +14 -0
  45. package/dist/components/media/VideoPlayer.d.ts +8 -0
  46. package/dist/components/ui/accordion.d.ts +7 -0
  47. package/dist/components/ui/alert-dialog.d.ts +14 -0
  48. package/dist/components/ui/alert.d.ts +9 -0
  49. package/dist/components/ui/aspect-ratio.d.ts +3 -0
  50. package/dist/components/ui/avatar.d.ts +8 -0
  51. package/dist/components/ui/badge.d.ts +9 -0
  52. package/dist/components/ui/breadcrumb.d.ts +11 -0
  53. package/dist/components/ui/button.d.ts +14 -0
  54. package/dist/components/ui/calendar.d.ts +8 -0
  55. package/dist/components/ui/card.d.ts +9 -0
  56. package/dist/components/ui/carousel.d.ts +19 -0
  57. package/dist/components/ui/chart.d.ts +40 -0
  58. package/dist/components/ui/checkbox.d.ts +4 -0
  59. package/dist/components/ui/collapsible.d.ts +5 -0
  60. package/dist/components/ui/command.d.ts +16 -0
  61. package/dist/components/ui/context-menu.d.ts +25 -0
  62. package/dist/components/ui/dialog.d.ts +15 -0
  63. package/dist/components/ui/drawer.d.ts +14 -0
  64. package/dist/components/ui/dropdown-menu.d.ts +25 -0
  65. package/dist/components/ui/empty.d.ts +8 -0
  66. package/dist/components/ui/file-upload.d.ts +10 -0
  67. package/dist/components/ui/form.d.ts +24 -0
  68. package/dist/components/ui/google-maps-loader.d.ts +30 -0
  69. package/dist/components/ui/hover-card.d.ts +6 -0
  70. package/dist/components/ui/index.d.ts +81 -0
  71. package/dist/components/ui/input-otp.d.ts +11 -0
  72. package/dist/components/ui/input.d.ts +6 -0
  73. package/dist/components/ui/label.d.ts +4 -0
  74. package/dist/components/ui/map-config.d.ts +12 -0
  75. package/dist/components/ui/map-layers.d.ts +48 -0
  76. package/dist/components/ui/map.d.ts +53 -0
  77. package/dist/components/ui/map.exports.d.ts +25 -0
  78. package/dist/components/ui/menubar.d.ts +26 -0
  79. package/dist/components/ui/navigation-menu.d.ts +14 -0
  80. package/dist/components/ui/notification-badge.d.ts +11 -0
  81. package/dist/components/ui/page-header.d.ts +58 -0
  82. package/dist/components/ui/pagination.d.ts +13 -0
  83. package/dist/components/ui/popover.d.ts +7 -0
  84. package/dist/components/ui/progress.d.ts +4 -0
  85. package/dist/components/ui/radio-group.d.ts +5 -0
  86. package/dist/components/ui/rating.d.ts +12 -0
  87. package/dist/components/ui/resizable.d.ts +27 -0
  88. package/dist/components/ui/route-map.d.ts +26 -0
  89. package/dist/components/ui/scroll-area.d.ts +5 -0
  90. package/dist/components/ui/search.d.ts +8 -0
  91. package/dist/components/ui/select.d.ts +15 -0
  92. package/dist/components/ui/separator.d.ts +4 -0
  93. package/dist/components/ui/sheet.d.ts +14 -0
  94. package/dist/components/ui/sidebar.d.ts +69 -0
  95. package/dist/components/ui/simple-map.d.ts +51 -0
  96. package/dist/components/ui/skeleton.d.ts +2 -0
  97. package/dist/components/ui/slider.d.ts +4 -0
  98. package/dist/components/ui/sonner.d.ts +23 -0
  99. package/dist/components/ui/stats-card.d.ts +14 -0
  100. package/dist/components/ui/stepper.d.ts +17 -0
  101. package/dist/components/ui/switch.d.ts +4 -0
  102. package/dist/components/ui/table.d.ts +10 -0
  103. package/dist/components/ui/tabs.d.ts +7 -0
  104. package/dist/components/ui/textarea.d.ts +3 -0
  105. package/dist/components/ui/timeline.d.ts +12 -0
  106. package/dist/components/ui/toggle-group.d.ts +12 -0
  107. package/dist/components/ui/toggle.d.ts +12 -0
  108. package/dist/components/ui/tooltip.d.ts +7 -0
  109. package/dist/components/ui/tree-view.d.ts +15 -0
  110. package/dist/components/ui/use-mobile.d.ts +2 -0
  111. package/dist/components/ui/utils.d.ts +2 -0
  112. package/dist/components/ui/xertica-assistant.d.ts +196 -0
  113. package/dist/contexts/ApiKeyContext.d.ts +15 -0
  114. package/dist/contexts/AssistenteContext.d.ts +71 -0
  115. package/dist/contexts/BrandColorsContext.d.ts +15 -0
  116. package/dist/contexts/LanguageContext.d.ts +11 -0
  117. package/dist/contexts/ThemeContext.d.ts +13 -0
  118. package/dist/contexts/index.d.ts +6 -0
  119. package/dist/contexts/theme-data.d.ts +81 -0
  120. package/dist/index.es.js +82597 -0
  121. package/dist/index.umd.js +82616 -0
  122. package/dist/routes.d.ts +10 -0
  123. package/dist/utils/gemini.d.ts +8 -0
  124. package/dist/xertica-ui.css +4470 -0
  125. package/package.json +18 -5
  126. package/vite.config.ts +14 -5
@@ -137,11 +137,11 @@ interface CodeBlockProps {
137
137
  showLineNumbers?: boolean;
138
138
  }
139
139
 
140
- export const CodeBlock = ({
141
- code,
142
- language = 'tsx',
140
+ export const CodeBlock = ({
141
+ code,
142
+ language = 'tsx',
143
143
  filename,
144
- showLineNumbers = false
144
+ showLineNumbers = false
145
145
  }: CodeBlockProps) => {
146
146
  const [copied, setCopied] = useState(false);
147
147
 
@@ -161,7 +161,7 @@ export const CodeBlock = ({
161
161
  } else {
162
162
  throw new Error('Clipboard API not available');
163
163
  }
164
-
164
+
165
165
  setCopied(true);
166
166
  setTimeout(() => setCopied(false), 2000);
167
167
  } catch (err) {
@@ -175,10 +175,10 @@ export const CodeBlock = ({
175
175
  document.body.appendChild(textArea);
176
176
  textArea.focus();
177
177
  textArea.select();
178
-
178
+
179
179
  const successful = document.execCommand('copy');
180
180
  document.body.removeChild(textArea);
181
-
181
+
182
182
  if (successful) {
183
183
  setCopied(true);
184
184
  setTimeout(() => setCopied(false), 2000);
@@ -202,7 +202,7 @@ export const CodeBlock = ({
202
202
  <span className="text-xs text-muted-foreground uppercase">{language}</span>
203
203
  </div>
204
204
  )}
205
-
205
+
206
206
  <div className="relative">
207
207
  <Button
208
208
  variant="ghost"
@@ -220,7 +220,7 @@ export const CodeBlock = ({
220
220
  <div className="overflow-x-auto w-full max-w-full">
221
221
  <SyntaxHighlighter
222
222
  language={language}
223
- style={elegantTheme}
223
+ style={elegantTheme as any}
224
224
  showLineNumbers={showLineNumbers}
225
225
  wrapLines={true}
226
226
  customStyle={{
@@ -0,0 +1,58 @@
1
+ import React from 'react';
2
+ import { Menu, ChevronRight } from 'lucide-react';
3
+ import { Button } from './ui/button';
4
+ import { ThemeToggle } from './ThemeToggle';
5
+ import { LanguageSelector } from './LanguageSelector';
6
+
7
+ interface HeaderProps {
8
+ sidebarExpanded: boolean;
9
+ onToggleSidebar: () => void;
10
+ title: string;
11
+ showLanguageSelector?: boolean;
12
+ showThemeToggle?: boolean;
13
+ className?: string;
14
+ }
15
+
16
+ export function Header({
17
+ sidebarExpanded,
18
+ onToggleSidebar,
19
+ title,
20
+ showLanguageSelector = true,
21
+ showThemeToggle = true,
22
+ className
23
+ }: HeaderProps) {
24
+
25
+ return (
26
+ <header className={`bg-card shadow-sm border-b border-border px-[24px] py-[14px] flex-shrink-0 ${className || ''}`}>
27
+ <div className="flex items-center justify-between p-[0px]">
28
+ <div className="flex items-center gap-2 text-muted-foreground">
29
+ {/* Botão menu para mobile */}
30
+ <Button
31
+ variant="ghost"
32
+ size="sm"
33
+ onClick={onToggleSidebar}
34
+ className="md:hidden mr-2 p-2"
35
+ >
36
+ <Menu className="w-5 h-5" />
37
+ </Button>
38
+ <span className="text-primary font-medium">Xertica.ai</span>
39
+ <ChevronRight className="w-4 h-4" />
40
+ <span className="text-foreground font-medium">{title}</span>
41
+ </div>
42
+
43
+ {/* Controles do usuário */}
44
+ <div className="flex items-center gap-3">
45
+ {/* Seletor de idioma */}
46
+ {showLanguageSelector && (
47
+ <LanguageSelector variant="minimal" showIcon={false} className="hidden sm:flex" />
48
+ )}
49
+
50
+ {/* Toggle de tema */}
51
+ {showThemeToggle && (
52
+ <ThemeToggle className="hover:bg-accent" />
53
+ )}
54
+ </div>
55
+ </div>
56
+ </header>
57
+ );
58
+ }
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Card, CardContent, CardFooter, CardHeader, CardTitle } from './ui/card';
3
+ import { Header } from './Header';
3
4
  import { Button } from './ui/button';
4
5
  import { ChevronRight, Menu, FileText } from 'lucide-react';
5
6
  import { ScrollArea } from './ui/scroll-area';
@@ -19,7 +20,7 @@ interface HomeContentProps {
19
20
  export function HomeContent({ sidebarExpanded, assistenteExpanded = false, onToggleSidebar, onToggleAssistente }: HomeContentProps) {
20
21
  const location = useLocation();
21
22
  const navigate = useNavigate();
22
-
23
+
23
24
  // Tradução direta para português
24
25
  const labelTranslations: Record<string, string> = {
25
26
  'home': 'Início',
@@ -28,48 +29,23 @@ export function HomeContent({ sidebarExpanded, assistenteExpanded = false, onTog
28
29
 
29
30
  // Get current route info
30
31
  const currentRoute = getRouteByPath(location.pathname);
31
- const breadcrumbLabel = currentRoute?.label
32
+ const breadcrumbLabel = currentRoute?.label
32
33
  ? labelTranslations[currentRoute.label.toLowerCase()] || currentRoute.label
33
34
  : 'Início';
34
35
 
35
36
 
36
37
 
37
38
  return (
38
- <div
39
- className={`flex-1 flex flex-col overflow-hidden transition-all duration-300 ${
40
- sidebarExpanded ? 'md:pl-64' : 'md:pl-20'
41
- } ${
42
- assistenteExpanded ? 'md:pr-[420px]' : 'md:pr-20'
43
- }`}
39
+ <div
40
+ className={`flex-1 flex flex-col overflow-hidden transition-all duration-300 ${sidebarExpanded ? 'md:pl-64' : 'md:pl-20'
41
+ } ${assistenteExpanded ? 'md:pr-[420px]' : 'md:pr-20'
42
+ }`}
44
43
  >
45
- {/* Header fixo */}
46
- <header className="bg-card shadow-sm border-b border-border px-[24px] py-[14px] flex-shrink-0">
47
- <div className="flex items-center justify-between p-[0px]">
48
- <div className="flex items-center gap-2 text-muted-foreground">
49
- {/* Botão menu para mobile */}
50
- <Button
51
- variant="ghost"
52
- size="sm"
53
- onClick={onToggleSidebar}
54
- className="md:hidden mr-2 p-2"
55
- >
56
- <Menu className="w-5 h-5" />
57
- </Button>
58
- <span className="text-primary font-medium">Xertica.ai</span>
59
- <ChevronRight className="w-4 h-4" />
60
- <span className="text-foreground font-medium">{breadcrumbLabel}</span>
61
- </div>
62
-
63
- {/* Controles do usuário */}
64
- <div className="flex items-center gap-3">
65
- {/* Seletor de idioma */}
66
- <LanguageSelector variant="minimal" showIcon={false} className="hidden sm:flex" />
67
-
68
- {/* Toggle de tema */}
69
- <ThemeToggle className="hover:bg-accent" />
70
- </div>
71
- </div>
72
- </header>
44
+ <Header
45
+ sidebarExpanded={sidebarExpanded}
46
+ onToggleSidebar={onToggleSidebar || (() => { })}
47
+ title={breadcrumbLabel}
48
+ />
73
49
 
74
50
  {/* Área de conteúdo */}
75
51
  <main className="flex-1 overflow-hidden bg-muted">
@@ -104,7 +80,7 @@ export function HomeContent({ sidebarExpanded, assistenteExpanded = false, onTog
104
80
  </p>
105
81
  </CardContent>
106
82
  <CardFooter>
107
- <Button
83
+ <Button
108
84
  variant="outline"
109
85
  className="w-full"
110
86
  onClick={() => navigate('/template')}
@@ -3,6 +3,7 @@ import { useLocation, useNavigate } from 'react-router';
3
3
  import { Sidebar } from './Sidebar';
4
4
  import { HomeContent } from './HomeContent';
5
5
  import { AssistenteXertica } from './AssistenteXertica';
6
+ import { routes } from '../routes';
6
7
 
7
8
  interface HomePageProps {
8
9
  user: { email: string } | null;
@@ -46,15 +47,16 @@ export function HomePage({ user, onLogout }: HomePageProps) {
46
47
 
47
48
  return (
48
49
  <div className="h-screen flex bg-muted overflow-hidden relative">
49
- <Sidebar
50
+ <Sidebar
50
51
  expanded={sidebarExpanded}
51
52
  onToggle={handleToggleSidebar}
52
53
  user={user}
53
54
  onLogout={onLogout}
54
55
  location={location}
55
56
  navigate={navigate}
57
+ routes={routes}
56
58
  />
57
- <HomeContent
59
+ <HomeContent
58
60
  sidebarExpanded={sidebarExpanded}
59
61
  assistenteExpanded={assistenteExpanded}
60
62
  onToggleSidebar={handleToggleSidebar}
@@ -7,7 +7,7 @@ import {
7
7
  MoreHorizontal,
8
8
  ChevronRight,
9
9
  } from "lucide-react";
10
- import { routes } from "../routes";
10
+ // routes import removed to make it reusable
11
11
  import { Avatar, AvatarFallback, AvatarImage } from "./ui/avatar";
12
12
  import { Popover, PopoverContent, PopoverTrigger } from "./ui/popover";
13
13
  import { Tooltip, TooltipProvider, TooltipTrigger } from "./ui/tooltip";
@@ -15,8 +15,9 @@ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
15
15
  import { cn } from "./ui/utils";
16
16
  import { XerticaLogo } from "./XerticaLogo";
17
17
  import { XerticaXLogo } from "./XerticaXLogo";
18
+ import { Button } from "./ui/button";
18
19
 
19
- // TooltipContent customizado para a Sidebar com seta branca
20
+ // Validar se SidebarTooltipContent existe em outro lugar ou manter aqui
20
21
  function SidebarTooltipContent({
21
22
  className,
22
23
  sideOffset = 0,
@@ -34,15 +35,23 @@ function SidebarTooltipContent({
34
35
  {...props}
35
36
  >
36
37
  {children}
37
- <TooltipPrimitive.Arrow
38
- className="fill-popover z-50 drop-shadow-sm"
39
- width={8}
38
+ <TooltipPrimitive.Arrow
39
+ className="fill-popover z-50 drop-shadow-sm"
40
+ width={8}
40
41
  height={4}
41
42
  />
42
43
  </TooltipPrimitive.Content>
43
44
  );
44
45
  }
45
46
 
47
+ // Interface for Route Config (copied/imported type)
48
+ export interface RouteConfig {
49
+ path: string;
50
+ label: string;
51
+ icon: React.ComponentType<any>;
52
+ component?: React.ComponentType<any>;
53
+ }
54
+
46
55
  interface SubMenuItem {
47
56
  id: string;
48
57
  label: string;
@@ -64,6 +73,7 @@ interface SidebarProps {
64
73
  onLogout: () => void;
65
74
  location: { pathname: string };
66
75
  navigate: (path: string) => void;
76
+ routes: RouteConfig[];
67
77
  }
68
78
 
69
79
  export function Sidebar({
@@ -73,6 +83,7 @@ export function Sidebar({
73
83
  onLogout,
74
84
  location,
75
85
  navigate,
86
+ routes,
76
87
  }: SidebarProps) {
77
88
  const navRef = useRef<HTMLDivElement>(null);
78
89
  const [hasOverflow, setHasOverflow] = useState(false);
@@ -154,9 +165,9 @@ export function Sidebar({
154
165
  ? "w-full h-10 flex items-center gap-3 px-3 justify-start rounded-[var(--radius-button)] transition-all duration-200 bg-sidebar-foreground/15 text-sidebar-foreground shadow-sm"
155
166
  : "w-full h-10 flex items-center gap-3 px-3 justify-start rounded-[var(--radius-button)] transition-all duration-200 text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground"
156
167
  : "w-full h-10 flex items-center justify-center px-0 rounded-[var(--radius-button)] transition-all duration-200 " +
157
- (item.active
158
- ? "bg-sidebar-foreground/15 text-sidebar-foreground shadow-sm"
159
- : "text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground")
168
+ (item.active
169
+ ? "bg-sidebar-foreground/15 text-sidebar-foreground shadow-sm"
170
+ : "text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground")
160
171
  }
161
172
  >
162
173
  <Icon className="w-5 h-5 flex-shrink-0" />
@@ -210,7 +221,7 @@ export function Sidebar({
210
221
  <span className="truncate">{item.label}</span>
211
222
  </button>
212
223
  )}
213
-
224
+
214
225
  {/* Subitens */}
215
226
  {hasSubItems && item.subItems && (
216
227
  <>
@@ -246,9 +257,9 @@ export function Sidebar({
246
257
  ? "w-full h-10 flex items-center gap-3 px-3 justify-start rounded-[var(--radius-button)] transition-all duration-200 bg-sidebar-foreground/15 text-sidebar-foreground shadow-sm"
247
258
  : "w-full h-10 flex items-center gap-3 px-3 justify-start rounded-[var(--radius-button)] transition-all duration-200 text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground"
248
259
  : "w-full h-10 flex items-center justify-center px-0 rounded-[var(--radius-button)] transition-all duration-200 " +
249
- (item.active
250
- ? "bg-sidebar-foreground/15 text-sidebar-foreground shadow-sm"
251
- : "text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground")
260
+ (item.active
261
+ ? "bg-sidebar-foreground/15 text-sidebar-foreground shadow-sm"
262
+ : "text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground")
252
263
  }
253
264
  >
254
265
  <Icon className="w-5 h-5 flex-shrink-0" />
@@ -281,11 +292,10 @@ export function Sidebar({
281
292
  <TooltipProvider delayDuration={300}>
282
293
  {/* Sidebar */}
283
294
  <div
284
- className={`bg-sidebar text-sidebar-foreground transition-all duration-300 ease-in-out flex flex-col z-50 ${
285
- expanded
286
- ? "fixed inset-0 md:fixed md:inset-y-0 md:left-0 md:w-64"
287
- : "fixed inset-y-0 left-0 w-20 -translate-x-full md:translate-x-0"
288
- }`}
295
+ className={`bg-sidebar text-sidebar-foreground transition-all duration-300 ease-in-out flex flex-col z-50 ${expanded
296
+ ? "fixed inset-0 md:fixed md:inset-y-0 md:left-0 md:w-64"
297
+ : "fixed inset-y-0 left-0 w-20 -translate-x-full md:translate-x-0"
298
+ }`}
289
299
  >
290
300
  {/* Botão Toggle Menu */}
291
301
  <div className="p-[14px] pt-[13px] pr-[14px] pb-[12px] pl-[14px]">
@@ -3,6 +3,7 @@ import { useLocation, useNavigate } from 'react-router';
3
3
  import { Sidebar } from './Sidebar';
4
4
  import { TemplateContent } from './TemplateContent';
5
5
  import { AssistenteXertica } from './AssistenteXertica';
6
+ import { routes } from '../routes';
6
7
 
7
8
  interface TemplatePageProps {
8
9
  user: { email: string } | null;
@@ -46,15 +47,16 @@ export function TemplatePage({ user, onLogout }: TemplatePageProps) {
46
47
 
47
48
  return (
48
49
  <div className="h-screen flex bg-muted overflow-hidden relative">
49
- <Sidebar
50
+ <Sidebar
50
51
  expanded={sidebarExpanded}
51
52
  onToggle={handleToggleSidebar}
52
53
  user={user}
53
54
  onLogout={onLogout}
54
55
  location={location}
55
56
  navigate={navigate}
57
+ routes={routes}
56
58
  />
57
- <TemplateContent
59
+ <TemplateContent
58
60
  sidebarExpanded={sidebarExpanded}
59
61
  assistenteExpanded={assistenteExpanded}
60
62
  onToggleSidebar={handleToggleSidebar}
@@ -1,9 +1,10 @@
1
+ import '../index.css';
1
2
  // ============================================================================
2
3
  // Xertica Assistant Exports
3
4
  // ============================================================================
4
5
 
5
6
  export { XerticaAssistant } from './ui/xertica-assistant';
6
- export type {
7
+ export type {
7
8
  XerticaAssistantProps,
8
9
  Message,
9
10
  Conversation,
@@ -41,4 +42,20 @@ export { XerticaOrbe } from './XerticaOrbe';
41
42
  // Layout
42
43
  export { Sidebar } from './Sidebar';
43
44
  export { ThemeToggle } from './ThemeToggle';
44
- export { LanguageSelector } from './LanguageSelector';
45
+ export { LanguageSelector } from './LanguageSelector';
46
+
47
+ // Connected Components (require Providers)
48
+ export { AssistenteXertica } from './AssistenteXertica';
49
+
50
+ // State Management & Contexts
51
+ export * from '../contexts';
52
+
53
+ // Layout & Common Components
54
+ export { Header } from './Header';
55
+ export { DocumentEditor } from './DocumentEditor';
56
+
57
+ // Media Components
58
+ export { VideoPlayer } from './media/VideoPlayer';
59
+ export { AudioPlayer } from './media/AudioPlayer';
60
+ export { FloatingMediaWrapper } from './media/FloatingMediaWrapper';
61
+ export { PodcastPlayer } from './PodcastPlayer';
@@ -14,12 +14,12 @@ export interface AudioPlayerProps {
14
14
  className?: string;
15
15
  }
16
16
 
17
- export function AudioPlayer({
18
- src,
17
+ export function AudioPlayer({
18
+ src,
19
19
  title = "Audio",
20
20
  artist,
21
21
  autoPlay = false,
22
- className
22
+ className
23
23
  }: AudioPlayerProps) {
24
24
  const audioRef = useRef<HTMLAudioElement>(null);
25
25
  const containerRef = useRef<HTMLDivElement>(null);
@@ -38,9 +38,9 @@ export function AudioPlayer({
38
38
  if (audioRef.current) {
39
39
  setCurrentTime(audioRef.current.currentTime);
40
40
  }
41
-
41
+
42
42
  setIsFloating(floating);
43
-
43
+
44
44
  if (!floating) {
45
45
  setIsManualFloating(false);
46
46
  if (containerRef.current) {
@@ -55,21 +55,21 @@ export function AudioPlayer({
55
55
  if (audio) {
56
56
  // If we are switching modes, restore time and play state
57
57
  if (Math.abs(audio.currentTime - currentTime) > 0.5) {
58
- audio.currentTime = currentTime;
58
+ audio.currentTime = currentTime;
59
59
  }
60
60
  if (isPlaying) {
61
- const playPromise = audio.play();
62
- if (playPromise !== undefined) {
63
- playPromise.catch(error => {
64
- // Auto-play might be blocked or interrupted
65
- console.log("Playback interrupted during switch:", error);
66
- });
67
- }
61
+ const playPromise = audio.play();
62
+ if (playPromise !== undefined) {
63
+ playPromise.catch(error => {
64
+ // Auto-play might be blocked or interrupted
65
+ console.log("Playback interrupted during switch:", error);
66
+ });
67
+ }
68
68
  }
69
69
  }
70
70
  // We depend on isFloating to trigger this check when the DOM node is recreated
71
71
  // But we also need to attach listeners to the new node
72
- }, [isFloating]);
72
+ }, [isFloating]);
73
73
 
74
74
  // Auto-float on scroll logic
75
75
  useEffect(() => {
@@ -79,17 +79,17 @@ export function AudioPlayer({
79
79
  const observer = new IntersectionObserver(
80
80
  ([entry]) => {
81
81
  if (isPlaying && !entry.isIntersecting && !isFloating) {
82
- // Sync time before floating
83
- if (audioRef.current) setCurrentTime(audioRef.current.currentTime);
84
- setIsFloating(true);
82
+ // Sync time before floating
83
+ if (audioRef.current) setCurrentTime(audioRef.current.currentTime);
84
+ setIsFloating(true);
85
85
  }
86
86
  else if (entry.isIntersecting && isFloating && !isManualFloating) {
87
- // Sync time before docking
88
- if (audioRef.current) setCurrentTime(audioRef.current.currentTime);
89
- handleSetFloating(false);
87
+ // Sync time before docking
88
+ if (audioRef.current) setCurrentTime(audioRef.current.currentTime);
89
+ handleSetFloating(false);
90
90
  }
91
91
  },
92
- { threshold: 0.2 }
92
+ { threshold: 0.2 }
93
93
  );
94
94
 
95
95
  observer.observe(container);
@@ -161,7 +161,7 @@ export function AudioPlayer({
161
161
 
162
162
  const PlayerControls = ({ isCompact = false }) => (
163
163
  <div className={cn("flex items-center gap-3 w-full", isCompact ? "px-3 py-1" : "px-4 py-3")}>
164
- <Button
164
+ <Button
165
165
  onClick={togglePlay}
166
166
  size="icon"
167
167
  variant="outline"
@@ -174,70 +174,70 @@ export function AudioPlayer({
174
174
  </Button>
175
175
 
176
176
  <div className="flex-1 min-w-0 flex flex-col justify-center gap-1.5">
177
- <div className="flex items-center justify-between text-xs leading-none">
178
- <div className="flex items-center gap-2 truncate">
179
- <span className="font-medium text-foreground truncate">{title}</span>
180
- {artist && !isCompact && <span className="text-muted-foreground hidden sm:inline-block border-l pl-2 border-border truncate">{artist}</span>}
181
- </div>
182
- <div className="text-muted-foreground font-medium tabular-nums shrink-0 text-[10px] sm:text-xs">
183
- {formatTime(currentTime)} / {formatTime(duration || 0)}
184
- </div>
177
+ <div className="flex items-center justify-between text-xs leading-none">
178
+ <div className="flex items-center gap-2 truncate">
179
+ <span className="font-medium text-foreground truncate">{title}</span>
180
+ {artist && !isCompact && <span className="text-muted-foreground hidden sm:inline-block border-l pl-2 border-border truncate">{artist}</span>}
185
181
  </div>
186
-
187
- <Slider
188
- value={[currentTime]}
189
- max={duration || 100}
190
- step={1}
191
- onValueChange={handleSeek}
192
- className="w-full"
193
- />
182
+ <div className="text-muted-foreground font-medium tabular-nums shrink-0 text-[10px] sm:text-xs">
183
+ {formatTime(currentTime)} / {formatTime(duration || 0)}
184
+ </div>
185
+ </div>
186
+
187
+ <Slider
188
+ value={[currentTime]}
189
+ max={duration || 100}
190
+ step={1}
191
+ onValueChange={handleSeek}
192
+ className="w-full"
193
+ />
194
194
  </div>
195
195
 
196
196
  <div className="flex items-center gap-1 shrink-0">
197
- {!isCompact && (
198
- <div className="hidden sm:flex items-center gap-2 group/volume mr-2">
199
- <Button
200
- variant="ghost"
201
- size="icon"
202
- className="h-8 w-8 text-muted-foreground hover:text-foreground"
203
- onClick={() => {
204
- const newMuted = !isMuted;
205
- setIsMuted(newMuted);
206
- if (audioRef.current) audioRef.current.muted = newMuted;
207
- }}
208
- >
209
- {isMuted ? <VolumeX className="w-4 h-4" /> : <Volume2 className="w-4 h-4" />}
210
- </Button>
211
- <div className="w-0 overflow-hidden group-hover/volume:w-20 transition-all duration-300">
212
- <Slider
213
- value={[isMuted ? 0 : volume]}
214
- max={1}
215
- step={0.01}
216
- onValueChange={handleVolumeChange}
217
- className="w-20"
218
- />
219
- </div>
220
- </div>
221
- )}
222
-
223
- {!isCompact && (
224
- <div className="w-px h-6 bg-border mx-1 hidden sm:block" />
225
- )}
226
-
227
- {!isCompact && (
197
+ {!isCompact && (
198
+ <div className="hidden sm:flex items-center gap-2 group/volume mr-2">
228
199
  <Button
229
200
  variant="ghost"
230
201
  size="icon"
231
202
  className="h-8 w-8 text-muted-foreground hover:text-foreground"
232
203
  onClick={() => {
233
- setIsManualFloating(true);
234
- handleSetFloating(true);
204
+ const newMuted = !isMuted;
205
+ setIsMuted(newMuted);
206
+ if (audioRef.current) audioRef.current.muted = newMuted;
235
207
  }}
236
- title="Modo Flutuante"
237
208
  >
238
- <Maximize2 className="w-4 h-4" />
209
+ {isMuted ? <VolumeX className="w-4 h-4" /> : <Volume2 className="w-4 h-4" />}
239
210
  </Button>
240
- )}
211
+ <div className="w-0 overflow-hidden group-hover/volume:w-20 transition-all duration-300">
212
+ <Slider
213
+ value={[isMuted ? 0 : volume]}
214
+ max={1}
215
+ step={0.01}
216
+ onValueChange={handleVolumeChange}
217
+ className="w-20"
218
+ />
219
+ </div>
220
+ </div>
221
+ )}
222
+
223
+ {!isCompact && (
224
+ <div className="w-px h-6 bg-border mx-1 hidden sm:block" />
225
+ )}
226
+
227
+ {!isCompact && (
228
+ <Button
229
+ variant="ghost"
230
+ size="icon"
231
+ className="h-8 w-8 text-muted-foreground hover:text-foreground"
232
+ onClick={() => {
233
+ setIsManualFloating(true);
234
+ handleSetFloating(true);
235
+ }}
236
+ title="Modo Flutuante"
237
+ >
238
+ <Maximize2 className="w-4 h-4" />
239
+ </Button>
240
+ )}
241
241
  </div>
242
242
  </div>
243
243
  );
@@ -247,21 +247,21 @@ export function AudioPlayer({
247
247
  <FloatingMediaWrapper
248
248
  isFloating={isFloating}
249
249
  setIsFloating={handleSetFloating}
250
- onCloseMedia={() => {
250
+ onClose={() => {
251
251
  setIsPlaying(false);
252
- setIsFloating(false);
252
+ setIsFloating(false);
253
253
  if (audioRef.current) audioRef.current.pause();
254
254
  }}
255
255
  title={title}
256
- aspectRatio={320/110}
256
+ aspectRatio={320 / 110}
257
257
  minHeight={110}
258
258
  minWidth={320}
259
259
  className="w-full"
260
260
  >
261
261
  <div className={cn(
262
262
  "bg-card w-full overflow-hidden flex flex-col justify-center",
263
- isFloating
264
- ? "h-full bg-transparent text-primary-foreground [&_.text-muted-foreground]:text-primary-foreground/80 [&_.text-foreground]:text-primary-foreground [&_.text-primary]:text-primary-foreground [&_.border-primary\\/20]:border-primary-foreground/30 [&_.hover\\:bg-primary\\/5]:hover:bg-primary-foreground/10 [&_[data-slot=slider-track]]:bg-primary-foreground/20 [&_[data-slot=slider-range]]:bg-primary-foreground [&_[data-slot=slider-thumb]]:border-primary-foreground"
263
+ isFloating
264
+ ? "h-full bg-transparent text-primary-foreground [&_.text-muted-foreground]:text-primary-foreground/80 [&_.text-foreground]:text-primary-foreground [&_.text-primary]:text-primary-foreground [&_.border-primary\\/20]:border-primary-foreground/30 [&_.hover\\:bg-primary\\/5]:hover:bg-primary-foreground/10 [&_[data-slot=slider-track]]:bg-primary-foreground/20 [&_[data-slot=slider-range]]:bg-primary-foreground [&_[data-slot=slider-thumb]]:border-primary-foreground"
265
265
  : "border rounded-md shadow-sm"
266
266
  )}>
267
267
  <audio