xertica-ui 2.3.0 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/CHANGELOG.md +22 -2
  2. package/README.md +33 -22
  3. package/bin/cli.ts +136 -47
  4. package/bin/language-config.ts +5 -8
  5. package/components/assistant/modern-chat-input/ModernChatInput.tsx +17 -7
  6. package/components/assistant/xertica-assistant/parts/AssistantConversationList.tsx +1 -3
  7. package/components/assistant/xertica-assistant/parts/AssistantFeedbackDialog.tsx +13 -3
  8. package/components/assistant/xertica-assistant/parts/AssistantMessageBubble.tsx +10 -6
  9. package/components/assistant/xertica-assistant/xertica-assistant.tsx +1 -3
  10. package/components/blocks/card-patterns/FeatureCardSkeleton.tsx +1 -6
  11. package/components/blocks/card-patterns/ProfileCard.tsx +1 -3
  12. package/components/blocks/card-patterns/ProjectCardSkeleton.tsx +1 -6
  13. package/components/brand/language-selector/language-selector.stories.tsx +1 -4
  14. package/components/brand/theme-toggle/ThemeToggle.tsx +5 -1
  15. package/components/brand/xertica-provider/XerticaProvider.tsx +1 -4
  16. package/components/index.ts +1 -5
  17. package/components/layout/sidebar/sidebar.tsx +9 -3
  18. package/components/media/audio-player/AudioPlayer.tsx +4 -2
  19. package/components/pages/forgot-password-page/ForgotPasswordPage.tsx +188 -188
  20. package/components/pages/home-content/HomeContent.tsx +55 -55
  21. package/components/pages/home-page/HomePage.tsx +5 -1
  22. package/components/pages/login-page/LoginPage.tsx +4 -2
  23. package/components/pages/reset-password-page/ResetPasswordPage.tsx +7 -3
  24. package/components/pages/template-content/TemplateContent.tsx +268 -149
  25. package/components/pages/verify-email-page/VerifyEmailPage.tsx +9 -9
  26. package/components/shared/error-boundary.stories.tsx +114 -132
  27. package/components/shared/error-boundary.tsx +150 -154
  28. package/components/shared/error-fallbacks.tsx +222 -226
  29. package/components/ui/stats-card/stats-card-skeleton.tsx +1 -3
  30. package/components/ui/stats-card/stats-card.stories.tsx +18 -0
  31. package/components/ui/stats-card/stats-card.tsx +18 -2
  32. package/components.json +512 -892
  33. package/contexts/AuthContext.tsx +121 -118
  34. package/contexts/LanguageContext.tsx +1 -2
  35. package/dist/AssistantChart-BKVtGUKF.js +3383 -0
  36. package/dist/AssistantChart-WeycT5Pd.cjs +3551 -0
  37. package/dist/VerifyEmailPage-Bp1XXl3H.cjs +3305 -0
  38. package/dist/VerifyEmailPage-DGhuIqkb.js +3296 -0
  39. package/dist/XerticaProvider-BErr83Bg.js +42 -0
  40. package/dist/XerticaProvider-CwOkHxiT.cjs +44 -0
  41. package/dist/XerticaXLogo-BX3ueACh.js +255 -0
  42. package/dist/XerticaXLogo-qBPhwK3g.cjs +260 -0
  43. package/dist/assistant.cjs.js +1 -1
  44. package/dist/assistant.es.js +1 -1
  45. package/dist/brand.cjs.js +2 -2
  46. package/dist/brand.es.js +2 -2
  47. package/dist/cli.js +90 -37
  48. package/dist/components/brand/theme-toggle/ThemeToggle.d.ts +1 -1
  49. package/dist/components/index.d.ts +1 -1
  50. package/dist/components/ui/stats-card/stats-card.d.ts +10 -0
  51. package/dist/index.cjs.js +6 -6
  52. package/dist/index.es.js +6 -6
  53. package/dist/layout.cjs.js +1 -1
  54. package/dist/layout.es.js +1 -1
  55. package/dist/pages.cjs.js +1 -1
  56. package/dist/pages.es.js +1 -1
  57. package/dist/sidebar-B4ZWaMrE.js +792 -0
  58. package/dist/sidebar-BS1p2V7t.cjs +795 -0
  59. package/dist/ui.cjs.js +1 -1
  60. package/dist/ui.es.js +1 -1
  61. package/dist/xertica-assistant-B1NaSFFj.js +2173 -0
  62. package/dist/xertica-assistant-CIaUlbIt.cjs +2180 -0
  63. package/dist/xertica-ui.css +1 -1
  64. package/docs/architecture-improvements.md +5 -5
  65. package/docs/architecture.md +16 -10
  66. package/docs/components/card-patterns.md +19 -17
  67. package/docs/components/error-boundary.md +201 -191
  68. package/docs/components/hooks.md +15 -13
  69. package/docs/components/language-selector.md +20 -16
  70. package/docs/components/pages.md +323 -309
  71. package/docs/components/stats-card.md +20 -2
  72. package/docs/doc-audit.md +12 -11
  73. package/docs/getting-started.md +41 -28
  74. package/docs/guidelines.md +14 -12
  75. package/docs/i18n.md +61 -57
  76. package/docs/installation.md +268 -267
  77. package/docs/llms.md +17 -17
  78. package/docs/state-management.md +17 -17
  79. package/guidelines/Guidelines.md +17 -14
  80. package/llms-compact.txt +1 -1
  81. package/llms-full.txt +11553 -7133
  82. package/llms.txt +1 -1
  83. package/package.json +1 -1
  84. package/styles/xertica/base.css +90 -84
  85. package/templates/CLAUDE.md +16 -1
  86. package/templates/guidelines/Guidelines.md +42 -18
  87. package/templates/package.json +3 -3
  88. package/templates/src/app/components/AuthGuard.tsx +131 -82
  89. package/templates/src/features/auth/ui/AuthPageShell.tsx +32 -32
  90. package/templates/src/features/auth/ui/ForgotPasswordContent.tsx +1 -3
  91. package/templates/src/features/auth/ui/ResetPasswordContent.tsx +6 -2
  92. package/templates/src/features/auth/ui/VerifyEmailContent.tsx +2 -6
  93. package/templates/src/features/home/data/mock.ts +41 -35
  94. package/templates/src/features/home/ui/HomeContent.tsx +62 -64
  95. package/templates/src/features/template/ui/CrudTemplate.tsx +1 -4
  96. package/templates/src/features/template/ui/LoginTemplate.tsx +1 -1
  97. package/templates/src/features/template/ui/TemplateContent.tsx +28 -20
  98. package/templates/src/locales/en/pages/templates.json +17 -17
  99. package/templates/src/locales/es/pages/templates.json +17 -17
  100. package/templates/src/locales/pt-BR/pages/templates.json +17 -17
  101. package/templates/src/pages/AssistantPage.tsx +26 -20
  102. package/templates/src/pages/HomePage.tsx +5 -1
  103. package/templates/src/shared/error-boundary.tsx +150 -154
  104. package/templates/src/shared/error-fallbacks.tsx +222 -226
  105. package/templates/vite.config.ts +12 -9
