@classytic/fluid 0.1.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.
@@ -0,0 +1,992 @@
1
+ "use client";
2
+ import { Button } from '@/components/ui/button';
3
+ import { Badge } from '@/components/ui/badge';
4
+ import { Skeleton } from '@/components/ui/skeleton';
5
+ import { clsx } from 'clsx';
6
+ import { twMerge } from 'tailwind-merge';
7
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
+ import * as React4 from 'react';
9
+ import React4__default, { useState } from 'react';
10
+ import Link3 from 'next/link';
11
+ import { Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbPage, BreadcrumbLink, BreadcrumbSeparator } from '@/components/ui/breadcrumb';
12
+ import { Separator } from '@/components/ui/separator';
13
+ import { SidebarTrigger, useSidebar, SidebarMenu, SidebarMenuItem, SidebarMenuButton, SidebarMenuSub, SidebarMenuSubItem, SidebarMenuSubButton, SidebarGroup, SidebarGroupLabel, Sidebar, SidebarHeader, SidebarContent, SidebarFooter } from '@/components/ui/sidebar';
14
+ import { ChevronRight, ChevronsUpDown, CircleUserRound, LogOut, Building2, ChevronLeft, Check } from 'lucide-react';
15
+ import { Collapsible, CollapsibleTrigger, CollapsibleContent } from '@/components/ui/collapsible';
16
+ import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar';
17
+ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuItem } from '@/components/ui/dropdown-menu';
18
+ import { SheetTitle, SheetDescription } from '@/components/ui/sheet';
19
+ import { Tooltip, TooltipTrigger, TooltipContent } from '@/components/ui/tooltip';
20
+
21
+ // src/dashboard/header-section.tsx
22
+ function cn(...inputs) {
23
+ return twMerge(clsx(inputs));
24
+ }
25
+ var variants = {
26
+ default: {
27
+ wrapper: "px-6 py-5 rounded-xl shadow-sm border bg-background hover:shadow-md",
28
+ title: "text-2xl font-semibold tracking-tight",
29
+ description: "text-sm text-muted-foreground",
30
+ iconSize: "size-10",
31
+ iconInner: "size-5",
32
+ spacing: "space-y-1"
33
+ },
34
+ compact: {
35
+ wrapper: "px-4 py-3 rounded-lg border bg-background/50",
36
+ title: "text-lg font-semibold",
37
+ description: "text-xs text-muted-foreground",
38
+ iconSize: "size-8",
39
+ iconInner: "size-4",
40
+ spacing: "space-y-0.5"
41
+ },
42
+ hero: {
43
+ wrapper: "px-8 py-8 rounded-2xl shadow-lg border bg-gradient-to-br from-background to-muted/20",
44
+ title: "text-3xl font-bold tracking-tight bg-gradient-to-r from-foreground to-foreground/70 bg-clip-text text-transparent",
45
+ description: "text-base text-muted-foreground mt-2",
46
+ iconSize: "size-14",
47
+ iconInner: "size-7",
48
+ spacing: "space-y-2"
49
+ },
50
+ minimal: {
51
+ wrapper: "px-0 py-2",
52
+ title: "text-xl font-medium",
53
+ description: "text-sm text-muted-foreground",
54
+ iconSize: "size-8",
55
+ iconInner: "size-4",
56
+ spacing: "space-y-0.5"
57
+ }
58
+ };
59
+ function HeaderSection({
60
+ title,
61
+ description,
62
+ actions = null,
63
+ icon: Icon = null,
64
+ iconClassName,
65
+ loading = false,
66
+ variant = "default",
67
+ className,
68
+ badge,
69
+ breadcrumbs,
70
+ metadata,
71
+ children
72
+ }) {
73
+ const currentVariant = variants[variant] || variants.default;
74
+ const isBadgeObject = (badge2) => {
75
+ return typeof badge2 === "object" && badge2 !== null && "text" in badge2;
76
+ };
77
+ if (loading && !title) {
78
+ return /* @__PURE__ */ jsx("div", { className: cn(currentVariant.wrapper, "transition-all duration-300", className), children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between", children: [
79
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
80
+ Icon && /* @__PURE__ */ jsx(Skeleton, { className: cn(currentVariant.iconSize, "rounded-lg") }),
81
+ /* @__PURE__ */ jsxs("div", { className: currentVariant.spacing, children: [
82
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-7 w-48" }),
83
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-64 mt-1" })
84
+ ] })
85
+ ] }),
86
+ actions && /* @__PURE__ */ jsxs("div", { className: "flex gap-2 mt-4 sm:mt-0", children: [
87
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-9 w-24" }),
88
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-9 w-24" })
89
+ ] })
90
+ ] }) });
91
+ }
92
+ return /* @__PURE__ */ jsxs(
93
+ "div",
94
+ {
95
+ className: cn(
96
+ "transition-all duration-300",
97
+ currentVariant.wrapper,
98
+ className
99
+ ),
100
+ children: [
101
+ breadcrumbs && /* @__PURE__ */ jsx("nav", { className: "mb-3 text-sm text-muted-foreground", children: breadcrumbs }),
102
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4", children: [
103
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start sm:items-center gap-4", children: [
104
+ Icon && /* @__PURE__ */ jsx(
105
+ "div",
106
+ {
107
+ className: cn(
108
+ "flex aspect-square items-center justify-center rounded-lg flex-shrink-0",
109
+ "bg-primary/10 text-primary",
110
+ currentVariant.iconSize,
111
+ iconClassName
112
+ ),
113
+ children: /* @__PURE__ */ jsx(Icon, { className: currentVariant.iconInner })
114
+ }
115
+ ),
116
+ /* @__PURE__ */ jsxs("div", { className: cn("flex-1", currentVariant.spacing), children: [
117
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
118
+ /* @__PURE__ */ jsx("h1", { className: cn("leading-none", currentVariant.title), children: title }),
119
+ badge && (isBadgeObject(badge) ? /* @__PURE__ */ jsx(
120
+ Badge,
121
+ {
122
+ variant: badge.variant || "secondary",
123
+ className: cn("ml-2", badge.className),
124
+ children: badge.text
125
+ }
126
+ ) : badge)
127
+ ] }),
128
+ description && /* @__PURE__ */ jsx("p", { className: currentVariant.description, children: description }),
129
+ metadata && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-4 mt-2 text-xs text-muted-foreground", children: metadata.map((item, index) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
130
+ item.icon && /* @__PURE__ */ jsx(item.icon, { className: "size-3" }),
131
+ /* @__PURE__ */ jsx("span", { children: item.text })
132
+ ] }, index)) })
133
+ ] })
134
+ ] }),
135
+ actions && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2 mt-4 sm:mt-0", children: actions.map((action, index) => {
136
+ const isActionLoading = action.loading ?? false;
137
+ const isDisabled = loading || action.disabled || isActionLoading;
138
+ const displayText = isActionLoading ? action.loadingText || action.text : action.text;
139
+ return /* @__PURE__ */ jsxs(
140
+ Button,
141
+ {
142
+ onClick: action.onClick,
143
+ disabled: isDisabled,
144
+ variant: action.variant || "default",
145
+ size: action.size || (variant === "compact" ? "sm" : "default"),
146
+ className: cn(
147
+ variant === "hero" && "shadow-md hover:shadow-lg",
148
+ action.className
149
+ ),
150
+ children: [
151
+ action.icon && action.iconPosition !== "right" && /* @__PURE__ */ jsx(action.icon, { className: "size-4 mr-2" }),
152
+ /* @__PURE__ */ jsx("span", { children: displayText }),
153
+ action.icon && action.iconPosition === "right" && /* @__PURE__ */ jsx(action.icon, { className: "size-4 ml-2" })
154
+ ]
155
+ },
156
+ index
157
+ );
158
+ }) })
159
+ ] }),
160
+ children && /* @__PURE__ */ jsx(
161
+ "div",
162
+ {
163
+ className: cn(
164
+ "mt-4 pt-4 border-t",
165
+ variant === "minimal" && "border-0 pt-2"
166
+ ),
167
+ children
168
+ }
169
+ )
170
+ ]
171
+ }
172
+ );
173
+ }
174
+ function PageHeader({ items, className, actions }) {
175
+ return /* @__PURE__ */ jsxs("header", { className: cn("flex h-12 shrink-0 items-center justify-between gap-2", className), children: [
176
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
177
+ /* @__PURE__ */ jsx(SidebarTrigger, { className: "-ml-1" }),
178
+ /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "mr-2 h-4" }),
179
+ /* @__PURE__ */ jsx(Breadcrumb, { children: /* @__PURE__ */ jsx(BreadcrumbList, { children: items.map((item, index) => /* @__PURE__ */ jsxs(React4__default.Fragment, { children: [
180
+ /* @__PURE__ */ jsx(
181
+ BreadcrumbItem,
182
+ {
183
+ className: item.current ? "" : "hidden md:block",
184
+ children: item.current ? /* @__PURE__ */ jsx(BreadcrumbPage, { children: item.label }) : /* @__PURE__ */ jsx(BreadcrumbLink, { render: /* @__PURE__ */ jsx(Link3, { href: item.href || "#" }), children: item.label })
185
+ }
186
+ ),
187
+ index < items.length - 1 && /* @__PURE__ */ jsx(BreadcrumbSeparator, { className: "hidden md:block" })
188
+ ] }, `breadcrumb-${index}`)) }) })
189
+ ] }),
190
+ actions
191
+ ] });
192
+ }
193
+ function SidebarBrand({
194
+ title,
195
+ icon,
196
+ href = "/",
197
+ className,
198
+ tooltip
199
+ }) {
200
+ const { isMobile, state } = useSidebar();
201
+ const isCollapsed = state === "collapsed";
202
+ return /* @__PURE__ */ jsx(SidebarMenu, { className, children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(
203
+ SidebarMenuButton,
204
+ {
205
+ size: "lg",
206
+ tooltip: isCollapsed ? tooltip || title : void 0,
207
+ render: /* @__PURE__ */ jsx(
208
+ Link3,
209
+ {
210
+ href,
211
+ className: cn(
212
+ "flex items-center text-sidebar-foreground",
213
+ isCollapsed && !isMobile && "justify-center"
214
+ )
215
+ }
216
+ ),
217
+ children: [
218
+ /* @__PURE__ */ jsx("div", { className: "h-8 w-8 rounded-lg flex items-center justify-center bg-sidebar-primary text-sidebar-primary-foreground shadow-sm flex-shrink-0", children: icon }),
219
+ /* @__PURE__ */ jsx(
220
+ "span",
221
+ {
222
+ className: cn(
223
+ "ml-2 font-semibold tracking-tight truncate",
224
+ !isMobile && isCollapsed && "hidden"
225
+ ),
226
+ children: title
227
+ }
228
+ )
229
+ ]
230
+ }
231
+ ) }) });
232
+ }
233
+ function SidebarNavItem({ item, onClick }) {
234
+ const hasSubItems = item.items && item.items.length > 0;
235
+ const Icon = item.icon;
236
+ const [open, setOpen] = useState(item.isActive ?? false);
237
+ if (hasSubItems) {
238
+ return /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(
239
+ Collapsible,
240
+ {
241
+ open,
242
+ onOpenChange: setOpen,
243
+ className: "group/collapsible",
244
+ children: [
245
+ /* @__PURE__ */ jsxs(
246
+ CollapsibleTrigger,
247
+ {
248
+ render: /* @__PURE__ */ jsx(SidebarMenuButton, {}),
249
+ children: [
250
+ Icon && /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }),
251
+ /* @__PURE__ */ jsx("span", { children: item.title }),
252
+ item.badge && /* @__PURE__ */ jsx("span", { className: "ml-auto text-xs bg-sidebar-accent text-sidebar-accent-foreground px-1.5 py-0.5 rounded", children: item.badge }),
253
+ /* @__PURE__ */ jsx(ChevronRight, { className: "ml-auto h-4 w-4 transition-transform duration-200 group-data-open/collapsible:rotate-90" })
254
+ ]
255
+ }
256
+ ),
257
+ /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx(SidebarMenuSub, { children: item.items.map((subItem, idx) => /* @__PURE__ */ jsx(SidebarMenuSubItem, { children: /* @__PURE__ */ jsxs(SidebarMenuSubButton, { render: /* @__PURE__ */ jsx(Link3, { href: subItem.url }), children: [
258
+ /* @__PURE__ */ jsx("span", { children: subItem.title }),
259
+ subItem.badge && /* @__PURE__ */ jsx("span", { className: "ml-auto text-xs opacity-60", children: subItem.badge })
260
+ ] }) }, `${item.title}-${subItem.title}-${idx}`)) }) })
261
+ ]
262
+ }
263
+ ) });
264
+ }
265
+ return /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsx(Link3, { href: item.url, className: "w-full", children: /* @__PURE__ */ jsxs(
266
+ SidebarMenuButton,
267
+ {
268
+ isActive: item.isActive,
269
+ onClick,
270
+ children: [
271
+ Icon && /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }),
272
+ /* @__PURE__ */ jsx("span", { children: item.title }),
273
+ item.badge && /* @__PURE__ */ jsx("span", { className: "ml-auto text-xs bg-sidebar-accent text-sidebar-accent-foreground px-1.5 py-0.5 rounded", children: item.badge })
274
+ ]
275
+ }
276
+ ) }) });
277
+ }
278
+ function SidebarNavGroup({
279
+ title,
280
+ items,
281
+ className,
282
+ onItemClick
283
+ }) {
284
+ return /* @__PURE__ */ jsxs(SidebarGroup, { className, children: [
285
+ title && /* @__PURE__ */ jsx(SidebarGroupLabel, { children: title }),
286
+ /* @__PURE__ */ jsx(SidebarMenu, { children: items.map((item, idx) => /* @__PURE__ */ jsx(
287
+ SidebarNavItem,
288
+ {
289
+ item,
290
+ onClick: () => onItemClick?.(item)
291
+ },
292
+ `${item.title}-${idx}`
293
+ )) })
294
+ ] });
295
+ }
296
+ function SidebarNav({ groups, className, onItemClick }) {
297
+ return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-2", className), children: groups.map((group, index) => /* @__PURE__ */ jsx(
298
+ SidebarNavGroup,
299
+ {
300
+ title: group.title,
301
+ items: group.items,
302
+ onItemClick
303
+ },
304
+ group.title || `nav-group-${index}`
305
+ )) });
306
+ }
307
+ function getUserInitials(name) {
308
+ if (!name) return "?";
309
+ const names = name.trim().split(" ");
310
+ if (names.length === 1) return names[0].slice(0, 2).toUpperCase();
311
+ return (names[0][0] + names[names.length - 1][0]).toUpperCase();
312
+ }
313
+ function UserAvatar({ user, className }) {
314
+ return /* @__PURE__ */ jsxs(Avatar, { className: cn("h-8 w-8 rounded-lg", className), children: [
315
+ /* @__PURE__ */ jsx(AvatarImage, { src: user.avatar, alt: user.name }),
316
+ /* @__PURE__ */ jsx(AvatarFallback, { className: "rounded-lg bg-sidebar-primary text-sidebar-primary-foreground", children: getUserInitials(user.name) })
317
+ ] });
318
+ }
319
+ function UserInfo({ user }) {
320
+ return /* @__PURE__ */ jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
321
+ /* @__PURE__ */ jsx("span", { className: "truncate font-semibold", children: user.name }),
322
+ /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-muted-foreground", children: user.email })
323
+ ] });
324
+ }
325
+ function SidebarUserMenu({
326
+ user,
327
+ menuItems = [],
328
+ onLogout,
329
+ className
330
+ }) {
331
+ const { isMobile, state } = useSidebar();
332
+ const isCollapsed = state === "collapsed";
333
+ const defaultItems = [
334
+ {
335
+ label: "Account",
336
+ icon: CircleUserRound,
337
+ href: "/dashboard/profile"
338
+ }
339
+ ];
340
+ const items = menuItems.length > 0 ? menuItems : defaultItems;
341
+ return /* @__PURE__ */ jsx(SidebarMenu, { className, children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
342
+ /* @__PURE__ */ jsxs(
343
+ DropdownMenuTrigger,
344
+ {
345
+ render: /* @__PURE__ */ jsx(
346
+ SidebarMenuButton,
347
+ {
348
+ size: "lg",
349
+ tooltip: isCollapsed ? user.name : void 0,
350
+ className: cn(
351
+ "data-open:bg-sidebar-accent data-open:text-sidebar-accent-foreground",
352
+ isCollapsed && !isMobile && "justify-center"
353
+ )
354
+ }
355
+ ),
356
+ children: [
357
+ /* @__PURE__ */ jsx(UserAvatar, { user }),
358
+ (!isCollapsed || isMobile) && /* @__PURE__ */ jsxs(Fragment, { children: [
359
+ /* @__PURE__ */ jsx(UserInfo, { user }),
360
+ /* @__PURE__ */ jsx(ChevronsUpDown, { className: "ml-auto size-4" })
361
+ ] })
362
+ ]
363
+ }
364
+ ),
365
+ /* @__PURE__ */ jsxs(
366
+ DropdownMenuContent,
367
+ {
368
+ className: "w-(--anchor-width) min-w-56 rounded-lg",
369
+ side: isMobile ? "bottom" : "right",
370
+ align: "end",
371
+ sideOffset: 4,
372
+ children: [
373
+ /* @__PURE__ */ jsx(DropdownMenuGroup, { children: /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "p-0 font-normal", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-1 py-1.5 text-left text-sm", children: [
374
+ /* @__PURE__ */ jsx(UserAvatar, { user }),
375
+ /* @__PURE__ */ jsx(UserInfo, { user })
376
+ ] }) }) }),
377
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
378
+ /* @__PURE__ */ jsx(DropdownMenuGroup, { children: items.map((item, index) => /* @__PURE__ */ jsxs(React4.Fragment, { children: [
379
+ item.separator && index > 0 && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
380
+ item.href ? /* @__PURE__ */ jsxs(
381
+ DropdownMenuItem,
382
+ {
383
+ render: /* @__PURE__ */ jsx(Link3, { href: item.href }),
384
+ className: "w-full flex items-center",
385
+ children: [
386
+ item.icon && /* @__PURE__ */ jsx(item.icon, { className: "mr-2 h-4 w-4" }),
387
+ item.label
388
+ ]
389
+ }
390
+ ) : /* @__PURE__ */ jsxs(
391
+ DropdownMenuItem,
392
+ {
393
+ onClick: item.onClick,
394
+ className: "w-full flex items-center",
395
+ children: [
396
+ item.icon && /* @__PURE__ */ jsx(item.icon, { className: "mr-2 h-4 w-4" }),
397
+ item.label
398
+ ]
399
+ }
400
+ )
401
+ ] }, item.label)) }),
402
+ onLogout && /* @__PURE__ */ jsxs(Fragment, { children: [
403
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
404
+ /* @__PURE__ */ jsxs(
405
+ DropdownMenuItem,
406
+ {
407
+ onClick: onLogout,
408
+ className: "w-full flex items-center",
409
+ children: [
410
+ /* @__PURE__ */ jsx(LogOut, { className: "mr-2 h-4 w-4" }),
411
+ "Log out"
412
+ ]
413
+ }
414
+ )
415
+ ] })
416
+ ]
417
+ }
418
+ )
419
+ ] }) }) });
420
+ }
421
+ function DropdownContent({
422
+ items,
423
+ selected,
424
+ onSelect,
425
+ label,
426
+ renderItem,
427
+ isMobile = false
428
+ }) {
429
+ return /* @__PURE__ */ jsx(
430
+ DropdownMenuContent,
431
+ {
432
+ className: "w-64 rounded-lg",
433
+ side: isMobile ? "bottom" : "right",
434
+ align: "start",
435
+ sideOffset: 4,
436
+ children: /* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
437
+ /* @__PURE__ */ jsx(DropdownMenuLabel, { className: "text-xs text-muted-foreground font-normal", children: label }),
438
+ items.map((item) => {
439
+ const isSelected = selected.id === item.id;
440
+ if (renderItem) {
441
+ return /* @__PURE__ */ jsx(
442
+ DropdownMenuItem,
443
+ {
444
+ onClick: () => onSelect(item),
445
+ className: "cursor-pointer",
446
+ children: renderItem(item, isSelected)
447
+ },
448
+ item.id
449
+ );
450
+ }
451
+ return /* @__PURE__ */ jsx(
452
+ DropdownMenuItem,
453
+ {
454
+ onClick: () => onSelect(item),
455
+ className: "gap-2 cursor-pointer",
456
+ children: /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
457
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
458
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-sm truncate", children: item.name }),
459
+ isSelected && /* @__PURE__ */ jsx(Check, { className: "size-3.5 text-primary shrink-0" })
460
+ ] }),
461
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 mt-0.5", children: [
462
+ item.code && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: item.code }),
463
+ item.type && /* @__PURE__ */ jsxs(Fragment, { children: [
464
+ item.code && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: "\u2022" }),
465
+ /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-[10px] h-4 px-1", children: item.type })
466
+ ] }),
467
+ item.isDefault && /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "text-[10px] h-4 px-1", children: "Default" }),
468
+ item.isActive === false && /* @__PURE__ */ jsx(Badge, { variant: "destructive", className: "text-[10px] h-4 px-1", children: "Inactive" })
469
+ ] }),
470
+ item.subtitle && /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground mt-0.5 truncate", children: item.subtitle })
471
+ ] })
472
+ },
473
+ item.id
474
+ );
475
+ })
476
+ ] })
477
+ }
478
+ );
479
+ }
480
+ function SidebarLoadingSkeleton({ isCollapsed, isMobile }) {
481
+ return /* @__PURE__ */ jsx(SidebarMenu, { children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(
482
+ SidebarMenuButton,
483
+ {
484
+ className: cn(
485
+ "h-10 py-1.5 bg-sidebar-accent/50",
486
+ isCollapsed && !isMobile && "justify-center"
487
+ ),
488
+ disabled: true,
489
+ children: [
490
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-4 rounded-sm shrink-0" }),
491
+ (!isCollapsed || isMobile) && /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 space-y-1", children: [
492
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-24" }),
493
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-2.5 w-14" })
494
+ ] })
495
+ ]
496
+ }
497
+ ) }) });
498
+ }
499
+ function SidebarProjectDisplay({
500
+ project,
501
+ Icon,
502
+ isCollapsed,
503
+ isMobile
504
+ }) {
505
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
506
+ /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
507
+ (!isCollapsed || isMobile) && /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 leading-tight text-left", children: [
508
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-medium truncate", children: project.name }),
509
+ project.code && /* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground truncate", children: project.code })
510
+ ] })
511
+ ] });
512
+ }
513
+ function StandaloneLoadingSkeleton({ size }) {
514
+ return /* @__PURE__ */ jsxs(
515
+ Button,
516
+ {
517
+ variant: "outline",
518
+ size,
519
+ className: cn("gap-2", size === "sm" ? "h-8" : "h-9"),
520
+ disabled: true,
521
+ children: [
522
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-4 rounded-sm" }),
523
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-3 w-20" })
524
+ ]
525
+ }
526
+ );
527
+ }
528
+ function StandaloneProjectDisplay({
529
+ project,
530
+ Icon,
531
+ size
532
+ }) {
533
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
534
+ /* @__PURE__ */ jsx(Icon, { className: cn("text-muted-foreground shrink-0", size === "sm" ? "h-3.5 w-3.5" : "h-4 w-4") }),
535
+ /* @__PURE__ */ jsx("span", { className: cn("font-medium truncate max-w-[120px]", size === "sm" ? "text-xs" : "text-sm"), children: project.name }),
536
+ project.code && /* @__PURE__ */ jsxs("span", { className: cn("text-muted-foreground truncate", size === "sm" ? "text-[10px]" : "text-xs"), children: [
537
+ "(",
538
+ project.code,
539
+ ")"
540
+ ] })
541
+ ] });
542
+ }
543
+ function ProjectSwitcher({
544
+ items,
545
+ selected,
546
+ onSelect,
547
+ isLoading = false,
548
+ label = "Switch Project",
549
+ icon: Icon = Building2,
550
+ className,
551
+ disabled = false,
552
+ variant = "sidebar",
553
+ size = "default",
554
+ renderItem
555
+ }) {
556
+ const hasMultipleItems = items.length > 1;
557
+ if (variant === "standalone") {
558
+ if (isLoading) {
559
+ return /* @__PURE__ */ jsx(StandaloneLoadingSkeleton, { size });
560
+ }
561
+ if (!selected) {
562
+ return null;
563
+ }
564
+ if (!hasMultipleItems || disabled) {
565
+ return /* @__PURE__ */ jsx(
566
+ Button,
567
+ {
568
+ variant: "outline",
569
+ size,
570
+ className: cn("gap-2 cursor-default", size === "sm" ? "h-8" : "h-9", className),
571
+ disabled: true,
572
+ children: /* @__PURE__ */ jsx(StandaloneProjectDisplay, { project: selected, Icon, size })
573
+ }
574
+ );
575
+ }
576
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
577
+ /* @__PURE__ */ jsxs(
578
+ DropdownMenuTrigger,
579
+ {
580
+ render: /* @__PURE__ */ jsx(
581
+ Button,
582
+ {
583
+ variant: "outline",
584
+ size,
585
+ className: cn("gap-2", size === "sm" ? "h-8" : "h-9", className)
586
+ }
587
+ ),
588
+ children: [
589
+ /* @__PURE__ */ jsx(StandaloneProjectDisplay, { project: selected, Icon, size }),
590
+ /* @__PURE__ */ jsx(ChevronsUpDown, { className: cn("text-muted-foreground shrink-0", size === "sm" ? "h-3 w-3" : "h-3.5 w-3.5") })
591
+ ]
592
+ }
593
+ ),
594
+ /* @__PURE__ */ jsx(
595
+ DropdownContent,
596
+ {
597
+ items,
598
+ selected,
599
+ onSelect,
600
+ label,
601
+ renderItem
602
+ }
603
+ )
604
+ ] });
605
+ }
606
+ const { isMobile, state } = useSidebar();
607
+ const isCollapsed = state === "collapsed";
608
+ if (isLoading) {
609
+ return /* @__PURE__ */ jsx(SidebarLoadingSkeleton, { isCollapsed, isMobile });
610
+ }
611
+ if (!selected) {
612
+ return null;
613
+ }
614
+ if (!hasMultipleItems || disabled) {
615
+ return /* @__PURE__ */ jsx(SidebarMenu, { className, children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsx(
616
+ SidebarMenuButton,
617
+ {
618
+ className: cn(
619
+ "h-10 py-1.5 bg-sidebar-accent/50",
620
+ isCollapsed && !isMobile && "justify-center"
621
+ ),
622
+ tooltip: isCollapsed ? selected.name : void 0,
623
+ disabled: true,
624
+ children: /* @__PURE__ */ jsx(
625
+ SidebarProjectDisplay,
626
+ {
627
+ project: selected,
628
+ Icon,
629
+ isCollapsed,
630
+ isMobile
631
+ }
632
+ )
633
+ }
634
+ ) }) });
635
+ }
636
+ return /* @__PURE__ */ jsx(SidebarMenu, { className, children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(DropdownMenu, { children: [
637
+ /* @__PURE__ */ jsxs(
638
+ DropdownMenuTrigger,
639
+ {
640
+ render: /* @__PURE__ */ jsx(
641
+ SidebarMenuButton,
642
+ {
643
+ className: cn(
644
+ "h-10 py-1.5 bg-sidebar-accent/50 hover:bg-sidebar-accent transition-colors",
645
+ isCollapsed && !isMobile && "justify-center"
646
+ ),
647
+ tooltip: isCollapsed ? selected.name : void 0
648
+ }
649
+ ),
650
+ children: [
651
+ /* @__PURE__ */ jsx(
652
+ SidebarProjectDisplay,
653
+ {
654
+ project: selected,
655
+ Icon,
656
+ isCollapsed,
657
+ isMobile
658
+ }
659
+ ),
660
+ (!isCollapsed || isMobile) && /* @__PURE__ */ jsx(ChevronsUpDown, { className: "h-3 w-3 text-muted-foreground shrink-0" })
661
+ ]
662
+ }
663
+ ),
664
+ /* @__PURE__ */ jsx(
665
+ DropdownContent,
666
+ {
667
+ items,
668
+ selected,
669
+ onSelect,
670
+ label,
671
+ renderItem,
672
+ isMobile
673
+ }
674
+ )
675
+ ] }) }) });
676
+ }
677
+ function BreadcrumbNav({ items }) {
678
+ return /* @__PURE__ */ jsx(Breadcrumb, { children: /* @__PURE__ */ jsx(BreadcrumbList, { children: items.map((item, index) => /* @__PURE__ */ jsxs(React4.Fragment, { children: [
679
+ /* @__PURE__ */ jsx(BreadcrumbItem, { className: item.current ? "" : "hidden md:block", children: item.current ? /* @__PURE__ */ jsx(BreadcrumbPage, { children: item.label }) : /* @__PURE__ */ jsx(BreadcrumbLink, { render: /* @__PURE__ */ jsx(Link3, { href: item.href || "#" }), children: item.label }) }),
680
+ index < items.length - 1 && /* @__PURE__ */ jsx(BreadcrumbSeparator, { className: "hidden md:block" })
681
+ ] }, `breadcrumb-${index}`)) }) });
682
+ }
683
+ function DashboardHeader({
684
+ breadcrumbs,
685
+ leftContent,
686
+ rightContent,
687
+ showSidebarTrigger = true,
688
+ className,
689
+ children
690
+ }) {
691
+ return /* @__PURE__ */ jsxs(
692
+ "header",
693
+ {
694
+ className: cn(
695
+ "flex h-12 shrink-0 items-center justify-between gap-2",
696
+ className
697
+ ),
698
+ children: [
699
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
700
+ showSidebarTrigger && /* @__PURE__ */ jsxs(Fragment, { children: [
701
+ /* @__PURE__ */ jsx(SidebarTrigger, { className: "-ml-1" }),
702
+ /* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "mr-2 h-4" })
703
+ ] }),
704
+ children ? children : /* @__PURE__ */ jsxs(Fragment, { children: [
705
+ breadcrumbs && breadcrumbs.length > 0 && /* @__PURE__ */ jsx(BreadcrumbNav, { items: breadcrumbs }),
706
+ leftContent
707
+ ] })
708
+ ] }),
709
+ rightContent && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: rightContent })
710
+ ]
711
+ }
712
+ );
713
+ }
714
+ function InsetSidebar({
715
+ brand,
716
+ navigation,
717
+ secondaryNavigation,
718
+ project,
719
+ user,
720
+ headerContent,
721
+ ariaLabel = "Navigation Menu",
722
+ className,
723
+ children
724
+ }) {
725
+ const { isMobile } = useSidebar();
726
+ return /* @__PURE__ */ jsxs(Sidebar, { variant: "inset", collapsible: "icon", className, children: [
727
+ isMobile && /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
728
+ /* @__PURE__ */ jsx(SheetTitle, { children: ariaLabel }),
729
+ /* @__PURE__ */ jsx(SheetDescription, { children: "Application navigation menu containing links to different sections" })
730
+ ] }),
731
+ /* @__PURE__ */ jsxs(SidebarHeader, { className: "gap-1", children: [
732
+ /* @__PURE__ */ jsx(
733
+ SidebarBrand,
734
+ {
735
+ title: brand.title,
736
+ icon: brand.icon,
737
+ href: brand.href
738
+ }
739
+ ),
740
+ project && /* @__PURE__ */ jsx(
741
+ ProjectSwitcher,
742
+ {
743
+ items: project.items,
744
+ selected: project.selected,
745
+ onSelect: project.onSelect,
746
+ isLoading: project.isLoading,
747
+ label: project.label,
748
+ icon: project.icon
749
+ }
750
+ ),
751
+ headerContent
752
+ ] }),
753
+ /* @__PURE__ */ jsx(SidebarContent, { children: children || /* @__PURE__ */ jsxs(Fragment, { children: [
754
+ /* @__PURE__ */ jsx(SidebarNav, { groups: navigation }),
755
+ secondaryNavigation && /* @__PURE__ */ jsx(SidebarNav, { groups: secondaryNavigation, className: "mt-auto" })
756
+ ] }) }),
757
+ user && /* @__PURE__ */ jsx(SidebarFooter, { children: /* @__PURE__ */ jsx(
758
+ SidebarUserMenu,
759
+ {
760
+ user: user.data,
761
+ menuItems: user.menuItems,
762
+ onLogout: user.onLogout
763
+ }
764
+ ) })
765
+ ] });
766
+ }
767
+ var SIDEBAR_RAIL_WIDTH = "3.5rem";
768
+ var SIDEBAR_PANEL_WIDTH = "13rem";
769
+ var SIDEBAR_WIDTH_EXPANDED = "16.5rem";
770
+ var SIDEBAR_WIDTH_COLLAPSED = "3.5rem";
771
+ var SIDEBAR_PADDING = "0.5rem";
772
+ var railVariants = {
773
+ default: "bg-sidebar",
774
+ dark: "bg-zinc-900 dark:bg-zinc-950",
775
+ primary: "bg-primary",
776
+ muted: "bg-muted"
777
+ };
778
+ var railTextVariants = {
779
+ default: "text-sidebar-foreground",
780
+ dark: "text-zinc-100",
781
+ primary: "text-primary-foreground",
782
+ muted: "text-muted-foreground"
783
+ };
784
+ function DualSidebar({
785
+ brand,
786
+ categories,
787
+ user,
788
+ defaultCategoryId,
789
+ onCategoryChange,
790
+ defaultCollapsed = false,
791
+ railVariant = "default",
792
+ ariaLabel = "Navigation Menu",
793
+ className
794
+ }) {
795
+ const [activeCategory, setActiveCategory] = React4.useState(
796
+ defaultCategoryId || (categories.length > 0 ? categories[0].id : null)
797
+ );
798
+ const [isExpanded, setIsExpanded] = React4.useState(!defaultCollapsed);
799
+ const { isMobile } = useSidebar();
800
+ const handleCategorySelect = (id) => {
801
+ setActiveCategory(id);
802
+ onCategoryChange?.(id);
803
+ if (!isExpanded) {
804
+ setIsExpanded(true);
805
+ }
806
+ };
807
+ const toggleExpanded = () => {
808
+ setIsExpanded(!isExpanded);
809
+ };
810
+ const activeCategoryData = categories.find((c) => c.id === activeCategory) || null;
811
+ const currentWidth = isExpanded ? SIDEBAR_WIDTH_EXPANDED : SIDEBAR_WIDTH_COLLAPSED;
812
+ const totalWidth = `calc(${currentWidth} + ${SIDEBAR_PADDING} * 2)`;
813
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
814
+ "div",
815
+ {
816
+ className: "group peer text-sidebar-foreground hidden md:block",
817
+ "data-state": "expanded",
818
+ "data-collapsible": "",
819
+ "data-variant": "inset",
820
+ "data-side": "left",
821
+ "data-slot": "sidebar",
822
+ children: [
823
+ /* @__PURE__ */ jsx(
824
+ "div",
825
+ {
826
+ "data-slot": "sidebar-gap",
827
+ className: "relative bg-transparent transition-[width] duration-200 ease-linear",
828
+ style: { width: totalWidth }
829
+ }
830
+ ),
831
+ /* @__PURE__ */ jsx(
832
+ "div",
833
+ {
834
+ "data-slot": "sidebar-container",
835
+ className: cn(
836
+ "fixed inset-y-0 left-0 z-10 hidden h-svh transition-[width] duration-200 ease-linear md:flex",
837
+ className
838
+ ),
839
+ style: {
840
+ width: totalWidth,
841
+ padding: SIDEBAR_PADDING
842
+ },
843
+ children: /* @__PURE__ */ jsxs(
844
+ "div",
845
+ {
846
+ "data-sidebar": "sidebar",
847
+ "data-slot": "sidebar-inner",
848
+ className: "bg-sidebar flex h-full w-full flex-row overflow-hidden rounded-lg border border-sidebar-border shadow-sm",
849
+ children: [
850
+ isMobile && /* @__PURE__ */ jsxs("span", { className: "sr-only", children: [
851
+ /* @__PURE__ */ jsx(SheetTitle, { children: ariaLabel }),
852
+ /* @__PURE__ */ jsx(SheetDescription, { children: "Navigation menu with category icons and expanded content" })
853
+ ] }),
854
+ /* @__PURE__ */ jsxs(
855
+ "div",
856
+ {
857
+ className: cn(
858
+ "flex flex-col shrink-0 transition-colors",
859
+ railVariants[railVariant],
860
+ railTextVariants[railVariant],
861
+ isExpanded && "border-r border-sidebar-border"
862
+ ),
863
+ style: { width: SIDEBAR_RAIL_WIDTH, minWidth: SIDEBAR_RAIL_WIDTH },
864
+ children: [
865
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center p-2 h-14", children: /* @__PURE__ */ jsxs(Tooltip, { children: [
866
+ /* @__PURE__ */ jsx(
867
+ TooltipTrigger,
868
+ {
869
+ render: /* @__PURE__ */ jsx(
870
+ Link3,
871
+ {
872
+ href: brand.href || "/",
873
+ className: cn(
874
+ "flex items-center justify-center h-10 w-10 rounded-lg shadow-sm transition-colors",
875
+ railVariant === "dark" || railVariant === "primary" ? "bg-white/10 hover:bg-white/20 text-inherit" : "bg-sidebar-primary text-sidebar-primary-foreground"
876
+ )
877
+ }
878
+ ),
879
+ children: brand.icon
880
+ }
881
+ ),
882
+ /* @__PURE__ */ jsx(TooltipContent, { side: "right", children: brand.title })
883
+ ] }) }),
884
+ /* @__PURE__ */ jsx("div", { className: "flex-1 flex flex-col gap-1 p-2", children: categories.map((category) => {
885
+ const Icon = category.icon;
886
+ const isActive = activeCategory === category.id;
887
+ return /* @__PURE__ */ jsxs(Tooltip, { children: [
888
+ /* @__PURE__ */ jsx(
889
+ TooltipTrigger,
890
+ {
891
+ render: /* @__PURE__ */ jsx(
892
+ "button",
893
+ {
894
+ onClick: () => handleCategorySelect(category.id),
895
+ className: cn(
896
+ "flex items-center justify-center h-10 w-10 rounded-lg transition-colors",
897
+ isActive ? railVariant === "dark" || railVariant === "primary" ? "bg-white/20" : "bg-sidebar-accent text-sidebar-accent-foreground" : railVariant === "dark" || railVariant === "primary" ? "hover:bg-white/10" : "hover:bg-sidebar-accent/50"
898
+ )
899
+ }
900
+ ),
901
+ children: /* @__PURE__ */ jsx(Icon, { className: "h-5 w-5" })
902
+ }
903
+ ),
904
+ /* @__PURE__ */ jsx(TooltipContent, { side: "right", children: category.name })
905
+ ] }, category.id);
906
+ }) }),
907
+ /* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsxs(Tooltip, { children: [
908
+ /* @__PURE__ */ jsx(
909
+ TooltipTrigger,
910
+ {
911
+ render: /* @__PURE__ */ jsx(
912
+ "button",
913
+ {
914
+ onClick: toggleExpanded,
915
+ className: cn(
916
+ "flex items-center justify-center h-10 w-10 rounded-lg transition-colors",
917
+ railVariant === "dark" || railVariant === "primary" ? "hover:bg-white/10" : "hover:bg-sidebar-accent/50"
918
+ )
919
+ }
920
+ ),
921
+ children: isExpanded ? /* @__PURE__ */ jsx(ChevronLeft, { className: "h-5 w-5" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-5 w-5" })
922
+ }
923
+ ),
924
+ /* @__PURE__ */ jsx(TooltipContent, { side: "right", children: isExpanded ? "Collapse sidebar" : "Expand sidebar" })
925
+ ] }) })
926
+ ]
927
+ }
928
+ ),
929
+ /* @__PURE__ */ jsx(
930
+ "div",
931
+ {
932
+ className: cn(
933
+ "flex flex-col bg-sidebar overflow-hidden transition-[width,opacity] duration-200 ease-linear",
934
+ isExpanded ? "opacity-100" : "opacity-0 w-0"
935
+ ),
936
+ style: { width: isExpanded ? SIDEBAR_PANEL_WIDTH : 0 },
937
+ children: activeCategoryData ? /* @__PURE__ */ jsxs(Fragment, { children: [
938
+ /* @__PURE__ */ jsx(SidebarHeader, { className: "h-14 border-b border-sidebar-border px-4 flex items-center shrink-0", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
939
+ /* @__PURE__ */ jsx(activeCategoryData.icon, { className: "h-5 w-5 text-sidebar-foreground" }),
940
+ /* @__PURE__ */ jsx("span", { className: "font-semibold text-sidebar-foreground truncate", children: activeCategoryData.name })
941
+ ] }) }),
942
+ /* @__PURE__ */ jsx(SidebarContent, { className: "flex-1 overflow-y-auto", children: /* @__PURE__ */ jsxs(SidebarGroup, { className: "p-2", children: [
943
+ /* @__PURE__ */ jsxs(SidebarGroupLabel, { className: "px-2 text-xs text-sidebar-foreground/60", children: [
944
+ activeCategoryData.name,
945
+ " Menu"
946
+ ] }),
947
+ /* @__PURE__ */ jsx(SidebarMenu, { children: activeCategoryData.items.map((item, idx) => {
948
+ const Icon = item.icon;
949
+ return /* @__PURE__ */ jsx(
950
+ SidebarMenuItem,
951
+ {
952
+ children: /* @__PURE__ */ jsxs(
953
+ SidebarMenuButton,
954
+ {
955
+ isActive: item.isActive,
956
+ render: /* @__PURE__ */ jsx(Link3, { href: item.url }),
957
+ children: [
958
+ Icon && /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }),
959
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: item.title }),
960
+ item.badge && /* @__PURE__ */ jsx("span", { className: "ml-auto text-xs bg-sidebar-accent text-sidebar-accent-foreground px-1.5 py-0.5 rounded shrink-0", children: item.badge })
961
+ ]
962
+ }
963
+ )
964
+ },
965
+ `${activeCategoryData.id}-${item.title}-${idx}`
966
+ );
967
+ }) })
968
+ ] }) }),
969
+ user && /* @__PURE__ */ jsx(SidebarFooter, { className: "border-t border-sidebar-border shrink-0", children: /* @__PURE__ */ jsx(
970
+ SidebarUserMenu,
971
+ {
972
+ user: user.data,
973
+ menuItems: user.menuItems,
974
+ onLogout: user.onLogout
975
+ }
976
+ ) })
977
+ ] }) : /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-center text-sidebar-foreground/60 text-sm", children: "Select a category" })
978
+ }
979
+ )
980
+ ]
981
+ }
982
+ )
983
+ }
984
+ )
985
+ ]
986
+ }
987
+ ) });
988
+ }
989
+
990
+ export { DashboardHeader, DualSidebar, HeaderSection, InsetSidebar, PageHeader, ProjectSwitcher, SidebarBrand, SidebarNav, SidebarNavGroup, SidebarNavItem, SidebarUserMenu, cn };
991
+ //# sourceMappingURL=dashboard.js.map
992
+ //# sourceMappingURL=dashboard.js.map