@@ -0,0 +1,795 @@
1
+ 'use strict';
2
+
3
+ const jsxRuntime = require('react/jsx-runtime');
4
+ const React = require('react');
5
+ const lucideReact = require('lucide-react');
6
+ const button = require('./button-0BlA47It.cjs');
7
+ const XerticaXLogo = require('./XerticaXLogo-qBPhwK3g.cjs');
8
+ const breadcrumb = require('./breadcrumb-BKtHF4gk.cjs');
9
+ const dropdownMenu = require('./dropdown-menu-BMcykFDf.cjs');
10
+ const avatar = require('./avatar-BCM7YQRC.cjs');
11
+ const LayoutContext = require('./LayoutContext-BEq_-n98.cjs');
12
+ const framerMotion = require('framer-motion');
13
+ const reactI18next = require('react-i18next');
14
+ const input = require('./input-C_UiS2Py.cjs');
15
+ const tooltip = require('./tooltip-D8n9UYoU.cjs');
16
+ const CustomTooltipContent = require('./CustomTooltipContent-BhdIeBEg.cjs');
17
+
18
+ function Header({
19
+ title,
20
+ breadcrumbs,
21
+ showLanguageSelector = true,
22
+ showThemeToggle = true,
23
+ className,
24
+ user,
25
+ actions,
26
+ showSettings,
27
+ onSettingsClick,
28
+ showLogout,
29
+ onLogoutClick,
30
+ renderLink,
31
+ breadcrumbSlot
32
+ }) {
33
+ const layout = LayoutContext.useOptionalLayout();
34
+ const toggleSidebar = layout?.toggleSidebar ?? (() => {
35
+ });
36
+ return /* @__PURE__ */ jsxRuntime.jsx(
37
+ "header",
38
+ {
39
+ className: `bg-card text-foreground shadow-sm border-b border-border px-[24px] h-[64px] flex-shrink-0 flex items-center ${className || ""}`,
40
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between w-full p-[0px]", children: [
41
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-muted-foreground w-full overflow-x-auto", children: [
42
+ /* @__PURE__ */ jsxRuntime.jsx(
43
+ button.Button,
44
+ {
45
+ variant: "ghost",
46
+ size: "sm",
47
+ onClick: toggleSidebar,
48
+ className: "md:hidden mr-2 p-2 shrink-0",
49
+ "aria-label": "Abrir menu lateral",
50
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "w-5 h-5" })
51
+ }
52
+ ),
53
+ breadcrumbs && breadcrumbs.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(breadcrumb.Breadcrumb, { children: /* @__PURE__ */ jsxRuntime.jsx(breadcrumb.BreadcrumbList, { className: "flex-nowrap whitespace-nowrap", children: breadcrumbs.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
54
+ /* @__PURE__ */ jsxRuntime.jsx(breadcrumb.BreadcrumbItem, { children: item.href ? renderLink ? /* @__PURE__ */ jsxRuntime.jsx(breadcrumb.BreadcrumbLink, { asChild: true, className: "flex items-center gap-1.5", children: renderLink(item.href, {
55
+ className: "flex items-center gap-1.5",
56
+ children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
57
+ item.icon,
58
+ item.label
59
+ ] })
60
+ }) }) : /* @__PURE__ */ jsxRuntime.jsxs(breadcrumb.BreadcrumbLink, { href: item.href, className: "flex items-center gap-1.5", children: [
61
+ item.icon,
62
+ item.label
63
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(breadcrumb.BreadcrumbPage, { className: "flex items-center gap-1.5", children: [
64
+ item.icon,
65
+ item.label
66
+ ] }) }),
67
+ index < breadcrumbs.length - 1 && /* @__PURE__ */ jsxRuntime.jsx(breadcrumb.BreadcrumbSeparator, {})
68
+ ] }, index)) }) }) : title ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground font-medium shrink-0", children: title }) : /* @__PURE__ */ jsxRuntime.jsx(breadcrumb.Breadcrumb, { children: /* @__PURE__ */ jsxRuntime.jsx(breadcrumb.BreadcrumbList, { className: "flex-nowrap whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx(breadcrumb.BreadcrumbItem, { children: /* @__PURE__ */ jsxRuntime.jsx(breadcrumb.BreadcrumbPage, { className: "text-foreground font-medium shrink-0", children: "Xertica.ai" }) }) }) }),
69
+ breadcrumbSlot && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center shrink-0", children: breadcrumbSlot })
70
+ ] }),
71
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 shrink-0 ml-4", children: [
72
+ showLanguageSelector && /* @__PURE__ */ jsxRuntime.jsx(XerticaXLogo.LanguageSelector, { variant: "minimal", showIcon: false, className: "hidden sm:flex" }),
73
+ showThemeToggle && /* @__PURE__ */ jsxRuntime.jsx(XerticaXLogo.ThemeToggle, { className: "hover:bg-accent" }),
74
+ actions?.map((action) => /* @__PURE__ */ jsxRuntime.jsxs(
75
+ button.Button,
76
+ {
77
+ variant: "ghost",
78
+ size: action.label ? "sm" : "icon",
79
+ onClick: action.onClick,
80
+ className: `hover:bg-accent ${action.className || ""}`,
81
+ "aria-label": action.label || action.id,
82
+ children: [
83
+ action.icon,
84
+ action.label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 hidden md:inline", children: action.label })
85
+ ]
86
+ },
87
+ action.id
88
+ )),
89
+ showSettings && /* @__PURE__ */ jsxRuntime.jsx(
90
+ button.Button,
91
+ {
92
+ variant: "ghost",
93
+ size: "icon",
94
+ onClick: onSettingsClick,
95
+ className: "hover:bg-accent",
96
+ "aria-label": "Configurações",
97
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, { className: "w-5 h-5" })
98
+ }
99
+ ),
100
+ user && /* @__PURE__ */ jsxRuntime.jsxs(dropdownMenu.DropdownMenu, { children: [
101
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
102
+ button.Button,
103
+ {
104
+ variant: "ghost",
105
+ className: "relative h-8 w-8 rounded-full p-0 overflow-hidden border border-border/50 hover:border-primary/30 transition-colors",
106
+ "aria-label": "Menu do usuário",
107
+ children: /* @__PURE__ */ jsxRuntime.jsxs(avatar.Avatar, { className: "h-8 w-8", children: [
108
+ /* @__PURE__ */ jsxRuntime.jsx(avatar.AvatarImage, { src: user.avatar, alt: user.name || "User" }),
109
+ /* @__PURE__ */ jsxRuntime.jsx(avatar.AvatarFallback, { className: "bg-primary/10 text-primary text-xs font-medium", children: user.name ? user.name.charAt(0).toUpperCase() : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.User, { className: "w-4 h-4" }) })
110
+ ] })
111
+ }
112
+ ) }),
113
+ /* @__PURE__ */ jsxRuntime.jsxs(dropdownMenu.DropdownMenuContent, { className: "w-56", align: "end", forceMount: true, children: [
114
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuLabel, { className: "font-normal", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col space-y-1", children: [
115
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium leading-none", children: user.name || "User" }),
116
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs leading-none text-muted-foreground", children: user.email || "user@example.com" })
117
+ ] }) }),
118
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuSeparator, {}),
119
+ user.menuItems?.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(dropdownMenu.DropdownMenuItem, { onClick: item.onClick, className: item.className, children: [
120
+ item.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mr-2", children: item.icon }),
121
+ item.label
122
+ ] }, item.id)),
123
+ !user.menuItems && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
124
+ /* @__PURE__ */ jsxRuntime.jsxs(dropdownMenu.DropdownMenuItem, { onClick: onSettingsClick, children: [
125
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, { className: "mr-2 h-4 w-4" }),
126
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Settings" })
127
+ ] }),
128
+ /* @__PURE__ */ jsxRuntime.jsxs(
129
+ dropdownMenu.DropdownMenuItem,
130
+ {
131
+ onClick: onLogoutClick,
132
+ className: "text-destructive focus:text-destructive",
133
+ children: [
134
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LogOut, { className: "mr-2 h-4 w-4" }),
135
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Logout" })
136
+ ]
137
+ }
138
+ )
139
+ ] })
140
+ ] })
141
+ ] }),
142
+ showLogout && /* @__PURE__ */ jsxRuntime.jsx(
143
+ button.Button,
144
+ {
145
+ variant: "ghost",
146
+ size: "icon",
147
+ onClick: onLogoutClick,
148
+ className: "hover:bg-accent text-muted-foreground hover:text-foreground",
149
+ "aria-label": "Sair",
150
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LogOut, { className: "w-5 h-5" })
151
+ }
152
+ )
153
+ ] })
154
+ ] })
155
+ }
156
+ );
157
+ }
158
+
159
+ const SidebarContext = React.createContext(null);
160
+ function useSidebarContext() {
161
+ const ctx = React.useContext(SidebarContext);
162
+ if (!ctx) {
163
+ throw new Error("Sidebar compound components must be used within <Sidebar.Root>");
164
+ }
165
+ return ctx;
166
+ }
167
+ function SidebarRoot({
168
+ expanded: expandedProp,
169
+ onToggle: onToggleProp,
170
+ navigate: navigateProp,
171
+ location: locationProp,
172
+ width: widthProp,
173
+ children,
174
+ className
175
+ }) {
176
+ const layoutContext = LayoutContext.useOptionalLayout();
177
+ const [localExpanded, setLocalExpanded] = React.useState(false);
178
+ const [isMobileViewport, setIsMobileViewport] = React.useState(false);
179
+ const expanded = expandedProp !== void 0 ? expandedProp : layoutContext?.sidebarExpanded ?? localExpanded;
180
+ const onToggle = onToggleProp || layoutContext?.toggleSidebar || (() => setLocalExpanded((prev) => !prev));
181
+ const width = widthProp !== void 0 ? widthProp : layoutContext?.sidebarWidth ?? 280;
182
+ const navigate = navigateProp || ((path) => {
183
+ if (typeof window !== "undefined") window.location.href = path;
184
+ });
185
+ const location = locationProp || (typeof window !== "undefined" ? window.location : { pathname: "/" });
186
+ React.useEffect(() => {
187
+ const checkViewport = () => setIsMobileViewport(window.innerWidth < 768);
188
+ checkViewport();
189
+ window.addEventListener("resize", checkViewport);
190
+ return () => window.removeEventListener("resize", checkViewport);
191
+ }, []);
192
+ return /* @__PURE__ */ jsxRuntime.jsx(
193
+ SidebarContext.Provider,
194
+ {
195
+ value: { expanded, isMobileViewport, onToggle, navigate, location, width },
196
+ children: /* @__PURE__ */ jsxRuntime.jsxs(tooltip.TooltipProvider, { delayDuration: 300, children: [
197
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
198
+ @media (max-width: 767px) {
199
+ [style*="padding-left"].flex-1,
200
+ [style*="paddingLeft"].flex-1 {
201
+ padding-left: 0 !important;
202
+ }
203
+ }
204
+ ` }),
205
+ /* @__PURE__ */ jsxRuntime.jsx(
206
+ "div",
207
+ {
208
+ className: button.cn(
209
+ "bg-sidebar text-sidebar-foreground transition-all duration-300 ease-in-out flex flex-col z-50",
210
+ expanded ? "fixed inset-0 md:fixed md:inset-y-0 md:left-0" : "fixed inset-y-0 left-0 w-20 -translate-x-full md:translate-x-0",
211
+ className
212
+ ),
213
+ style: expanded && !isMobileViewport ? { width: `${width}px` } : void 0,
214
+ children
215
+ }
216
+ )
217
+ ] })
218
+ }
219
+ );
220
+ }
221
+ function SidebarHeader({
222
+ logo,
223
+ logoCollapsed
224
+ }) {
225
+ const { expanded, onToggle } = useSidebarContext();
226
+ const { t } = reactI18next.useTranslation();
227
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
228
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 p-[14px] pt-[13px] pr-[14px] pb-[12px] pl-[14px]", children: /* @__PURE__ */ jsxRuntime.jsx(
229
+ "button",
230
+ {
231
+ onClick: onToggle,
232
+ className: "w-full h-10 flex items-center gap-3 px-3 justify-center rounded-[var(--radius-button)] transition-all duration-200 text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground",
233
+ "aria-label": expanded ? t("sidebar.collapse") : t("sidebar.expand"),
234
+ "aria-expanded": expanded,
235
+ "aria-controls": "sidebar-nav",
236
+ children: expanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, { className: "w-5 h-5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "w-5 h-5" })
237
+ }
238
+ ) }),
239
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 px-4 py-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center h-10 justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center flex-shrink-0", children: expanded ? logo || /* @__PURE__ */ jsxRuntime.jsx(XerticaXLogo.XerticaLogo, { className: "h-5 w-auto", variant: "white" }) : logoCollapsed || /* @__PURE__ */ jsxRuntime.jsx(XerticaXLogo.XerticaXLogo, { className: "h-5 w-auto", variant: "white" }) }) }) })
240
+ ] });
241
+ }
242
+ function SidebarNav({
243
+ navigationGroups = [],
244
+ routes = [],
245
+ variant = "default"
246
+ }) {
247
+ const { expanded, navigate, location, onToggle } = useSidebarContext();
248
+ const { t } = reactI18next.useTranslation();
249
+ const navRef = React.useRef(null);
250
+ const [localActiveItem, setLocalActiveItem] = React.useState(null);
251
+ const [hasOverflow, setHasOverflow] = React.useState(false);
252
+ const [visibleItems, setVisibleItems] = React.useState([]);
253
+ const [overflowItems, setOverflowItems] = React.useState([]);
254
+ const labelTranslations = React.useMemo(
255
+ () => ({
256
+ home: "Início",
257
+ dashboard: "Painel",
258
+ components: "Componentes"
259
+ }),
260
+ []
261
+ );
262
+ const navigationItems = React.useMemo(
263
+ () => (routes || []).map((route) => ({
264
+ ...route,
265
+ label: labelTranslations[route.label.toLowerCase()] || route.label,
266
+ active: location.pathname === route.path || location.pathname.startsWith(route.path + "/"),
267
+ children: route.children
268
+ })),
269
+ [routes, location.pathname, labelTranslations]
270
+ );
271
+ React.useEffect(() => {
272
+ if (typeof window === "undefined") return;
273
+ const checkOverflow = () => {
274
+ if (!navRef.current) return;
275
+ if (variant === "assistant") return;
276
+ const navHeight = navRef.current.clientHeight;
277
+ const itemHeight = 44;
278
+ const maxVisibleItems = Math.floor(navHeight / itemHeight);
279
+ if (navigationItems.length > maxVisibleItems) {
280
+ setHasOverflow(true);
281
+ setVisibleItems(navigationItems.slice(0, maxVisibleItems - 1));
282
+ setOverflowItems(navigationItems.slice(maxVisibleItems - 1));
283
+ } else {
284
+ setHasOverflow(false);
285
+ setVisibleItems(navigationItems);
286
+ setOverflowItems([]);
287
+ }
288
+ };
289
+ checkOverflow();
290
+ window.addEventListener("resize", checkOverflow);
291
+ return () => window.removeEventListener("resize", checkOverflow);
292
+ }, [navigationItems.length, variant]);
293
+ const handleNavigate = (path) => {
294
+ setLocalActiveItem(path);
295
+ navigate(path);
296
+ if (typeof window !== "undefined" && window.innerWidth < 768) {
297
+ onToggle();
298
+ }
299
+ };
300
+ const toNavItem = (route) => ({
301
+ path: route.path,
302
+ label: labelTranslations[route.label.toLowerCase()] || route.label,
303
+ icon: route.icon,
304
+ active: location.pathname === route.path || location.pathname.startsWith(route.path + "/"),
305
+ children: route.children,
306
+ actions: route.actions
307
+ });
308
+ const renderActionItems = (actions) => {
309
+ return actions.map((action, idx) => {
310
+ const Icon = action.icon;
311
+ if (action.children && action.children.length > 0) {
312
+ return /* @__PURE__ */ jsxRuntime.jsxs(dropdownMenu.DropdownMenuSub, { children: [
313
+ /* @__PURE__ */ jsxRuntime.jsxs(dropdownMenu.DropdownMenuSubTrigger, { children: [
314
+ Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "mr-2 h-4 w-4" }),
315
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: action.label })
316
+ ] }),
317
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuPortal, { children: /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuSubContent, { className: "w-48 bg-popover border-border", children: renderActionItems(action.children) }) })
318
+ ] }, idx);
319
+ }
320
+ return /* @__PURE__ */ jsxRuntime.jsxs(
321
+ dropdownMenu.DropdownMenuItem,
322
+ {
323
+ className: button.cn(
324
+ "flex items-center gap-2",
325
+ action.variant === "destructive" ? "text-destructive focus:text-destructive" : ""
326
+ ),
327
+ onClick: (e) => {
328
+ e.stopPropagation();
329
+ action.onClick?.(null);
330
+ },
331
+ children: [
332
+ Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4 flex-shrink-0" }),
333
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: action.label })
334
+ ]
335
+ },
336
+ idx
337
+ );
338
+ });
339
+ };
340
+ const renderAssistantActionMenu = (actions, isHeader = false) => {
341
+ if (!actions || actions.length === 0) return null;
342
+ return /* @__PURE__ */ jsxRuntime.jsxs(dropdownMenu.DropdownMenu, { children: [
343
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
344
+ button.Button,
345
+ {
346
+ variant: "ghost",
347
+ size: "icon",
348
+ className: button.cn(
349
+ "h-8 w-8 text-sidebar-foreground/80 hover:bg-sidebar-foreground/20 hover:text-sidebar-foreground rounded-full transition-all",
350
+ !isHeader && "opacity-0 group-hover/item:opacity-100"
351
+ ),
352
+ "aria-label": t("sidebar.moreOptions"),
353
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreVertical, { className: "h-4 w-4" })
354
+ }
355
+ ) }),
356
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuContent, { align: "end", className: "w-48 bg-popover border-border p-1", children: renderActionItems(actions) })
357
+ ] });
358
+ };
359
+ const renderDefaultItem = (item) => {
360
+ const Icon = item.icon;
361
+ const hasChildren = item.children && item.children.length > 0;
362
+ const activeClass = item.active ? "bg-sidebar-foreground/15 text-sidebar-foreground shadow-sm" : "text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground";
363
+ if (!expanded) {
364
+ return /* @__PURE__ */ jsxRuntime.jsxs(tooltip.Tooltip, { children: [
365
+ /* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
366
+ "button",
367
+ {
368
+ onClick: () => handleNavigate(item.path),
369
+ className: button.cn(
370
+ "w-full h-10 flex items-center justify-center px-0 rounded-[var(--radius-button)] transition-all duration-200",
371
+ activeClass
372
+ ),
373
+ "aria-label": item.label,
374
+ children: Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "w-5 h-5 flex-shrink-0" })
375
+ }
376
+ ) }),
377
+ /* @__PURE__ */ jsxRuntime.jsx(CustomTooltipContent.CustomTooltipContent, { side: "right", sideOffset: 0, children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: item.label }) })
378
+ ] }, item.path);
379
+ }
380
+ return /* @__PURE__ */ jsxRuntime.jsxs(
381
+ "div",
382
+ {
383
+ className: button.cn(
384
+ "group/item flex items-center w-full h-10 rounded-[var(--radius-button)] transition-all duration-200",
385
+ activeClass
386
+ ),
387
+ children: [
388
+ /* @__PURE__ */ jsxRuntime.jsxs(
389
+ "button",
390
+ {
391
+ onClick: () => handleNavigate(item.path),
392
+ className: "flex items-center gap-3 px-3 flex-1 h-full min-w-0 text-left",
393
+ children: [
394
+ Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "w-5 h-5 flex-shrink-0" }),
395
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate flex-1", children: item.label })
396
+ ]
397
+ }
398
+ ),
399
+ hasChildren && /* @__PURE__ */ jsxRuntime.jsxs(dropdownMenu.DropdownMenu, { children: [
400
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
401
+ "button",
402
+ {
403
+ onClick: (e) => e.stopPropagation(),
404
+ className: "h-full px-2 pr-2.5 flex items-center justify-center text-sidebar-foreground/40 hover:text-sidebar-foreground transition-colors",
405
+ "aria-label": t("sidebar.submenu", { label: item.label }),
406
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "w-4 h-4" })
407
+ }
408
+ ) }),
409
+ /* @__PURE__ */ jsxRuntime.jsx(
410
+ dropdownMenu.DropdownMenuContent,
411
+ {
412
+ side: "right",
413
+ align: "start",
414
+ className: "w-48 bg-popover border-border p-1",
415
+ children: item.children.map((child) => {
416
+ const ChildIcon = child.icon;
417
+ const isChildActive = location.pathname === child.path || location.pathname.startsWith(child.path + "/");
418
+ return /* @__PURE__ */ jsxRuntime.jsxs(
419
+ dropdownMenu.DropdownMenuItem,
420
+ {
421
+ onClick: () => handleNavigate(child.path),
422
+ className: button.cn(
423
+ "flex items-center gap-2 cursor-pointer",
424
+ isChildActive && "bg-accent text-accent-foreground"
425
+ ),
426
+ children: [
427
+ ChildIcon && /* @__PURE__ */ jsxRuntime.jsx(ChildIcon, { className: "h-4 w-4 flex-shrink-0" }),
428
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: child.label })
429
+ ]
430
+ },
431
+ child.path
432
+ );
433
+ })
434
+ }
435
+ )
436
+ ] })
437
+ ]
438
+ },
439
+ item.path
440
+ );
441
+ };
442
+ const renderDefaultGroup = (group) => {
443
+ const GroupIcon = group.icon;
444
+ if (!expanded) {
445
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: group.items.map((item) => renderDefaultItem(toNavItem(item))) }, group.id);
446
+ }
447
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
448
+ (group.label || GroupIcon) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 mb-1 flex items-center gap-2", children: [
449
+ GroupIcon && (React.isValidElement(GroupIcon) ? GroupIcon : /* @__PURE__ */ jsxRuntime.jsx(GroupIcon, { className: "h-3 w-3 text-sidebar-foreground/80" })),
450
+ group.label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold uppercase tracking-wider text-sidebar-foreground/80", children: group.label })
451
+ ] }),
452
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: group.items.map((item) => renderDefaultItem(toNavItem(item))) })
453
+ ] }, group.id);
454
+ };
455
+ const renderAssistantGroup = (group) => {
456
+ const isAnyItemActive = group.items.some(
457
+ (item) => location.pathname === item.path || location.pathname.startsWith(item.path + "/")
458
+ );
459
+ const GroupIcon = group.icon;
460
+ if (!expanded) {
461
+ if (!GroupIcon) return null;
462
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs(tooltip.Tooltip, { children: [
463
+ /* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
464
+ "button",
465
+ {
466
+ onClick: () => onToggle(),
467
+ "aria-label": group.label,
468
+ className: button.cn(
469
+ "h-10 w-10 flex items-center justify-center rounded-[var(--radius-button)] transition-all duration-200",
470
+ isAnyItemActive ? "bg-sidebar-foreground/15 text-sidebar-foreground shadow-sm" : "text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground"
471
+ ),
472
+ children: React.isValidElement(GroupIcon) ? GroupIcon : /* @__PURE__ */ jsxRuntime.jsx(GroupIcon, { className: "h-5 w-5" })
473
+ }
474
+ ) }),
475
+ /* @__PURE__ */ jsxRuntime.jsx(CustomTooltipContent.CustomTooltipContent, { side: "right", children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: group.label }) })
476
+ ] }) }, group.id);
477
+ }
478
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-2 group", children: [
479
+ (group.label || group.icon) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-3 mb-1", children: [
480
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sidebar-foreground/80 text-xs font-semibold uppercase tracking-wider", children: [
481
+ GroupIcon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: React.isValidElement(GroupIcon) ? GroupIcon : /* @__PURE__ */ jsxRuntime.jsx(GroupIcon, { className: "h-4 w-4" }) }),
482
+ group.label && /* @__PURE__ */ jsxRuntime.jsx("span", { children: group.label })
483
+ ] }),
484
+ renderAssistantActionMenu(group.actions, true)
485
+ ] }),
486
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: group.items.map((item) => {
487
+ const isRouteActive = location.pathname === item.path || location.pathname.startsWith(item.path + "/");
488
+ const isActive = isRouteActive || localActiveItem === item.path;
489
+ const Icon = item.icon;
490
+ return /* @__PURE__ */ jsxRuntime.jsxs(
491
+ "div",
492
+ {
493
+ className: `group/item flex items-start justify-between px-3 min-h-[36px] py-2.5 rounded-[var(--radius-button)] cursor-pointer transition-all duration-200 ${isActive ? "bg-sidebar-foreground/15 text-sidebar-foreground" : "text-sidebar-foreground/80 hover:bg-sidebar-foreground/10 hover:text-sidebar-foreground"}`,
494
+ onClick: () => handleNavigate(item.path),
495
+ children: [
496
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0 flex-1", children: [
497
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 overflow-hidden h-5", children: [
498
+ Icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-4 h-4 flex-shrink-0 flex items-center justify-center", children: React.isValidElement(Icon) ? Icon : /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "w-4 h-4" }) }),
499
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-medium leading-none", children: item.label })
500
+ ] }),
501
+ isActive && item.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[11px] text-sidebar-foreground/60 mt-1.5 animate-in fade-in slide-in-from-top-1 duration-200", children: item.description })
502
+ ] }),
503
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-5 flex items-center ml-1", children: renderAssistantActionMenu(item.actions) })
504
+ ]
505
+ },
506
+ item.path
507
+ );
508
+ }) })
509
+ ] }, group.id);
510
+ };
511
+ if (variant === "assistant") {
512
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(input.ScrollArea, { className: "h-full px-4", children: navigationGroups.map((group) => renderAssistantGroup(group)) }) });
513
+ }
514
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
515
+ "nav",
516
+ {
517
+ id: "sidebar-nav",
518
+ "aria-label": t("sidebar.mainNavigation"),
519
+ className: "h-full px-4 py-4 overflow-hidden",
520
+ ref: navRef,
521
+ children: navigationGroups && navigationGroups.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: navigationGroups.map((group) => /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: renderDefaultGroup(group) }, group.id)) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
522
+ (hasOverflow ? visibleItems : navigationItems).map((item) => renderDefaultItem(item)),
523
+ hasOverflow && /* @__PURE__ */ jsxRuntime.jsxs(input.Popover, { children: [
524
+ /* @__PURE__ */ jsxRuntime.jsx(input.PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
525
+ "button",
526
+ {
527
+ className: expanded ? "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" : "w-full h-10 flex items-center justify-center px-0 rounded-[var(--radius-button)] transition-all duration-200 text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground",
528
+ "aria-label": t("sidebar.moreOptions"),
529
+ children: [
530
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoreVertical, { className: "w-5 h-5 flex-shrink-0" }),
531
+ expanded && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sidebar-foreground", children: t("sidebar.moreOptions") })
532
+ ]
533
+ }
534
+ ) }),
535
+ /* @__PURE__ */ jsxRuntime.jsx(
536
+ input.PopoverContent,
537
+ {
538
+ side: "right",
539
+ align: "start",
540
+ className: "w-56 p-2 bg-popover border border-border rounded-[var(--radius-card)] shadow-lg",
541
+ sideOffset: 8,
542
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: overflowItems.map((item) => {
543
+ const Icon = item.icon;
544
+ return /* @__PURE__ */ jsxRuntime.jsxs(
545
+ "button",
546
+ {
547
+ onClick: () => handleNavigate(item.path),
548
+ className: "w-full h-9 flex items-center gap-2 px-3 rounded-[var(--radius-button)] transition-all duration-200 text-popover-foreground/80 hover:bg-accent hover:text-accent-foreground text-left",
549
+ children: [
550
+ Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "w-4 h-4 flex-shrink-0" }),
551
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: item.label })
552
+ ]
553
+ },
554
+ item.path
555
+ );
556
+ }) })
557
+ }
558
+ )
559
+ ] })
560
+ ] })
561
+ }
562
+ ) });
563
+ }
564
+ function SidebarSearch({
565
+ fixedArea,
566
+ search
567
+ }) {
568
+ const { expanded } = useSidebarContext();
569
+ const { t } = reactI18next.useTranslation();
570
+ const [isFilterOpen, setIsFilterOpen] = React.useState(false);
571
+ if (!(fixedArea && fixedArea.show || search && search.show)) return null;
572
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-shrink-0 px-4 pb-4 space-y-4 border-b border-sidebar-border/30 mb-2", children: [
573
+ fixedArea?.show && fixedArea.content && expanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "animate-in fade-in slide-in-from-top-1 duration-300", children: fixedArea.content }),
574
+ search?.show && expanded && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
575
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
576
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-1", children: [
577
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 h-4 w-4 text-sidebar-foreground/50" }),
578
+ /* @__PURE__ */ jsxRuntime.jsx(
579
+ input.Input,
580
+ {
581
+ type: "text",
582
+ placeholder: search.placeholder || t("sidebar.searchPlaceholder"),
583
+ "aria-label": search.placeholder || t("sidebar.searchPlaceholder"),
584
+ value: search.value,
585
+ onChange: (e) => search.onChange?.(e.target.value),
586
+ className: "w-full h-9 bg-sidebar-foreground/10 border-sidebar-border text-sidebar-foreground placeholder:text-sidebar-foreground/50 pl-9 focus-visible:ring-1 focus-visible:ring-sidebar-foreground/30 focus-visible:ring-offset-0"
587
+ }
588
+ )
589
+ ] }),
590
+ search.filter?.show && search.filter.content && /* @__PURE__ */ jsxRuntime.jsx(
591
+ button.Button,
592
+ {
593
+ variant: "ghost",
594
+ size: "icon",
595
+ onClick: () => setIsFilterOpen(!isFilterOpen),
596
+ className: button.cn(
597
+ "h-9 w-9 text-sidebar-foreground transition-all duration-200",
598
+ isFilterOpen ? "bg-sidebar-foreground/20" : "hover:bg-sidebar-foreground/15"
599
+ ),
600
+ "aria-label": isFilterOpen ? t("sidebar.closeFilters") : t("sidebar.openFilters"),
601
+ children: search.filter.icon || /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Filter, { className: "h-4 w-4" })
602
+ }
603
+ )
604
+ ] }),
605
+ /* @__PURE__ */ jsxRuntime.jsx(framerMotion.AnimatePresence, { children: isFilterOpen && search.filter?.show && search.filter.content && /* @__PURE__ */ jsxRuntime.jsx(
606
+ framerMotion.motion.div,
607
+ {
608
+ initial: { height: 0, opacity: 0 },
609
+ animate: { height: "auto", opacity: 1 },
610
+ exit: { height: 0, opacity: 0 },
611
+ transition: { duration: 0.2 },
612
+ className: "overflow-hidden",
613
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-2 border-t border-sidebar-border/20", children: search.filter.content })
614
+ }
615
+ ) })
616
+ ] }),
617
+ !expanded && (fixedArea?.show || search?.show) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-4 py-2", children: [
618
+ fixedArea?.show && fixedArea.icon && /* @__PURE__ */ jsxRuntime.jsxs(tooltip.Tooltip, { children: [
619
+ /* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
620
+ "button",
621
+ {
622
+ onClick: () => fixedArea.onClick?.(),
623
+ className: "h-10 w-10 flex items-center justify-center rounded-[var(--radius-button)] bg-primary text-primary-foreground shadow-sm hover:bg-primary/90 transition-all",
624
+ "aria-label": t("assistant.newConversation"),
625
+ children: React.isValidElement(fixedArea.icon) ? fixedArea.icon : /* @__PURE__ */ jsxRuntime.jsx(fixedArea.icon, { className: "h-5 w-5" })
626
+ }
627
+ ) }),
628
+ /* @__PURE__ */ jsxRuntime.jsx(CustomTooltipContent.CustomTooltipContent, { side: "right", children: t("assistant.newConversation") })
629
+ ] }),
630
+ search?.show && /* @__PURE__ */ jsxRuntime.jsxs(tooltip.Tooltip, { children: [
631
+ /* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
632
+ "button",
633
+ {
634
+ className: "h-10 w-10 flex items-center justify-center rounded-[var(--radius-button)] text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground",
635
+ "aria-label": t("sidebar.search"),
636
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-5 w-5" })
637
+ }
638
+ ) }),
639
+ /* @__PURE__ */ jsxRuntime.jsx(CustomTooltipContent.CustomTooltipContent, { side: "right", children: t("sidebar.search") })
640
+ ] })
641
+ ] })
642
+ ] });
643
+ }
644
+ function SidebarFooter({
645
+ user,
646
+ onLogout = () => {
647
+ },
648
+ onSettingsClick,
649
+ showUser = true,
650
+ showSettings = true,
651
+ showLogout = true
652
+ }) {
653
+ const { expanded, navigate, location, onToggle } = useSidebarContext();
654
+ const { t } = reactI18next.useTranslation();
655
+ const isSettingsActive = location.pathname === "/settings";
656
+ const handleSettingsClick = () => {
657
+ if (onSettingsClick) {
658
+ onSettingsClick();
659
+ } else {
660
+ navigate("/settings");
661
+ }
662
+ if (typeof window !== "undefined" && window.innerWidth < 768) {
663
+ onToggle();
664
+ }
665
+ };
666
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-shrink-0 p-4 space-y-2", children: [
667
+ showUser && (!expanded ? /* @__PURE__ */ jsxRuntime.jsxs(tooltip.Tooltip, { children: [
668
+ /* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
669
+ "button",
670
+ {
671
+ className: "w-full h-10 flex items-center justify-center px-0 rounded-[var(--radius-button)] transition-all duration-200 text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground",
672
+ "aria-label": t("sidebar.userProfile"),
673
+ children: /* @__PURE__ */ jsxRuntime.jsxs(avatar.Avatar, { className: "w-7 h-7 flex-shrink-0", children: [
674
+ /* @__PURE__ */ jsxRuntime.jsx(avatar.AvatarImage, { src: user?.avatar, alt: user?.name || "User" }),
675
+ /* @__PURE__ */ jsxRuntime.jsx(avatar.AvatarFallback, { className: "bg-sidebar-foreground/15 text-sidebar-foreground text-xs", children: user?.name ? user.name.charAt(0).toUpperCase() : "U" })
676
+ ] })
677
+ }
678
+ ) }),
679
+ /* @__PURE__ */ jsxRuntime.jsx(CustomTooltipContent.CustomTooltipContent, { side: "right", sideOffset: 0, children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: user?.name || t("sidebar.profile") }) })
680
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("button", { className: "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", children: [
681
+ /* @__PURE__ */ jsxRuntime.jsxs(avatar.Avatar, { className: "w-7 h-7 flex-shrink-0", children: [
682
+ /* @__PURE__ */ jsxRuntime.jsx(avatar.AvatarImage, { src: user?.avatar, alt: user?.name || "User" }),
683
+ /* @__PURE__ */ jsxRuntime.jsx(avatar.AvatarFallback, { className: "bg-sidebar-foreground/15 text-sidebar-foreground text-xs", children: user?.name ? user.name.charAt(0).toUpperCase() : "U" })
684
+ ] }),
685
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sidebar-foreground truncate", children: user?.name || t("sidebar.profile") })
686
+ ] })),
687
+ showSettings && (!expanded ? /* @__PURE__ */ jsxRuntime.jsxs(tooltip.Tooltip, { children: [
688
+ /* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
689
+ "button",
690
+ {
691
+ onClick: handleSettingsClick,
692
+ className: button.cn(
693
+ "w-full h-10 flex items-center justify-center px-0 rounded-[var(--radius-button)] transition-all duration-200",
694
+ isSettingsActive ? "bg-sidebar-foreground/15 text-sidebar-foreground shadow-sm" : "text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground"
695
+ ),
696
+ "aria-label": t("nav.settings"),
697
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, { className: "w-5 h-5 flex-shrink-0" })
698
+ }
699
+ ) }),
700
+ /* @__PURE__ */ jsxRuntime.jsx(CustomTooltipContent.CustomTooltipContent, { side: "right", sideOffset: 0, children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: t("nav.settings") }) })
701
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(
702
+ "button",
703
+ {
704
+ onClick: handleSettingsClick,
705
+ className: button.cn(
706
+ "w-full h-10 flex items-center gap-3 px-3 justify-start rounded-[var(--radius-button)] transition-all duration-200",
707
+ isSettingsActive ? "bg-sidebar-foreground/15 text-sidebar-foreground shadow-sm" : "text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground"
708
+ ),
709
+ children: [
710
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, { className: "w-5 h-5 flex-shrink-0" }),
711
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sidebar-foreground", children: t("nav.settings") })
712
+ ]
713
+ }
714
+ )),
715
+ showLogout && (!expanded ? /* @__PURE__ */ jsxRuntime.jsxs(tooltip.Tooltip, { children: [
716
+ /* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
717
+ "button",
718
+ {
719
+ onClick: onLogout,
720
+ className: "w-full h-10 flex items-center justify-center px-0 rounded-[var(--radius-button)] transition-all duration-200 text-sidebar-foreground/80 hover:bg-sidebar-foreground/15 hover:text-sidebar-foreground",
721
+ "aria-label": t("sidebar.logout"),
722
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LogOut, { className: "w-5 h-5 flex-shrink-0" })
723
+ }
724
+ ) }),
725
+ /* @__PURE__ */ jsxRuntime.jsx(CustomTooltipContent.CustomTooltipContent, { side: "right", sideOffset: 0, children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: t("sidebar.logout") }) })
726
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(
727
+ "button",
728
+ {
729
+ onClick: onLogout,
730
+ className: "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",
731
+ children: [
732
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LogOut, { className: "w-5 h-5 flex-shrink-0" }),
733
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sidebar-foreground", children: t("sidebar.logout") })
734
+ ]
735
+ }
736
+ ))
737
+ ] });
738
+ }
739
+ function Sidebar({
740
+ expanded: expandedProp,
741
+ onToggle: onToggleProp,
742
+ user,
743
+ onLogout = () => {
744
+ },
745
+ onSettingsClick,
746
+ location: locationProp,
747
+ navigate: navigateProp,
748
+ routes,
749
+ logo,
750
+ logoCollapsed,
751
+ variant = "default",
752
+ fixedArea,
753
+ search,
754
+ navigationGroups = [],
755
+ footer,
756
+ showFooter,
757
+ width: widthProp
758
+ }) {
759
+ const { showUser = true, showSettings = true, showLogout = true } = footer || {};
760
+ const displayFooter = showFooter !== void 0 ? showFooter : variant === "default";
761
+ return /* @__PURE__ */ jsxRuntime.jsxs(
762
+ SidebarRoot,
763
+ {
764
+ expanded: expandedProp,
765
+ onToggle: onToggleProp,
766
+ navigate: navigateProp,
767
+ location: locationProp,
768
+ width: widthProp,
769
+ children: [
770
+ /* @__PURE__ */ jsxRuntime.jsx(SidebarHeader, { logo, logoCollapsed }),
771
+ variant === "assistant" && /* @__PURE__ */ jsxRuntime.jsx(SidebarSearch, { fixedArea, search }),
772
+ /* @__PURE__ */ jsxRuntime.jsx(SidebarNav, { navigationGroups, routes, variant }),
773
+ displayFooter && (showUser || showSettings || showLogout) && /* @__PURE__ */ jsxRuntime.jsx(
774
+ SidebarFooter,
775
+ {
776
+ user,
777
+ onLogout,
778
+ onSettingsClick,
779
+ showUser,
780
+ showSettings,
781
+ showLogout
782
+ }
783
+ )
784
+ ]
785
+ }
786
+ );
787
+ }
788
+ Sidebar.Root = SidebarRoot;
789
+ Sidebar.Header = SidebarHeader;
790
+ Sidebar.Search = SidebarSearch;
791
+ Sidebar.Nav = SidebarNav;
792
+ Sidebar.Footer = SidebarFooter;
793
+
794
+ exports.Header = Header;
795
+ exports.Sidebar = Sidebar;