@fayz-ai/ui 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ChartWidgetInner-GDE5PBTR.js → ChartWidgetInner-IOLIUYTB.js} +21 -8
- package/dist/ChartWidgetInner-IOLIUYTB.js.map +1 -0
- package/dist/analytics/AnalyticsCard.d.ts.map +1 -1
- package/dist/analytics/AnalyticsControls.d.ts.map +1 -1
- package/dist/chunk-3OVZ5JJQ.js +540 -0
- package/dist/chunk-3OVZ5JJQ.js.map +1 -0
- package/dist/{chunk-UZYXFEQS.js → chunk-4GK6IHOI.js} +16 -3
- package/dist/chunk-4GK6IHOI.js.map +1 -0
- package/dist/{chunk-46UZAKFJ.js → chunk-5KMAEQA3.js} +7 -6
- package/dist/chunk-5KMAEQA3.js.map +1 -0
- package/dist/chunk-AASANYXN.js +601 -0
- package/dist/chunk-AASANYXN.js.map +1 -0
- package/dist/{chunk-LFZFBN3P.js → chunk-FFJ2C5YH.js} +11 -61
- package/dist/chunk-FFJ2C5YH.js.map +1 -0
- package/dist/{chunk-5KAGNW45.js → chunk-J7F3Z52K.js} +4 -4
- package/dist/{chunk-5KAGNW45.js.map → chunk-J7F3Z52K.js.map} +1 -1
- package/dist/{chunk-2EFRFYGF.js → chunk-KD2V3TAX.js} +180 -33
- package/dist/chunk-KD2V3TAX.js.map +1 -0
- package/dist/{chunk-MVH64JFG.js → chunk-NA3GE4H3.js} +488 -537
- package/dist/chunk-NA3GE4H3.js.map +1 -0
- package/dist/chunk-OKZ6WQB3.js +57 -0
- package/dist/chunk-OKZ6WQB3.js.map +1 -0
- package/dist/{chunk-77CUIMOI.js → chunk-SLWTKHNY.js} +103 -158
- package/dist/chunk-SLWTKHNY.js.map +1 -0
- package/dist/dashboard/ChartWidgetInner.d.ts.map +1 -1
- package/dist/dashboard/index.js +5 -4
- package/dist/icons.d.ts.map +1 -1
- package/dist/icons.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30 -16
- package/dist/index.js.map +1 -1
- package/dist/layout/AppShell.d.ts +7 -2
- package/dist/layout/AppShell.d.ts.map +1 -1
- package/dist/layout/Sidebar.d.ts +27 -4
- package/dist/layout/Sidebar.d.ts.map +1 -1
- package/dist/layout/Topbar.d.ts +10 -3
- package/dist/layout/Topbar.d.ts.map +1 -1
- package/dist/layout/index.js +5 -4
- package/dist/primitives/SearchCombobox.d.ts +9 -1
- package/dist/primitives/SearchCombobox.d.ts.map +1 -1
- package/dist/primitives/color-palette.d.ts +24 -0
- package/dist/primitives/color-palette.d.ts.map +1 -0
- package/dist/primitives/header-tabs.d.ts +11 -1
- package/dist/primitives/header-tabs.d.ts.map +1 -1
- package/dist/primitives/image-drop.d.ts +28 -0
- package/dist/primitives/image-drop.d.ts.map +1 -0
- package/dist/primitives/index.d.ts +8 -3
- package/dist/primitives/index.d.ts.map +1 -1
- package/dist/primitives/index.js +7 -5
- package/dist/primitives/list-view.d.ts +7 -1
- package/dist/primitives/list-view.d.ts.map +1 -1
- package/dist/primitives/option-select.d.ts +46 -0
- package/dist/primitives/option-select.d.ts.map +1 -0
- package/dist/primitives/page-toolbar.d.ts +20 -1
- package/dist/primitives/page-toolbar.d.ts.map +1 -1
- package/dist/primitives/sheet.d.ts.map +1 -1
- package/dist/primitives/step-progress.d.ts +20 -0
- package/dist/primitives/step-progress.d.ts.map +1 -0
- package/dist/primitives/use-row-selection.d.ts +50 -0
- package/dist/primitives/use-row-selection.d.ts.map +1 -0
- package/dist/styles.css +20 -0
- package/dist/wizard/Wizard.d.ts +38 -0
- package/dist/wizard/Wizard.d.ts.map +1 -0
- package/dist/wizard/WizardField.d.ts +22 -0
- package/dist/wizard/WizardField.d.ts.map +1 -0
- package/dist/wizard/index.d.ts +6 -0
- package/dist/wizard/index.d.ts.map +1 -0
- package/dist/wizard/index.js +5 -0
- package/dist/wizard/index.js.map +1 -0
- package/dist/wizard/logic.d.ts +39 -0
- package/dist/wizard/logic.d.ts.map +1 -0
- package/dist/wizard/types.d.ts +95 -0
- package/dist/wizard/types.d.ts.map +1 -0
- package/dist/wizard/useWizard.d.ts +47 -0
- package/dist/wizard/useWizard.d.ts.map +1 -0
- package/package.json +12 -6
- package/dist/ChartWidgetInner-GDE5PBTR.js.map +0 -1
- package/dist/chunk-2EFRFYGF.js.map +0 -1
- package/dist/chunk-46UZAKFJ.js.map +0 -1
- package/dist/chunk-77CUIMOI.js.map +0 -1
- package/dist/chunk-LFZFBN3P.js.map +0 -1
- package/dist/chunk-MVH64JFG.js.map +0 -1
- package/dist/chunk-UZYXFEQS.js.map +0 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { useHasPageHeaderHost, usePageHeader, useLayoutStore, useRegisterPageActions, useHasPageHeaderBack, usePageHeaderSlot, useHasPageHeaderOutlet, useHasPageActions, usePageHeaderHost } from './chunk-FFJ2C5YH.js';
|
|
2
|
+
import { cn } from './chunk-OKZ6WQB3.js';
|
|
3
|
+
import { ICON_MAP } from './chunk-4GK6IHOI.js';
|
|
3
4
|
import * as React7 from 'react';
|
|
4
5
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
5
|
-
import { X, Loader2, ArrowLeft,
|
|
6
|
+
import { X, Loader2, ArrowLeft, Search, Bell, PanelLeft, PanelLeftClose, Menu, Crown, ChevronDown, ChevronRight, ChevronLeft, ExternalLink, CreditCard, Sparkles, Home, Plus, PiggyBank, Wallet, MessageCircle, Settings, Calendar, ArrowLeftRight, Receipt, UserCog, LogOut } from 'lucide-react';
|
|
6
7
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
8
|
import { useTranslation, useNavReferrer, routeModule, navHistoryBack } from '@fayz-ai/core';
|
|
8
9
|
import * as Popover from '@radix-ui/react-popover';
|
|
@@ -40,12 +41,26 @@ var SheetOverlay = React7.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
40
41
|
}
|
|
41
42
|
));
|
|
42
43
|
SheetOverlay.displayName = "SheetOverlay";
|
|
43
|
-
var SheetContent = React7.forwardRef(({ className, children, width, hideClose, overlay = "blur", ...props }, ref) => /* @__PURE__ */ jsxs(SheetPortal, { children: [
|
|
44
|
+
var SheetContent = React7.forwardRef(({ className, children, width, hideClose, overlay = "blur", onPointerDownOutside, onInteractOutside, ...props }, ref) => /* @__PURE__ */ jsxs(SheetPortal, { children: [
|
|
44
45
|
/* @__PURE__ */ jsx(SheetOverlay, { className: overlay === "none" ? "bg-transparent backdrop-blur-0" : overlay === "dim" ? "backdrop-blur-0" : void 0 }),
|
|
45
46
|
/* @__PURE__ */ jsxs(
|
|
46
47
|
DialogPrimitive.Content,
|
|
47
48
|
{
|
|
48
49
|
ref,
|
|
50
|
+
onPointerDownOutside: (e) => {
|
|
51
|
+
const target = e.target;
|
|
52
|
+
if (target.closest("[data-modal-passthrough]") || target.closest("[data-radix-popper-content-wrapper]")) {
|
|
53
|
+
e.preventDefault();
|
|
54
|
+
}
|
|
55
|
+
onPointerDownOutside?.(e);
|
|
56
|
+
},
|
|
57
|
+
onInteractOutside: (e) => {
|
|
58
|
+
const target = e.target;
|
|
59
|
+
if (target.closest("[data-modal-passthrough]") || target.closest("[data-radix-popper-content-wrapper]")) {
|
|
60
|
+
e.preventDefault();
|
|
61
|
+
}
|
|
62
|
+
onInteractOutside?.(e);
|
|
63
|
+
},
|
|
49
64
|
className: cn(
|
|
50
65
|
"fayz-glass-surface saas-sheet-content fixed inset-y-0 right-0 z-50 flex flex-col border-l bg-card shadow-2xl outline-none",
|
|
51
66
|
"w-full",
|
|
@@ -318,370 +333,6 @@ function PageHeader({ title, onBack, parentLabel, backLabel }) {
|
|
|
318
333
|
if (hasHost) return null;
|
|
319
334
|
return /* @__PURE__ */ jsx("div", { className: "mb-4", children: node });
|
|
320
335
|
}
|
|
321
|
-
function TopbarUserMenu({
|
|
322
|
-
user,
|
|
323
|
-
userPlan,
|
|
324
|
-
billingLabel = "Subscription",
|
|
325
|
-
onSignOut,
|
|
326
|
-
onProfile,
|
|
327
|
-
onSettings,
|
|
328
|
-
onBilling,
|
|
329
|
-
userMenuExtras
|
|
330
|
-
}) {
|
|
331
|
-
const [open, setOpen] = React7.useState(false);
|
|
332
|
-
if (!user) return null;
|
|
333
|
-
const initial = (user.fullName?.trim()?.[0] ?? user.email?.[0] ?? "?").toUpperCase();
|
|
334
|
-
const item = (label, onClick, Icon) => onClick ? /* @__PURE__ */ jsxs(
|
|
335
|
-
"button",
|
|
336
|
-
{
|
|
337
|
-
onClick: () => {
|
|
338
|
-
setOpen(false);
|
|
339
|
-
onClick();
|
|
340
|
-
},
|
|
341
|
-
className: "flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-sm text-popover-foreground transition-colors hover:bg-muted/70",
|
|
342
|
-
children: [
|
|
343
|
-
Icon && /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 text-muted-foreground" }),
|
|
344
|
-
/* @__PURE__ */ jsx("span", { children: label })
|
|
345
|
-
]
|
|
346
|
-
},
|
|
347
|
-
label
|
|
348
|
-
) : null;
|
|
349
|
-
return /* @__PURE__ */ jsxs(Popover.Root, { open, onOpenChange: setOpen, children: [
|
|
350
|
-
/* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
351
|
-
"button",
|
|
352
|
-
{
|
|
353
|
-
"aria-label": "User menu",
|
|
354
|
-
className: "ml-1 flex h-9 w-9 items-center justify-center overflow-hidden rounded-full bg-primary text-xs font-semibold text-primary-foreground ring-2 ring-transparent transition hover:ring-sidebar-border",
|
|
355
|
-
children: user.avatarUrl ? (
|
|
356
|
-
// eslint-disable-next-line @next/next/no-img-element
|
|
357
|
-
/* @__PURE__ */ jsx("img", { src: user.avatarUrl, alt: "", className: "h-full w-full object-cover" })
|
|
358
|
-
) : initial
|
|
359
|
-
}
|
|
360
|
-
) }),
|
|
361
|
-
/* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsxs(
|
|
362
|
-
Popover.Content,
|
|
363
|
-
{
|
|
364
|
-
align: "end",
|
|
365
|
-
sideOffset: 8,
|
|
366
|
-
className: "fayz-glass-surface z-50 min-w-[220px] rounded-xl border border-border bg-popover p-1.5 shadow-lg animate-in fade-in-0 zoom-in-95",
|
|
367
|
-
children: [
|
|
368
|
-
/* @__PURE__ */ jsxs("div", { className: "border-b border-border px-3 py-2", children: [
|
|
369
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium text-foreground", children: user.fullName || user.email }),
|
|
370
|
-
/* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: user.email })
|
|
371
|
-
] }),
|
|
372
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-1 space-y-0.5", children: [
|
|
373
|
-
item("Perfil", onProfile, UserCog),
|
|
374
|
-
item("Configura\xE7\xF5es", onSettings, Settings),
|
|
375
|
-
onBilling && /* @__PURE__ */ jsxs(
|
|
376
|
-
"button",
|
|
377
|
-
{
|
|
378
|
-
onClick: () => {
|
|
379
|
-
setOpen(false);
|
|
380
|
-
onBilling();
|
|
381
|
-
},
|
|
382
|
-
className: "flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-sm text-popover-foreground transition-colors hover:bg-muted/70",
|
|
383
|
-
children: [
|
|
384
|
-
/* @__PURE__ */ jsx(CreditCard, { className: "h-4 w-4 text-muted-foreground" }),
|
|
385
|
-
/* @__PURE__ */ jsx("span", { className: "flex-1 text-left", children: billingLabel }),
|
|
386
|
-
userPlan && /* @__PURE__ */ jsxs(
|
|
387
|
-
"span",
|
|
388
|
-
{
|
|
389
|
-
className: userPlan.paid ? "inline-flex items-center gap-1 rounded-full border border-amber-400/40 bg-amber-400/15 px-2 py-0.5 text-[10px] font-semibold text-amber-600 dark:text-amber-300" : "inline-flex items-center gap-1 rounded-full border border-border bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground",
|
|
390
|
-
children: [
|
|
391
|
-
userPlan.paid ? /* @__PURE__ */ jsx(Crown, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(Sparkles, { className: "h-3 w-3" }),
|
|
392
|
-
userPlan.label
|
|
393
|
-
]
|
|
394
|
-
}
|
|
395
|
-
)
|
|
396
|
-
]
|
|
397
|
-
},
|
|
398
|
-
"billing"
|
|
399
|
-
),
|
|
400
|
-
userMenuExtras?.map((e) => item(e.label, e.onClick)),
|
|
401
|
-
onSignOut && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
402
|
-
/* @__PURE__ */ jsx("div", { className: "my-1 border-t border-border" }),
|
|
403
|
-
item("Sair", onSignOut, LogOut)
|
|
404
|
-
] })
|
|
405
|
-
] })
|
|
406
|
-
]
|
|
407
|
-
}
|
|
408
|
-
) })
|
|
409
|
-
] });
|
|
410
|
-
}
|
|
411
|
-
var ICON_MAP2 = {
|
|
412
|
-
Home,
|
|
413
|
-
Users,
|
|
414
|
-
Settings,
|
|
415
|
-
CreditCard,
|
|
416
|
-
Bell,
|
|
417
|
-
Calendar,
|
|
418
|
-
CalendarClock,
|
|
419
|
-
Package,
|
|
420
|
-
Activity,
|
|
421
|
-
BarChart3,
|
|
422
|
-
FileText,
|
|
423
|
-
Mail,
|
|
424
|
-
DollarSign,
|
|
425
|
-
Megaphone,
|
|
426
|
-
ShoppingCart,
|
|
427
|
-
ShoppingBag,
|
|
428
|
-
Target,
|
|
429
|
-
Wrench,
|
|
430
|
-
ClipboardList,
|
|
431
|
-
ClipboardCheck,
|
|
432
|
-
Briefcase,
|
|
433
|
-
UserCog,
|
|
434
|
-
BookOpen,
|
|
435
|
-
MessageCircle,
|
|
436
|
-
Globe,
|
|
437
|
-
BookOpenCheck,
|
|
438
|
-
Percent,
|
|
439
|
-
Tag,
|
|
440
|
-
Tags,
|
|
441
|
-
Camera,
|
|
442
|
-
UtensilsCrossed,
|
|
443
|
-
Search,
|
|
444
|
-
MapPin,
|
|
445
|
-
Handshake,
|
|
446
|
-
Contact,
|
|
447
|
-
Building2,
|
|
448
|
-
ChevronDown,
|
|
449
|
-
Filter,
|
|
450
|
-
Plus,
|
|
451
|
-
Shield,
|
|
452
|
-
List,
|
|
453
|
-
ListChecks,
|
|
454
|
-
FolderOpen,
|
|
455
|
-
Dog,
|
|
456
|
-
Cat,
|
|
457
|
-
PawPrint,
|
|
458
|
-
Heart,
|
|
459
|
-
LayoutTemplate,
|
|
460
|
-
LeafyGreen,
|
|
461
|
-
Apple,
|
|
462
|
-
Egg,
|
|
463
|
-
Wheat,
|
|
464
|
-
ArrowDownCircle,
|
|
465
|
-
ArrowUpCircle,
|
|
466
|
-
ArrowLeftRight,
|
|
467
|
-
Plug,
|
|
468
|
-
SlidersHorizontal,
|
|
469
|
-
TableProperties,
|
|
470
|
-
Landmark,
|
|
471
|
-
Receipt,
|
|
472
|
-
TrendingUp,
|
|
473
|
-
CircleDollarSign,
|
|
474
|
-
Clock,
|
|
475
|
-
AlertTriangle,
|
|
476
|
-
Sparkles,
|
|
477
|
-
Wallet,
|
|
478
|
-
Warehouse,
|
|
479
|
-
Ruler,
|
|
480
|
-
ArrowUpRight,
|
|
481
|
-
ArrowDownRight,
|
|
482
|
-
UserPlus,
|
|
483
|
-
UserX,
|
|
484
|
-
TreePalm,
|
|
485
|
-
Boxes,
|
|
486
|
-
Box,
|
|
487
|
-
FileCheck2,
|
|
488
|
-
PartyPopper,
|
|
489
|
-
Radio,
|
|
490
|
-
CalendarDays,
|
|
491
|
-
BadgeDollarSign,
|
|
492
|
-
Banknote,
|
|
493
|
-
Layers,
|
|
494
|
-
Music,
|
|
495
|
-
Eye,
|
|
496
|
-
ListMusic,
|
|
497
|
-
Disc3,
|
|
498
|
-
UsersRound,
|
|
499
|
-
Mic,
|
|
500
|
-
CalendarCheck2,
|
|
501
|
-
CalendarX,
|
|
502
|
-
ListPlus,
|
|
503
|
-
Map,
|
|
504
|
-
Ban,
|
|
505
|
-
Clock3,
|
|
506
|
-
Inbox,
|
|
507
|
-
UserCheck,
|
|
508
|
-
Star,
|
|
509
|
-
Zap,
|
|
510
|
-
Clapperboard,
|
|
511
|
-
Newspaper,
|
|
512
|
-
GraduationCap,
|
|
513
|
-
Repeat
|
|
514
|
-
};
|
|
515
|
-
function getIcon(name) {
|
|
516
|
-
return ICON_MAP2[name] ?? Home;
|
|
517
|
-
}
|
|
518
|
-
function NavDropdown({ item, currentPath, onNavigate }) {
|
|
519
|
-
const [open, setOpen] = React7.useState(false);
|
|
520
|
-
const Icon = getIcon(item.icon);
|
|
521
|
-
const isChildActive = item.children?.some(
|
|
522
|
-
(child) => currentPath === child.route || currentPath.startsWith(child.route + "/")
|
|
523
|
-
);
|
|
524
|
-
return /* @__PURE__ */ jsxs(Popover.Root, { open, onOpenChange: setOpen, children: [
|
|
525
|
-
/* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
526
|
-
"button",
|
|
527
|
-
{
|
|
528
|
-
"data-nav-active": isChildActive || void 0,
|
|
529
|
-
className: cn(
|
|
530
|
-
"flex items-center gap-1.5 whitespace-nowrap border-b-2 px-3 py-2 text-sm transition-colors",
|
|
531
|
-
isChildActive ? "border-sidebar-accent-foreground font-semibold text-sidebar-foreground" : "border-transparent text-sidebar-muted hover:text-sidebar-foreground"
|
|
532
|
-
),
|
|
533
|
-
children: [
|
|
534
|
-
/* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }),
|
|
535
|
-
/* @__PURE__ */ jsx("span", { children: item.label }),
|
|
536
|
-
/* @__PURE__ */ jsx(ChevronDown, { className: cn("h-3 w-3 transition-transform", open && "rotate-180") })
|
|
537
|
-
]
|
|
538
|
-
}
|
|
539
|
-
) }),
|
|
540
|
-
/* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(
|
|
541
|
-
Popover.Content,
|
|
542
|
-
{
|
|
543
|
-
align: "start",
|
|
544
|
-
sideOffset: 4,
|
|
545
|
-
className: "fayz-glass-surface z-50 min-w-[200px] rounded-xl border border-border bg-popover p-1.5 shadow-lg animate-in fade-in-0 zoom-in-95",
|
|
546
|
-
children: item.children?.map((child) => {
|
|
547
|
-
const ChildIcon = getIcon(child.icon);
|
|
548
|
-
const isActive = currentPath === child.route || currentPath.startsWith(child.route + "/");
|
|
549
|
-
return /* @__PURE__ */ jsxs(
|
|
550
|
-
"button",
|
|
551
|
-
{
|
|
552
|
-
onClick: () => {
|
|
553
|
-
onNavigate(child.route);
|
|
554
|
-
setOpen(false);
|
|
555
|
-
},
|
|
556
|
-
className: cn(
|
|
557
|
-
"flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-sm transition-colors",
|
|
558
|
-
isActive ? "bg-muted font-medium text-foreground" : "text-popover-foreground hover:bg-muted/70"
|
|
559
|
-
),
|
|
560
|
-
children: [
|
|
561
|
-
/* @__PURE__ */ jsx(ChildIcon, { className: "h-4 w-4 text-muted-foreground" }),
|
|
562
|
-
/* @__PURE__ */ jsx("span", { children: child.label })
|
|
563
|
-
]
|
|
564
|
-
},
|
|
565
|
-
child.id
|
|
566
|
-
);
|
|
567
|
-
})
|
|
568
|
-
}
|
|
569
|
-
) })
|
|
570
|
-
] });
|
|
571
|
-
}
|
|
572
|
-
function Topbar({
|
|
573
|
-
navigation,
|
|
574
|
-
logo,
|
|
575
|
-
user,
|
|
576
|
-
onMenuClick,
|
|
577
|
-
orgSwitcher,
|
|
578
|
-
leftContent,
|
|
579
|
-
rightContent,
|
|
580
|
-
currentPath = "/",
|
|
581
|
-
onNavigate,
|
|
582
|
-
searchPlaceholder = "Search...",
|
|
583
|
-
onSignOut,
|
|
584
|
-
onProfile,
|
|
585
|
-
onSettings,
|
|
586
|
-
onBilling,
|
|
587
|
-
userPlan,
|
|
588
|
-
billingLabel,
|
|
589
|
-
userMenuExtras
|
|
590
|
-
}) {
|
|
591
|
-
const setCommandPaletteOpen = useLayoutStore((s) => s.setCommandPaletteOpen);
|
|
592
|
-
const mainNav = navigation.filter((item) => item.section === "main");
|
|
593
|
-
const secondaryNav = navigation.filter((item) => item.section === "secondary");
|
|
594
|
-
const allNav = [...mainNav, ...secondaryNav];
|
|
595
|
-
const handleNavigate = (route) => {
|
|
596
|
-
onNavigate?.(route);
|
|
597
|
-
};
|
|
598
|
-
return /* @__PURE__ */ jsxs("header", { "data-print": "hide", className: "sticky top-0 z-50 w-full shrink-0", children: [
|
|
599
|
-
/* @__PURE__ */ jsx("div", { className: "border-b border-sidebar-border bg-sidebar text-sidebar-foreground", children: /* @__PURE__ */ jsxs("div", { className: "flex h-14 w-full items-center justify-between px-4 md:px-6", children: [
|
|
600
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
601
|
-
onMenuClick && /* @__PURE__ */ jsx(
|
|
602
|
-
"button",
|
|
603
|
-
{
|
|
604
|
-
onClick: onMenuClick,
|
|
605
|
-
className: "inline-flex items-center justify-center rounded-md p-2 text-sidebar-foreground/70 hover:bg-sidebar/30 hover:text-sidebar-foreground md:hidden",
|
|
606
|
-
"aria-label": "Open menu",
|
|
607
|
-
children: /* @__PURE__ */ jsx(Menu, { className: "h-5 w-5" })
|
|
608
|
-
}
|
|
609
|
-
),
|
|
610
|
-
/* @__PURE__ */ jsx("div", { className: "hidden shrink-0 items-center md:flex", children: logo ?? /* @__PURE__ */ jsx("span", { className: "text-lg font-bold", children: "App" }) })
|
|
611
|
-
] }),
|
|
612
|
-
/* @__PURE__ */ jsx("div", { className: "mx-8 hidden max-w-sm flex-1 md:flex", children: /* @__PURE__ */ jsxs(
|
|
613
|
-
"button",
|
|
614
|
-
{
|
|
615
|
-
onClick: () => setCommandPaletteOpen(true),
|
|
616
|
-
className: "relative flex h-8 w-full items-center rounded-md border border-sidebar-border bg-sidebar-accent px-3 pl-8 text-sm text-sidebar-muted shadow-sm transition-colors hover:border-sidebar-foreground/25 hover:bg-sidebar-foreground/10 hover:text-sidebar-foreground",
|
|
617
|
-
children: [
|
|
618
|
-
/* @__PURE__ */ jsx(Search, { className: "absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-sidebar-muted" }),
|
|
619
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs", children: searchPlaceholder }),
|
|
620
|
-
/* @__PURE__ */ jsx("kbd", { className: "ml-auto hidden rounded border border-sidebar-border bg-sidebar-accent px-1.5 py-0.5 text-[10px] font-medium text-sidebar-muted sm:inline-block", children: "\u2318K" })
|
|
621
|
-
]
|
|
622
|
-
}
|
|
623
|
-
) }),
|
|
624
|
-
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-1", children: [
|
|
625
|
-
orgSwitcher && /* @__PURE__ */ jsx("div", { className: "hidden min-w-0 items-center md:flex", children: orgSwitcher }),
|
|
626
|
-
leftContent,
|
|
627
|
-
rightContent,
|
|
628
|
-
/* @__PURE__ */ jsx(
|
|
629
|
-
TopbarUserMenu,
|
|
630
|
-
{
|
|
631
|
-
user,
|
|
632
|
-
userPlan,
|
|
633
|
-
billingLabel,
|
|
634
|
-
onSignOut,
|
|
635
|
-
onProfile,
|
|
636
|
-
onSettings,
|
|
637
|
-
onBilling,
|
|
638
|
-
userMenuExtras
|
|
639
|
-
}
|
|
640
|
-
)
|
|
641
|
-
] })
|
|
642
|
-
] }) }),
|
|
643
|
-
/* @__PURE__ */ jsx("div", { className: "hidden md:block bg-sidebar", children: /* @__PURE__ */ jsx("div", { className: "flex h-11 w-full items-center px-4 md:px-6", children: /* @__PURE__ */ jsx("nav", { ref: (el) => {
|
|
644
|
-
if (!el) return;
|
|
645
|
-
const active = el.querySelector('[data-nav-active="true"]');
|
|
646
|
-
if (active) {
|
|
647
|
-
const left = active.offsetLeft - el.offsetWidth / 2 + active.offsetWidth / 2;
|
|
648
|
-
el.scrollTo({ left: Math.max(0, left), behavior: "smooth" });
|
|
649
|
-
}
|
|
650
|
-
}, className: "flex items-center gap-0.5 overflow-x-auto scrollbar-none", children: allNav.map((item) => {
|
|
651
|
-
if (item.children && item.children.length > 0) {
|
|
652
|
-
return /* @__PURE__ */ jsx(
|
|
653
|
-
NavDropdown,
|
|
654
|
-
{
|
|
655
|
-
item,
|
|
656
|
-
currentPath,
|
|
657
|
-
onNavigate: handleNavigate
|
|
658
|
-
},
|
|
659
|
-
item.id
|
|
660
|
-
);
|
|
661
|
-
}
|
|
662
|
-
const Icon = getIcon(item.icon);
|
|
663
|
-
const isActive = item.route === "/" ? currentPath === "/" : currentPath === item.route || currentPath.startsWith(item.route + "/");
|
|
664
|
-
return /* @__PURE__ */ jsxs(
|
|
665
|
-
"button",
|
|
666
|
-
{
|
|
667
|
-
"data-nav-active": isActive || void 0,
|
|
668
|
-
onClick: () => handleNavigate(item.route),
|
|
669
|
-
className: cn(
|
|
670
|
-
"flex items-center gap-1.5 whitespace-nowrap border-b-2 px-3 py-2 text-sm transition-colors",
|
|
671
|
-
isActive ? "border-primary font-semibold text-sidebar-foreground" : "border-transparent text-sidebar-muted hover:text-sidebar-foreground"
|
|
672
|
-
),
|
|
673
|
-
children: [
|
|
674
|
-
/* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }),
|
|
675
|
-
/* @__PURE__ */ jsx("span", { children: item.label }),
|
|
676
|
-
item.premium && /* @__PURE__ */ jsx(Crown, { className: "h-3 w-3 text-amber-500", "aria-hidden": true }),
|
|
677
|
-
item.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-primary px-1.5 py-0.5 text-[10px] font-semibold text-primary-foreground", children: item.badge })
|
|
678
|
-
]
|
|
679
|
-
},
|
|
680
|
-
item.id
|
|
681
|
-
);
|
|
682
|
-
}) }) }) })
|
|
683
|
-
] });
|
|
684
|
-
}
|
|
685
336
|
var GUTTER_PX = 8;
|
|
686
337
|
var CLOSE_DELAY_MS = 140;
|
|
687
338
|
var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React7.useLayoutEffect : React7.useEffect;
|
|
@@ -895,7 +546,7 @@ function FlyoutBody({
|
|
|
895
546
|
}
|
|
896
547
|
var RAIL_PUSH_MS = 260;
|
|
897
548
|
var useIsomorphicLayoutEffect2 = typeof window !== "undefined" ? React7.useLayoutEffect : React7.useEffect;
|
|
898
|
-
function
|
|
549
|
+
function getIcon(name) {
|
|
899
550
|
return ICON_MAP[name] ?? Home;
|
|
900
551
|
}
|
|
901
552
|
function shortcutKey() {
|
|
@@ -928,7 +579,7 @@ function NavItem({
|
|
|
928
579
|
onNavigate,
|
|
929
580
|
flyout
|
|
930
581
|
}) {
|
|
931
|
-
const Icon =
|
|
582
|
+
const Icon = getIcon(item.icon);
|
|
932
583
|
const isExternal = !!item.href;
|
|
933
584
|
const hoverProps = collapsed && flyout ? flyout.rowProps(flyoutContentOf(item)) : void 0;
|
|
934
585
|
const className = cn(
|
|
@@ -938,7 +589,7 @@ function NavItem({
|
|
|
938
589
|
// as cramped rather than as dense.
|
|
939
590
|
"flex w-full items-center gap-3 rounded-button px-2.5 py-2 text-[13px] font-medium transition-colors",
|
|
940
591
|
"hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground",
|
|
941
|
-
isActive ? "bg-sidebar-accent font-semibold text-sidebar-accent-foreground
|
|
592
|
+
isActive ? "bg-sidebar-accent font-semibold text-sidebar-accent-foreground" : "text-sidebar-foreground/80",
|
|
942
593
|
collapsed && "justify-center px-2"
|
|
943
594
|
);
|
|
944
595
|
const inner = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -995,7 +646,7 @@ function NavGroup({
|
|
|
995
646
|
}) {
|
|
996
647
|
const isChildActive = item.children?.some((c) => c.route === activeRoute);
|
|
997
648
|
const [open, setOpen] = React7.useState(() => isChildActive ?? false);
|
|
998
|
-
const Icon =
|
|
649
|
+
const Icon = getIcon(item.icon);
|
|
999
650
|
if (collapsed) {
|
|
1000
651
|
const hoverProps = flyout?.rowProps(flyoutContentOf(item));
|
|
1001
652
|
return /* @__PURE__ */ jsx(
|
|
@@ -1050,7 +701,7 @@ function NavGroup({
|
|
|
1050
701
|
// along with the labels and land the arrowhead on top of the text.
|
|
1051
702
|
childConnector ? "relative" : "ml-4 space-y-0.5 border-l border-sidebar-border/50 pl-3"
|
|
1052
703
|
), children: item.children?.map((child, childIndex) => {
|
|
1053
|
-
const ChildIcon =
|
|
704
|
+
const ChildIcon = getIcon(child.icon);
|
|
1054
705
|
const isActive = child.route === activeRoute;
|
|
1055
706
|
const childExternal = !!child.href;
|
|
1056
707
|
const childClass = cn(
|
|
@@ -1144,6 +795,7 @@ function Sidebar({
|
|
|
1144
795
|
user: _user,
|
|
1145
796
|
orgSwitcher,
|
|
1146
797
|
topContent,
|
|
798
|
+
identity,
|
|
1147
799
|
navTop,
|
|
1148
800
|
footerContent,
|
|
1149
801
|
borderless,
|
|
@@ -1154,7 +806,8 @@ function Sidebar({
|
|
|
1154
806
|
sectionLabels,
|
|
1155
807
|
navKey,
|
|
1156
808
|
navDirection = "forward",
|
|
1157
|
-
navChildConnector
|
|
809
|
+
navChildConnector,
|
|
810
|
+
drawer
|
|
1158
811
|
}) {
|
|
1159
812
|
const currentPath = currentPathProp;
|
|
1160
813
|
const setCommandPaletteOpen = useLayoutStore((s) => s.setCommandPaletteOpen);
|
|
@@ -1205,7 +858,6 @@ function Sidebar({
|
|
|
1205
858
|
item.id
|
|
1206
859
|
);
|
|
1207
860
|
const navBody = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1208
|
-
navTop && /* @__PURE__ */ jsx("div", { className: "mb-2", children: withCollapsed(navTop, collapsed) }),
|
|
1209
861
|
mainItems.length > 0 && renderSection(mainItems, sectionLabels?.main),
|
|
1210
862
|
secondaryItems.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-6", children: renderSection(secondaryItems, sectionLabels?.secondary) })
|
|
1211
863
|
] });
|
|
@@ -1234,162 +886,435 @@ function Sidebar({
|
|
|
1234
886
|
/* @__PURE__ */ jsx(RailFlyoutProvider, { value: flyout, children: /* @__PURE__ */ jsxs(
|
|
1235
887
|
"aside",
|
|
1236
888
|
{
|
|
1237
|
-
ref: railRef,
|
|
1238
|
-
"data-print": "hide",
|
|
1239
|
-
onBlur: (event) => {
|
|
1240
|
-
if (!event.currentTarget.contains(event.relatedTarget)) flyout.dismiss();
|
|
1241
|
-
},
|
|
889
|
+
ref: railRef,
|
|
890
|
+
"data-print": "hide",
|
|
891
|
+
onBlur: (event) => {
|
|
892
|
+
if (!event.currentTarget.contains(event.relatedTarget)) flyout.dismiss();
|
|
893
|
+
},
|
|
894
|
+
className: cn(
|
|
895
|
+
// `relative` anchors the flyout, which hangs off the rail's right edge
|
|
896
|
+
// and has to escape the nav's own scroll box to do it.
|
|
897
|
+
"relative flex h-full flex-col bg-sidebar text-sidebar-foreground transition-all duration-200",
|
|
898
|
+
!borderless && "border-r border-sidebar-border",
|
|
899
|
+
// 14rem expanded. It was 16rem, which is the width a rail needs when
|
|
900
|
+
// its entries are sentences ("GlossGenius Financing", "Configure your
|
|
901
|
+
// payment methods"); these are one or two words, so the extra 2rem was
|
|
902
|
+
// paid for by the content column on every screen in every app. The
|
|
903
|
+
// labels still truncate, and a long one now truncates 32px earlier —
|
|
904
|
+
// which is the trade, taken deliberately.
|
|
905
|
+
collapsed ? "w-16" : "w-56"
|
|
906
|
+
),
|
|
907
|
+
children: [
|
|
908
|
+
/* @__PURE__ */ jsxs("div", { className: cn("shrink-0", !borderless && "border-b border-sidebar-border"), children: [
|
|
909
|
+
/* @__PURE__ */ jsxs(
|
|
910
|
+
"div",
|
|
911
|
+
{
|
|
912
|
+
className: cn(
|
|
913
|
+
"flex items-center gap-1 px-2",
|
|
914
|
+
// h-12 com a conta embaixo (48 + 44 + 8 = 100px, na régua de 4/8),
|
|
915
|
+
// h-14 quando a marca é a única coisa aqui e a linha tem de bater
|
|
916
|
+
// com o cabeçalho da página.
|
|
917
|
+
identity ? "h-12" : "h-14",
|
|
918
|
+
collapsed && "justify-center"
|
|
919
|
+
),
|
|
920
|
+
children: [
|
|
921
|
+
topContent ? /* @__PURE__ */ jsx("div", { className: cn("min-w-0", collapsed ? "flex justify-center" : "flex-1"), children: withCollapsed(topContent, collapsed) }) : !collapsed && /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 px-1.5", children: logo ?? /* @__PURE__ */ jsx("span", { className: "text-lg font-bold", children: "App" }) }),
|
|
922
|
+
drawer && /* @__PURE__ */ jsx(
|
|
923
|
+
"button",
|
|
924
|
+
{
|
|
925
|
+
onClick: onToggle,
|
|
926
|
+
className: "fz-tap shrink-0 rounded-button p-1.5 text-sidebar-muted transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
|
927
|
+
"aria-label": "Close menu",
|
|
928
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4" })
|
|
929
|
+
}
|
|
930
|
+
)
|
|
931
|
+
]
|
|
932
|
+
}
|
|
933
|
+
),
|
|
934
|
+
identity && /* @__PURE__ */ jsx("div", { className: cn("px-2 pb-2", collapsed && "flex justify-center"), children: withCollapsed(identity, collapsed) })
|
|
935
|
+
] }),
|
|
936
|
+
navTop ? /* @__PURE__ */ jsx("div", { className: "px-2 pb-2 pt-2", children: withCollapsed(navTop, collapsed) }) : (
|
|
937
|
+
/* Search — above the first destination. It used to be a 16px magnifier
|
|
938
|
+
tucked beside the avatar at the very bottom, which is where you put
|
|
939
|
+
something nobody is meant to find: the fastest way through an admin
|
|
940
|
+
with thirty screens was the one control shaped like an afterthought.
|
|
941
|
+
Here it reads as what it is — a field — and says which key opens it.
|
|
942
|
+
Clicking it opens the same palette ⌘K does; it is a button, not an
|
|
943
|
+
input, because typing happens there. */
|
|
944
|
+
/* @__PURE__ */ jsx("div", { className: "px-2 pb-2 pt-2", children: /* @__PURE__ */ jsxs(
|
|
945
|
+
"button",
|
|
946
|
+
{
|
|
947
|
+
onClick: () => setCommandPaletteOpen(true),
|
|
948
|
+
"aria-keyshortcuts": "Meta+K Control+K",
|
|
949
|
+
className: cn(
|
|
950
|
+
// Tonal surface, no outline. On a dark rail a 1px border is a hard
|
|
951
|
+
// edge competing with every other hard edge; a lighter fill of the
|
|
952
|
+
// same hue reads as "a field" without drawing a box around it — and
|
|
953
|
+
// leaves the outline treatment free to mean focus, which it must.
|
|
954
|
+
"fz-tap group flex items-center rounded-lg bg-sidebar-accent/40 text-sidebar-muted transition-colors",
|
|
955
|
+
"hover:bg-sidebar-accent/70 hover:text-sidebar-foreground",
|
|
956
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sidebar-accent-foreground/50",
|
|
957
|
+
collapsed ? "h-9 w-9 justify-center" : "h-9 w-full gap-2.5 px-2.5"
|
|
958
|
+
),
|
|
959
|
+
"aria-label": searchLabel,
|
|
960
|
+
title: collapsed ? searchLabel : void 0,
|
|
961
|
+
children: [
|
|
962
|
+
/* @__PURE__ */ jsx(Search, { className: "h-4 w-4 shrink-0" }),
|
|
963
|
+
!collapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
964
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-left text-[13px]", children: searchLabel }),
|
|
965
|
+
/* @__PURE__ */ jsxs("span", { className: "shrink-0 text-[11px] font-medium tabular-nums text-sidebar-muted/60 transition-opacity group-hover:opacity-100 md:opacity-70", children: [
|
|
966
|
+
shortcutKey(),
|
|
967
|
+
"K"
|
|
968
|
+
] })
|
|
969
|
+
] })
|
|
970
|
+
]
|
|
971
|
+
}
|
|
972
|
+
) })
|
|
973
|
+
),
|
|
974
|
+
/* @__PURE__ */ jsxs(
|
|
975
|
+
"nav",
|
|
976
|
+
{
|
|
977
|
+
className: cn(
|
|
978
|
+
"relative flex-1 p-2",
|
|
979
|
+
// scrollbar-none: the rail still scrolls, but without the native
|
|
980
|
+
// scrollbar gutter eating into the nav items.
|
|
981
|
+
outgoing ? "overflow-hidden" : "overflow-y-auto scrollbar-none"
|
|
982
|
+
),
|
|
983
|
+
children: [
|
|
984
|
+
outgoing && /* @__PURE__ */ jsx(
|
|
985
|
+
"div",
|
|
986
|
+
{
|
|
987
|
+
"aria-hidden": true,
|
|
988
|
+
className: cn(
|
|
989
|
+
"pointer-events-none absolute inset-x-2 top-2 space-y-1",
|
|
990
|
+
outgoing.direction === "back" ? "saas-rail-out-back" : "saas-rail-out-forward"
|
|
991
|
+
),
|
|
992
|
+
children: outgoing.body
|
|
993
|
+
}
|
|
994
|
+
),
|
|
995
|
+
/* @__PURE__ */ jsx(
|
|
996
|
+
"div",
|
|
997
|
+
{
|
|
998
|
+
className: cn(
|
|
999
|
+
"space-y-1",
|
|
1000
|
+
outgoing && (outgoing.direction === "back" ? "saas-rail-in-back" : "saas-rail-in-forward")
|
|
1001
|
+
),
|
|
1002
|
+
children: navBody
|
|
1003
|
+
},
|
|
1004
|
+
navKey
|
|
1005
|
+
)
|
|
1006
|
+
]
|
|
1007
|
+
}
|
|
1008
|
+
),
|
|
1009
|
+
settingsItems.length > 0 && /* @__PURE__ */ jsx("div", { className: cn("p-2 space-y-1", !borderless && "border-t border-sidebar-border"), children: settingsItems.map((item) => /* @__PURE__ */ jsx(
|
|
1010
|
+
NavItem,
|
|
1011
|
+
{
|
|
1012
|
+
item,
|
|
1013
|
+
collapsed,
|
|
1014
|
+
isActive: item.route === activeRoute,
|
|
1015
|
+
onNavigate: handleNavigate,
|
|
1016
|
+
flyout
|
|
1017
|
+
},
|
|
1018
|
+
item.id
|
|
1019
|
+
)) }),
|
|
1020
|
+
footerContent && // `empty:hidden` — slot children may all render null (e.g. the
|
|
1021
|
+
// SeuSiteWidget self-hides when the tenant has no project); without
|
|
1022
|
+
// it the padded/bordered wrapper shows as a blank block.
|
|
1023
|
+
/* @__PURE__ */ jsx("div", { className: cn("space-y-2 p-2 empty:hidden", !borderless && "border-t border-sidebar-border"), children: footerContent }),
|
|
1024
|
+
withCollapsed(orgSwitcher, collapsed),
|
|
1025
|
+
/* @__PURE__ */ jsx("div", { className: cn("p-2", !borderless && "border-t border-sidebar-border"), children: /* @__PURE__ */ jsxs("div", { className: cn(
|
|
1026
|
+
"flex items-center rounded-button",
|
|
1027
|
+
collapsed ? "flex-col gap-1" : "gap-1 px-1"
|
|
1028
|
+
), children: [
|
|
1029
|
+
userMenuSlot,
|
|
1030
|
+
!collapsed && /* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
1031
|
+
notificationSlot ?? /* @__PURE__ */ jsxs(
|
|
1032
|
+
"button",
|
|
1033
|
+
{
|
|
1034
|
+
className: "fz-tap relative inline-flex shrink-0 items-center justify-center rounded-button p-2 text-sidebar-muted transition-colors hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground",
|
|
1035
|
+
"aria-label": unreadCount > 0 ? `${unreadCount} unread notifications` : "Notifications",
|
|
1036
|
+
children: [
|
|
1037
|
+
/* @__PURE__ */ jsx(Bell, { className: "h-4 w-4" }),
|
|
1038
|
+
unreadCount > 0 && /* @__PURE__ */ jsx("span", { className: "absolute right-1 top-1 h-2 w-2 rounded-full bg-destructive" })
|
|
1039
|
+
]
|
|
1040
|
+
}
|
|
1041
|
+
),
|
|
1042
|
+
!drawer && /* @__PURE__ */ jsx(
|
|
1043
|
+
"button",
|
|
1044
|
+
{
|
|
1045
|
+
onClick: onToggle,
|
|
1046
|
+
className: "fz-tap inline-flex shrink-0 items-center justify-center rounded-button p-2 text-sidebar-muted transition-colors hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground",
|
|
1047
|
+
"aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
|
|
1048
|
+
title: collapsed ? "Expand sidebar" : "Collapse sidebar",
|
|
1049
|
+
children: collapsed ? /* @__PURE__ */ jsx(PanelLeft, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(PanelLeftClose, { className: "h-4 w-4" })
|
|
1050
|
+
}
|
|
1051
|
+
)
|
|
1052
|
+
] }) }),
|
|
1053
|
+
flyout.panel
|
|
1054
|
+
]
|
|
1055
|
+
}
|
|
1056
|
+
) })
|
|
1057
|
+
);
|
|
1058
|
+
}
|
|
1059
|
+
function TopbarUserMenu({
|
|
1060
|
+
user,
|
|
1061
|
+
userPlan,
|
|
1062
|
+
billingLabel = "Subscription",
|
|
1063
|
+
onSignOut,
|
|
1064
|
+
onProfile,
|
|
1065
|
+
onSettings,
|
|
1066
|
+
onBilling,
|
|
1067
|
+
userMenuExtras
|
|
1068
|
+
}) {
|
|
1069
|
+
const [open, setOpen] = React7.useState(false);
|
|
1070
|
+
if (!user) return null;
|
|
1071
|
+
const initial = (user.fullName?.trim()?.[0] ?? user.email?.[0] ?? "?").toUpperCase();
|
|
1072
|
+
const item = (label, onClick, Icon) => onClick ? /* @__PURE__ */ jsxs(
|
|
1073
|
+
"button",
|
|
1074
|
+
{
|
|
1075
|
+
onClick: () => {
|
|
1076
|
+
setOpen(false);
|
|
1077
|
+
onClick();
|
|
1078
|
+
},
|
|
1079
|
+
className: "flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-sm text-popover-foreground transition-colors hover:bg-muted/70",
|
|
1080
|
+
children: [
|
|
1081
|
+
Icon && /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 text-muted-foreground" }),
|
|
1082
|
+
/* @__PURE__ */ jsx("span", { children: label })
|
|
1083
|
+
]
|
|
1084
|
+
},
|
|
1085
|
+
label
|
|
1086
|
+
) : null;
|
|
1087
|
+
return /* @__PURE__ */ jsxs(Popover.Root, { open, onOpenChange: setOpen, children: [
|
|
1088
|
+
/* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
1089
|
+
"button",
|
|
1090
|
+
{
|
|
1091
|
+
"aria-label": "User menu",
|
|
1092
|
+
className: "ml-1 flex h-9 w-9 items-center justify-center overflow-hidden rounded-full bg-primary text-xs font-semibold text-primary-foreground ring-2 ring-transparent transition hover:ring-sidebar-border",
|
|
1093
|
+
children: user.avatarUrl ? (
|
|
1094
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
1095
|
+
/* @__PURE__ */ jsx("img", { src: user.avatarUrl, alt: "", className: "h-full w-full object-cover" })
|
|
1096
|
+
) : initial
|
|
1097
|
+
}
|
|
1098
|
+
) }),
|
|
1099
|
+
/* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsxs(
|
|
1100
|
+
Popover.Content,
|
|
1101
|
+
{
|
|
1102
|
+
align: "end",
|
|
1103
|
+
sideOffset: 8,
|
|
1104
|
+
className: "fayz-glass-surface z-50 min-w-[220px] rounded-xl border border-border bg-popover p-1.5 shadow-lg animate-in fade-in-0 zoom-in-95",
|
|
1105
|
+
children: [
|
|
1106
|
+
/* @__PURE__ */ jsxs("div", { className: "border-b border-border px-3 py-2", children: [
|
|
1107
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-sm font-medium text-foreground", children: user.fullName || user.email }),
|
|
1108
|
+
/* @__PURE__ */ jsx("p", { className: "truncate text-xs text-muted-foreground", children: user.email })
|
|
1109
|
+
] }),
|
|
1110
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-1 space-y-0.5", children: [
|
|
1111
|
+
item("Perfil", onProfile, UserCog),
|
|
1112
|
+
item("Configura\xE7\xF5es", onSettings, Settings),
|
|
1113
|
+
onBilling && /* @__PURE__ */ jsxs(
|
|
1114
|
+
"button",
|
|
1115
|
+
{
|
|
1116
|
+
onClick: () => {
|
|
1117
|
+
setOpen(false);
|
|
1118
|
+
onBilling();
|
|
1119
|
+
},
|
|
1120
|
+
className: "flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-sm text-popover-foreground transition-colors hover:bg-muted/70",
|
|
1121
|
+
children: [
|
|
1122
|
+
/* @__PURE__ */ jsx(CreditCard, { className: "h-4 w-4 text-muted-foreground" }),
|
|
1123
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 text-left", children: billingLabel }),
|
|
1124
|
+
userPlan && /* @__PURE__ */ jsxs(
|
|
1125
|
+
"span",
|
|
1126
|
+
{
|
|
1127
|
+
className: userPlan.paid ? "inline-flex items-center gap-1 rounded-full border border-amber-400/40 bg-amber-400/15 px-2 py-0.5 text-[10px] font-semibold text-amber-600 dark:text-amber-300" : "inline-flex items-center gap-1 rounded-full border border-border bg-muted px-2 py-0.5 text-[10px] font-medium text-muted-foreground",
|
|
1128
|
+
children: [
|
|
1129
|
+
userPlan.paid ? /* @__PURE__ */ jsx(Crown, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(Sparkles, { className: "h-3 w-3" }),
|
|
1130
|
+
userPlan.label
|
|
1131
|
+
]
|
|
1132
|
+
}
|
|
1133
|
+
)
|
|
1134
|
+
]
|
|
1135
|
+
},
|
|
1136
|
+
"billing"
|
|
1137
|
+
),
|
|
1138
|
+
userMenuExtras?.map((e) => item(e.label, e.onClick)),
|
|
1139
|
+
onSignOut && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1140
|
+
/* @__PURE__ */ jsx("div", { className: "my-1 border-t border-border" }),
|
|
1141
|
+
item("Sair", onSignOut, LogOut)
|
|
1142
|
+
] })
|
|
1143
|
+
] })
|
|
1144
|
+
]
|
|
1145
|
+
}
|
|
1146
|
+
) })
|
|
1147
|
+
] });
|
|
1148
|
+
}
|
|
1149
|
+
function getIcon2(name) {
|
|
1150
|
+
return ICON_MAP[name] ?? Home;
|
|
1151
|
+
}
|
|
1152
|
+
function NavDropdown({ item, currentPath, onNavigate }) {
|
|
1153
|
+
const [open, setOpen] = React7.useState(false);
|
|
1154
|
+
const Icon = getIcon2(item.icon);
|
|
1155
|
+
const isChildActive = item.children?.some(
|
|
1156
|
+
(child) => currentPath === child.route || currentPath.startsWith(child.route + "/")
|
|
1157
|
+
);
|
|
1158
|
+
return /* @__PURE__ */ jsxs(Popover.Root, { open, onOpenChange: setOpen, children: [
|
|
1159
|
+
/* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
1160
|
+
"button",
|
|
1161
|
+
{
|
|
1162
|
+
"data-nav-active": isChildActive || void 0,
|
|
1242
1163
|
className: cn(
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
"relative flex h-full flex-col bg-sidebar text-sidebar-foreground transition-all duration-200",
|
|
1246
|
-
!borderless && "border-r border-sidebar-border",
|
|
1247
|
-
// 14rem expanded. It was 16rem, which is the width a rail needs when
|
|
1248
|
-
// its entries are sentences ("GlossGenius Financing", "Configure your
|
|
1249
|
-
// payment methods"); these are one or two words, so the extra 2rem was
|
|
1250
|
-
// paid for by the content column on every screen in every app. The
|
|
1251
|
-
// labels still truncate, and a long one now truncates 32px earlier —
|
|
1252
|
-
// which is the trade, taken deliberately.
|
|
1253
|
-
collapsed ? "w-16" : "w-56"
|
|
1164
|
+
"flex items-center gap-1.5 whitespace-nowrap border-b-2 px-3 py-2 text-sm transition-colors",
|
|
1165
|
+
isChildActive ? "border-sidebar-accent-foreground font-semibold text-sidebar-foreground" : "border-transparent text-sidebar-muted hover:text-sidebar-foreground"
|
|
1254
1166
|
),
|
|
1255
1167
|
children: [
|
|
1256
|
-
/* @__PURE__ */
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
"aria-label": "Collapse sidebar",
|
|
1273
|
-
children: /* @__PURE__ */ jsx(PanelLeftClose, { className: "h-4 w-4" })
|
|
1274
|
-
}
|
|
1275
|
-
)
|
|
1276
|
-
] }),
|
|
1277
|
-
collapsed && /* @__PURE__ */ jsx(
|
|
1278
|
-
"button",
|
|
1279
|
-
{
|
|
1280
|
-
onClick: onToggle,
|
|
1281
|
-
className: "rounded-button p-1.5 text-sidebar-muted transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
|
1282
|
-
"aria-label": "Expand sidebar",
|
|
1283
|
-
children: /* @__PURE__ */ jsx(PanelLeft, { className: "h-4 w-4" })
|
|
1284
|
-
}
|
|
1285
|
-
)
|
|
1286
|
-
]
|
|
1287
|
-
}
|
|
1288
|
-
),
|
|
1289
|
-
topContent && /* @__PURE__ */ jsx("div", { className: "px-2 pt-2", children: withCollapsed(topContent, collapsed) }),
|
|
1290
|
-
/* @__PURE__ */ jsx("div", { className: "px-2 pb-2 pt-2", children: /* @__PURE__ */ jsxs(
|
|
1168
|
+
/* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }),
|
|
1169
|
+
/* @__PURE__ */ jsx("span", { children: item.label }),
|
|
1170
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: cn("h-3 w-3 transition-transform", open && "rotate-180") })
|
|
1171
|
+
]
|
|
1172
|
+
}
|
|
1173
|
+
) }),
|
|
1174
|
+
/* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(
|
|
1175
|
+
Popover.Content,
|
|
1176
|
+
{
|
|
1177
|
+
align: "start",
|
|
1178
|
+
sideOffset: 4,
|
|
1179
|
+
className: "fayz-glass-surface z-50 min-w-[200px] rounded-xl border border-border bg-popover p-1.5 shadow-lg animate-in fade-in-0 zoom-in-95",
|
|
1180
|
+
children: item.children?.map((child) => {
|
|
1181
|
+
const ChildIcon = getIcon2(child.icon);
|
|
1182
|
+
const isActive = currentPath === child.route || currentPath.startsWith(child.route + "/");
|
|
1183
|
+
return /* @__PURE__ */ jsxs(
|
|
1291
1184
|
"button",
|
|
1292
1185
|
{
|
|
1293
|
-
onClick: () =>
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
// edge competing with every other hard edge; a lighter fill of the
|
|
1298
|
-
// same hue reads as "a field" without drawing a box around it — and
|
|
1299
|
-
// leaves the outline treatment free to mean focus, which it must.
|
|
1300
|
-
"fz-tap group flex items-center rounded-lg bg-sidebar-accent/40 text-sidebar-muted transition-colors",
|
|
1301
|
-
"hover:bg-sidebar-accent/70 hover:text-sidebar-foreground",
|
|
1302
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sidebar-accent-foreground/50",
|
|
1303
|
-
collapsed ? "h-9 w-9 justify-center" : "h-9 w-full gap-2.5 px-2.5"
|
|
1304
|
-
),
|
|
1305
|
-
"aria-label": searchLabel,
|
|
1306
|
-
title: collapsed ? searchLabel : void 0,
|
|
1307
|
-
children: [
|
|
1308
|
-
/* @__PURE__ */ jsx(Search, { className: "h-4 w-4 shrink-0" }),
|
|
1309
|
-
!collapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1310
|
-
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-left text-[13px]", children: searchLabel }),
|
|
1311
|
-
/* @__PURE__ */ jsxs("span", { className: "shrink-0 text-[11px] font-medium tabular-nums text-sidebar-muted/60 transition-opacity group-hover:opacity-100 md:opacity-70", children: [
|
|
1312
|
-
shortcutKey(),
|
|
1313
|
-
"K"
|
|
1314
|
-
] })
|
|
1315
|
-
] })
|
|
1316
|
-
]
|
|
1317
|
-
}
|
|
1318
|
-
) }),
|
|
1319
|
-
/* @__PURE__ */ jsxs(
|
|
1320
|
-
"nav",
|
|
1321
|
-
{
|
|
1186
|
+
onClick: () => {
|
|
1187
|
+
onNavigate(child.route);
|
|
1188
|
+
setOpen(false);
|
|
1189
|
+
},
|
|
1322
1190
|
className: cn(
|
|
1323
|
-
"
|
|
1324
|
-
|
|
1325
|
-
// scrollbar gutter eating into the nav items.
|
|
1326
|
-
outgoing ? "overflow-hidden" : "overflow-y-auto scrollbar-none"
|
|
1191
|
+
"flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-sm transition-colors",
|
|
1192
|
+
isActive ? "bg-muted font-medium text-foreground" : "text-popover-foreground hover:bg-muted/70"
|
|
1327
1193
|
),
|
|
1328
1194
|
children: [
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
{
|
|
1332
|
-
"aria-hidden": true,
|
|
1333
|
-
className: cn(
|
|
1334
|
-
"pointer-events-none absolute inset-x-2 top-2 space-y-1",
|
|
1335
|
-
outgoing.direction === "back" ? "saas-rail-out-back" : "saas-rail-out-forward"
|
|
1336
|
-
),
|
|
1337
|
-
children: outgoing.body
|
|
1338
|
-
}
|
|
1339
|
-
),
|
|
1340
|
-
/* @__PURE__ */ jsx(
|
|
1341
|
-
"div",
|
|
1342
|
-
{
|
|
1343
|
-
className: cn(
|
|
1344
|
-
"space-y-1",
|
|
1345
|
-
outgoing && (outgoing.direction === "back" ? "saas-rail-in-back" : "saas-rail-in-forward")
|
|
1346
|
-
),
|
|
1347
|
-
children: navBody
|
|
1348
|
-
},
|
|
1349
|
-
navKey
|
|
1350
|
-
)
|
|
1195
|
+
/* @__PURE__ */ jsx(ChildIcon, { className: "h-4 w-4 text-muted-foreground" }),
|
|
1196
|
+
/* @__PURE__ */ jsx("span", { children: child.label })
|
|
1351
1197
|
]
|
|
1352
|
-
}
|
|
1353
|
-
),
|
|
1354
|
-
settingsItems.length > 0 && /* @__PURE__ */ jsx("div", { className: cn("p-2 space-y-1", !borderless && "border-t border-sidebar-border"), children: settingsItems.map((item) => /* @__PURE__ */ jsx(
|
|
1355
|
-
NavItem,
|
|
1356
|
-
{
|
|
1357
|
-
item,
|
|
1358
|
-
collapsed,
|
|
1359
|
-
isActive: item.route === activeRoute,
|
|
1360
|
-
onNavigate: handleNavigate,
|
|
1361
|
-
flyout
|
|
1362
1198
|
},
|
|
1363
|
-
|
|
1364
|
-
)
|
|
1365
|
-
|
|
1366
|
-
// SeuSiteWidget self-hides when the tenant has no project); without
|
|
1367
|
-
// it the padded/bordered wrapper shows as a blank block.
|
|
1368
|
-
/* @__PURE__ */ jsx("div", { className: cn("space-y-2 p-2 empty:hidden", !borderless && "border-t border-sidebar-border"), children: footerContent }),
|
|
1369
|
-
withCollapsed(orgSwitcher, collapsed),
|
|
1370
|
-
/* @__PURE__ */ jsx("div", { className: cn("p-2", !borderless && "border-t border-sidebar-border"), children: /* @__PURE__ */ jsxs("div", { className: cn(
|
|
1371
|
-
"flex items-center rounded-button",
|
|
1372
|
-
collapsed ? "flex-col gap-1" : "gap-1 px-1"
|
|
1373
|
-
), children: [
|
|
1374
|
-
userMenuSlot,
|
|
1375
|
-
!collapsed && /* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
1376
|
-
notificationSlot ?? /* @__PURE__ */ jsxs(
|
|
1377
|
-
"button",
|
|
1378
|
-
{
|
|
1379
|
-
className: "fz-tap relative inline-flex shrink-0 items-center justify-center rounded-button p-2 text-sidebar-muted transition-colors hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground",
|
|
1380
|
-
"aria-label": unreadCount > 0 ? `${unreadCount} unread notifications` : "Notifications",
|
|
1381
|
-
children: [
|
|
1382
|
-
/* @__PURE__ */ jsx(Bell, { className: "h-4 w-4" }),
|
|
1383
|
-
unreadCount > 0 && /* @__PURE__ */ jsx("span", { className: "absolute right-1 top-1 h-2 w-2 rounded-full bg-destructive" })
|
|
1384
|
-
]
|
|
1385
|
-
}
|
|
1386
|
-
)
|
|
1387
|
-
] }) }),
|
|
1388
|
-
flyout.panel
|
|
1389
|
-
]
|
|
1199
|
+
child.id
|
|
1200
|
+
);
|
|
1201
|
+
})
|
|
1390
1202
|
}
|
|
1391
1203
|
) })
|
|
1392
|
-
);
|
|
1204
|
+
] });
|
|
1205
|
+
}
|
|
1206
|
+
function Topbar({
|
|
1207
|
+
navigation,
|
|
1208
|
+
logo,
|
|
1209
|
+
user,
|
|
1210
|
+
onMenuClick,
|
|
1211
|
+
orgSwitcher,
|
|
1212
|
+
leftContent,
|
|
1213
|
+
rightContent,
|
|
1214
|
+
currentPath = "/",
|
|
1215
|
+
onNavigate,
|
|
1216
|
+
searchPlaceholder = "Search...",
|
|
1217
|
+
onSignOut,
|
|
1218
|
+
onProfile,
|
|
1219
|
+
onSettings,
|
|
1220
|
+
onBilling,
|
|
1221
|
+
userPlan,
|
|
1222
|
+
billingLabel,
|
|
1223
|
+
userMenuExtras,
|
|
1224
|
+
userMenuSlot
|
|
1225
|
+
}) {
|
|
1226
|
+
const setCommandPaletteOpen = useLayoutStore((s) => s.setCommandPaletteOpen);
|
|
1227
|
+
const mainNav = navigation.filter((item) => item.section === "main");
|
|
1228
|
+
const secondaryNav = navigation.filter((item) => item.section === "secondary");
|
|
1229
|
+
const allNav = [...mainNav, ...secondaryNav];
|
|
1230
|
+
const handleNavigate = (route) => {
|
|
1231
|
+
onNavigate?.(route);
|
|
1232
|
+
};
|
|
1233
|
+
return /* @__PURE__ */ jsxs("header", { "data-print": "hide", className: "sticky top-0 z-50 w-full shrink-0", children: [
|
|
1234
|
+
/* @__PURE__ */ jsx("div", { className: "border-b border-sidebar-border bg-sidebar text-sidebar-foreground", children: /* @__PURE__ */ jsxs("div", { className: "flex h-14 w-full items-center justify-between px-4 md:px-6", children: [
|
|
1235
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [
|
|
1236
|
+
onMenuClick && /* @__PURE__ */ jsx(
|
|
1237
|
+
"button",
|
|
1238
|
+
{
|
|
1239
|
+
onClick: onMenuClick,
|
|
1240
|
+
className: "inline-flex items-center justify-center rounded-md p-2 text-sidebar-foreground/70 hover:bg-sidebar/30 hover:text-sidebar-foreground md:hidden",
|
|
1241
|
+
"aria-label": "Open menu",
|
|
1242
|
+
children: /* @__PURE__ */ jsx(Menu, { className: "h-5 w-5" })
|
|
1243
|
+
}
|
|
1244
|
+
),
|
|
1245
|
+
/* @__PURE__ */ jsx("div", { className: "hidden min-w-0 shrink-0 items-center md:flex", children: orgSwitcher ?? logo ?? /* @__PURE__ */ jsx("span", { className: "text-lg font-bold", children: "App" }) })
|
|
1246
|
+
] }),
|
|
1247
|
+
/* @__PURE__ */ jsx("div", { className: "mx-8 hidden max-w-sm flex-1 md:flex", children: /* @__PURE__ */ jsxs(
|
|
1248
|
+
"button",
|
|
1249
|
+
{
|
|
1250
|
+
onClick: () => setCommandPaletteOpen(true),
|
|
1251
|
+
className: "relative flex h-8 w-full items-center rounded-md border border-sidebar-border bg-sidebar-accent px-3 pl-8 text-sm text-sidebar-muted shadow-sm transition-colors hover:border-sidebar-foreground/25 hover:bg-sidebar-foreground/10 hover:text-sidebar-foreground",
|
|
1252
|
+
children: [
|
|
1253
|
+
/* @__PURE__ */ jsx(Search, { className: "absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-sidebar-muted" }),
|
|
1254
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs", children: searchPlaceholder }),
|
|
1255
|
+
/* @__PURE__ */ jsx("kbd", { className: "ml-auto hidden rounded border border-sidebar-border bg-sidebar-accent px-1.5 py-0.5 text-[10px] font-medium text-sidebar-muted sm:inline-block", children: "\u2318K" })
|
|
1256
|
+
]
|
|
1257
|
+
}
|
|
1258
|
+
) }),
|
|
1259
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-1", children: [
|
|
1260
|
+
leftContent,
|
|
1261
|
+
rightContent,
|
|
1262
|
+
userMenuSlot ?? /* @__PURE__ */ jsx(
|
|
1263
|
+
TopbarUserMenu,
|
|
1264
|
+
{
|
|
1265
|
+
user,
|
|
1266
|
+
userPlan,
|
|
1267
|
+
billingLabel,
|
|
1268
|
+
onSignOut,
|
|
1269
|
+
onProfile,
|
|
1270
|
+
onSettings,
|
|
1271
|
+
onBilling,
|
|
1272
|
+
userMenuExtras
|
|
1273
|
+
}
|
|
1274
|
+
)
|
|
1275
|
+
] })
|
|
1276
|
+
] }) }),
|
|
1277
|
+
/* @__PURE__ */ jsx("div", { className: "hidden md:block bg-sidebar", children: /* @__PURE__ */ jsx("div", { className: "flex h-11 w-full items-center px-4 md:px-6", children: /* @__PURE__ */ jsx("nav", { ref: (el) => {
|
|
1278
|
+
if (!el) return;
|
|
1279
|
+
const active = el.querySelector('[data-nav-active="true"]');
|
|
1280
|
+
if (active) {
|
|
1281
|
+
const left = active.offsetLeft - el.offsetWidth / 2 + active.offsetWidth / 2;
|
|
1282
|
+
el.scrollTo({ left: Math.max(0, left), behavior: "smooth" });
|
|
1283
|
+
}
|
|
1284
|
+
}, className: "flex items-center gap-0.5 overflow-x-auto scrollbar-none", children: allNav.map((item) => {
|
|
1285
|
+
if (item.children && item.children.length > 0) {
|
|
1286
|
+
return /* @__PURE__ */ jsx(
|
|
1287
|
+
NavDropdown,
|
|
1288
|
+
{
|
|
1289
|
+
item,
|
|
1290
|
+
currentPath,
|
|
1291
|
+
onNavigate: handleNavigate
|
|
1292
|
+
},
|
|
1293
|
+
item.id
|
|
1294
|
+
);
|
|
1295
|
+
}
|
|
1296
|
+
const Icon = getIcon2(item.icon);
|
|
1297
|
+
const isActive = item.route === "/" ? currentPath === "/" : currentPath === item.route || currentPath.startsWith(item.route + "/");
|
|
1298
|
+
return /* @__PURE__ */ jsxs(
|
|
1299
|
+
"button",
|
|
1300
|
+
{
|
|
1301
|
+
"data-nav-active": isActive || void 0,
|
|
1302
|
+
onClick: () => handleNavigate(item.route),
|
|
1303
|
+
className: cn(
|
|
1304
|
+
"flex items-center gap-1.5 whitespace-nowrap border-b-2 px-3 py-2 text-sm transition-colors",
|
|
1305
|
+
isActive ? "border-primary font-semibold text-sidebar-foreground" : "border-transparent text-sidebar-muted hover:text-sidebar-foreground"
|
|
1306
|
+
),
|
|
1307
|
+
children: [
|
|
1308
|
+
/* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }),
|
|
1309
|
+
/* @__PURE__ */ jsx("span", { children: item.label }),
|
|
1310
|
+
item.premium && /* @__PURE__ */ jsx(Crown, { className: "h-3 w-3 text-amber-500", "aria-hidden": true }),
|
|
1311
|
+
item.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-primary px-1.5 py-0.5 text-[10px] font-semibold text-primary-foreground", children: item.badge })
|
|
1312
|
+
]
|
|
1313
|
+
},
|
|
1314
|
+
item.id
|
|
1315
|
+
);
|
|
1316
|
+
}) }) }) })
|
|
1317
|
+
] });
|
|
1393
1318
|
}
|
|
1394
1319
|
var ModuleHeaderSlotContext = React7.createContext(null);
|
|
1395
1320
|
function useModuleHeaderSlot() {
|
|
@@ -1423,6 +1348,7 @@ function SidebarLayout({
|
|
|
1423
1348
|
userMenuExtras: _userMenuExtras,
|
|
1424
1349
|
orgSwitcher,
|
|
1425
1350
|
sidebarTopContent,
|
|
1351
|
+
sidebarIdentity,
|
|
1426
1352
|
sidebarNavTop,
|
|
1427
1353
|
sidebarFooterContent,
|
|
1428
1354
|
frame,
|
|
@@ -1440,7 +1366,8 @@ function SidebarLayout({
|
|
|
1440
1366
|
sidebarSectionLabels,
|
|
1441
1367
|
sidebarNavKey,
|
|
1442
1368
|
sidebarNavDirection,
|
|
1443
|
-
sidebarNavChildConnector
|
|
1369
|
+
sidebarNavChildConnector,
|
|
1370
|
+
railOpen
|
|
1444
1371
|
}) {
|
|
1445
1372
|
const sidebarCollapsed = useLayoutStore((s) => s.sidebarCollapsed);
|
|
1446
1373
|
const pageHeaderSlot = usePageHeaderSlot();
|
|
@@ -1474,6 +1401,7 @@ function SidebarLayout({
|
|
|
1474
1401
|
onBilling,
|
|
1475
1402
|
orgSwitcher,
|
|
1476
1403
|
topContent: sidebarTopContent,
|
|
1404
|
+
identity: sidebarIdentity,
|
|
1477
1405
|
navTop: sidebarNavTop,
|
|
1478
1406
|
footerContent: sidebarFooterContent,
|
|
1479
1407
|
borderless: frame,
|
|
@@ -1492,7 +1420,13 @@ function SidebarLayout({
|
|
|
1492
1420
|
// `content`, not `card`: this is the page's own surface, and cards have
|
|
1493
1421
|
// to sit ON it. Painted card, the frame was the same tone as everything
|
|
1494
1422
|
// inside it and the page read as one flat sheet.
|
|
1495
|
-
frame && "md:
|
|
1423
|
+
frame && "md:my-2 md:ml-2 md:rounded-xl md:border md:border-border md:bg-content",
|
|
1424
|
+
// With a companion rail open, the page and the rail are ONE card: the
|
|
1425
|
+
// right edge opens and the rail closes it. Two cards with a strip of
|
|
1426
|
+
// chrome between them made the assistant read as a separate window
|
|
1427
|
+
// parked next to the app rather than as a column of it — the rail's own
|
|
1428
|
+
// left border is then the single seam between the two.
|
|
1429
|
+
frame && (railOpen ? "md:rounded-r-none md:border-r-0" : "md:mr-2")
|
|
1496
1430
|
), children: [
|
|
1497
1431
|
/* @__PURE__ */ jsx("div", { ref: setPageRailSlot, className: "flex shrink-0 empty:hidden" }),
|
|
1498
1432
|
/* @__PURE__ */ jsxs("div", { className: "relative flex min-w-0 flex-1 flex-col overflow-hidden", children: [
|
|
@@ -1539,6 +1473,7 @@ function SidebarLayout({
|
|
|
1539
1473
|
onBilling,
|
|
1540
1474
|
orgSwitcher,
|
|
1541
1475
|
topContent: sidebarTopContent,
|
|
1476
|
+
identity: sidebarIdentity,
|
|
1542
1477
|
navTop: sidebarNavTop,
|
|
1543
1478
|
footerContent: sidebarFooterContent,
|
|
1544
1479
|
userMenuSlot,
|
|
@@ -1563,6 +1498,7 @@ function TopbarLayout({
|
|
|
1563
1498
|
userPlan,
|
|
1564
1499
|
billingLabel,
|
|
1565
1500
|
userMenuExtras,
|
|
1501
|
+
userMenuSlot,
|
|
1566
1502
|
orgSwitcher,
|
|
1567
1503
|
frame,
|
|
1568
1504
|
currentPath,
|
|
@@ -1599,6 +1535,7 @@ function TopbarLayout({
|
|
|
1599
1535
|
userPlan,
|
|
1600
1536
|
billingLabel,
|
|
1601
1537
|
userMenuExtras,
|
|
1538
|
+
userMenuSlot,
|
|
1602
1539
|
orgSwitcher,
|
|
1603
1540
|
leftContent: topbarStart,
|
|
1604
1541
|
rightContent: topbarEnd || notificationSlot ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -1710,6 +1647,7 @@ function MobileOverlay({ onClose, onNavigate, ...sidebarProps }) {
|
|
|
1710
1647
|
...sidebarProps,
|
|
1711
1648
|
collapsed: false,
|
|
1712
1649
|
onToggle: close,
|
|
1650
|
+
drawer: true,
|
|
1713
1651
|
borderless: true,
|
|
1714
1652
|
onNavigate: (route) => {
|
|
1715
1653
|
onNavigate?.(route);
|
|
@@ -1723,16 +1661,16 @@ function MobileOverlay({ onClose, onNavigate, ...sidebarProps }) {
|
|
|
1723
1661
|
}
|
|
1724
1662
|
var BOTTOM_NAV_ICONS = {
|
|
1725
1663
|
Home: Home,
|
|
1726
|
-
Receipt
|
|
1727
|
-
ArrowLeftRight
|
|
1728
|
-
Calendar
|
|
1664
|
+
Receipt,
|
|
1665
|
+
ArrowLeftRight,
|
|
1666
|
+
Calendar,
|
|
1729
1667
|
CreditCard: CreditCard,
|
|
1730
1668
|
Settings: Settings,
|
|
1731
1669
|
Menu: Menu,
|
|
1732
|
-
MessageCircle
|
|
1733
|
-
Wallet
|
|
1670
|
+
MessageCircle,
|
|
1671
|
+
Wallet,
|
|
1734
1672
|
PiggyBank,
|
|
1735
|
-
Plus
|
|
1673
|
+
Plus
|
|
1736
1674
|
};
|
|
1737
1675
|
function FloatingProfileAvatar({ user, onClick }) {
|
|
1738
1676
|
if (!user) return null;
|
|
@@ -1819,6 +1757,7 @@ function AppShell({
|
|
|
1819
1757
|
topbarStart,
|
|
1820
1758
|
topbarEnd,
|
|
1821
1759
|
sidebarTopContent,
|
|
1760
|
+
sidebarIdentity,
|
|
1822
1761
|
sidebarNavTop,
|
|
1823
1762
|
sidebarFooterContent,
|
|
1824
1763
|
bottomNav,
|
|
@@ -1868,6 +1807,7 @@ function AppShell({
|
|
|
1868
1807
|
userMenuExtras,
|
|
1869
1808
|
orgSwitcher,
|
|
1870
1809
|
sidebarTopContent,
|
|
1810
|
+
sidebarIdentity,
|
|
1871
1811
|
sidebarNavTop,
|
|
1872
1812
|
sidebarFooterContent,
|
|
1873
1813
|
frame: contentFrame,
|
|
@@ -1886,6 +1826,7 @@ function AppShell({
|
|
|
1886
1826
|
sidebarNavKey,
|
|
1887
1827
|
sidebarNavDirection,
|
|
1888
1828
|
sidebarNavChildConnector,
|
|
1829
|
+
railOpen: !!rightRail && rightRailOpen,
|
|
1889
1830
|
children
|
|
1890
1831
|
}
|
|
1891
1832
|
);
|
|
@@ -1905,6 +1846,7 @@ function AppShell({
|
|
|
1905
1846
|
userPlan,
|
|
1906
1847
|
billingLabel,
|
|
1907
1848
|
userMenuExtras,
|
|
1849
|
+
userMenuSlot,
|
|
1908
1850
|
orgSwitcher,
|
|
1909
1851
|
frame: contentFrame,
|
|
1910
1852
|
currentPath,
|
|
@@ -2026,7 +1968,11 @@ function SplitWithRightRail({
|
|
|
2026
1968
|
}
|
|
2027
1969
|
},
|
|
2028
1970
|
className: cn(
|
|
2029
|
-
|
|
1971
|
+
// Zero width: the divider USED to be a 4px gutter, which meant the
|
|
1972
|
+
// page and the rail could never touch — there was always a strip of
|
|
1973
|
+
// chrome between them. It now sits exactly on the seam the rail's own
|
|
1974
|
+
// left border draws, and lights that border up when you reach for it.
|
|
1975
|
+
"group relative hidden w-0 shrink-0 cursor-col-resize focus-visible:outline-none",
|
|
2030
1976
|
open && "md:block"
|
|
2031
1977
|
),
|
|
2032
1978
|
children: [
|
|
@@ -2034,7 +1980,7 @@ function SplitWithRightRail({
|
|
|
2034
1980
|
"span",
|
|
2035
1981
|
{
|
|
2036
1982
|
className: cn(
|
|
2037
|
-
"absolute inset-y-6 left-
|
|
1983
|
+
"absolute inset-y-6 -left-px w-0.5 rounded-full bg-transparent transition-colors",
|
|
2038
1984
|
"group-hover:bg-primary/60 group-focus-visible:bg-primary",
|
|
2039
1985
|
dragging && "bg-primary"
|
|
2040
1986
|
)
|
|
@@ -2067,6 +2013,7 @@ function HeaderTabs({
|
|
|
2067
2013
|
value,
|
|
2068
2014
|
onChange,
|
|
2069
2015
|
className,
|
|
2016
|
+
fill,
|
|
2070
2017
|
...rest
|
|
2071
2018
|
}) {
|
|
2072
2019
|
return /* @__PURE__ */ jsx(
|
|
@@ -2075,7 +2022,8 @@ function HeaderTabs({
|
|
|
2075
2022
|
role: "tablist",
|
|
2076
2023
|
"aria-label": rest["aria-label"],
|
|
2077
2024
|
className: cn(
|
|
2078
|
-
"inline-flex max-w-full
|
|
2025
|
+
"inline-flex max-w-full gap-5 overflow-x-auto scrollbar-none",
|
|
2026
|
+
fill ? "items-stretch" : "items-center",
|
|
2079
2027
|
className
|
|
2080
2028
|
),
|
|
2081
2029
|
children: tabs.map((tab) => {
|
|
@@ -2089,7 +2037,10 @@ function HeaderTabs({
|
|
|
2089
2037
|
"aria-selected": active,
|
|
2090
2038
|
onClick: () => onChange(tab.value),
|
|
2091
2039
|
className: cn(
|
|
2092
|
-
"relative flex shrink-0 items-center gap-1.5 whitespace-nowrap
|
|
2040
|
+
"relative flex shrink-0 items-center gap-1.5 whitespace-nowrap text-sm transition-colors",
|
|
2041
|
+
// Filled: the row owns the band's height and the underline sits on
|
|
2042
|
+
// its bottom edge. Otherwise the underline trails the label by 6px.
|
|
2043
|
+
fill ? "h-full" : "pb-1.5",
|
|
2093
2044
|
active ? "font-medium text-foreground" : "text-muted-foreground hover:text-foreground"
|
|
2094
2045
|
),
|
|
2095
2046
|
children: [
|
|
@@ -2173,7 +2124,7 @@ function useModuleLayout() {
|
|
|
2173
2124
|
}
|
|
2174
2125
|
function RailNavItem({ item }) {
|
|
2175
2126
|
const [expanded, setExpanded] = React7.useState(true);
|
|
2176
|
-
const Icon = item.icon ?
|
|
2127
|
+
const Icon = item.icon ? ICON_MAP[item.icon] ?? null : null;
|
|
2177
2128
|
const hasChildren = item.children && item.children.length > 0;
|
|
2178
2129
|
const hasActiveChild = hasChildren && item.children.some((c) => c.active);
|
|
2179
2130
|
const isActive = item.active || hasActiveChild;
|
|
@@ -2227,7 +2178,7 @@ function MobileTabs({ nav }) {
|
|
|
2227
2178
|
}, [nav]);
|
|
2228
2179
|
return /* @__PURE__ */ jsxs("div", { className: "md:hidden -mx-1 mb-4 no-print", children: [
|
|
2229
2180
|
/* @__PURE__ */ jsx("div", { ref: scrollRef, className: "flex gap-1 px-1 pb-2 overflow-x-auto scrollbar-none", children: nav.map((item) => {
|
|
2230
|
-
const Icon = item.icon ?
|
|
2181
|
+
const Icon = item.icon ? ICON_MAP[item.icon] ?? null : null;
|
|
2231
2182
|
const hasChildren = item.children && item.children.length > 0;
|
|
2232
2183
|
const isActive = item.active || item.children?.some((c) => c.active);
|
|
2233
2184
|
const isExpanded = expandedId === item.id;
|
|
@@ -2298,7 +2249,7 @@ function SubpageHeader({ title, subtitle, icon, onBack, parentLabel, actions, ba
|
|
|
2298
2249
|
const effectiveOnBack = inline ? onBack : cross.onBack;
|
|
2299
2250
|
const effectiveParentLabel = inline ? parentLabel : cross.parentLabel;
|
|
2300
2251
|
useBackHandler(effectiveOnBack);
|
|
2301
|
-
const Icon = icon ?
|
|
2252
|
+
const Icon = icon ? ICON_MAP[icon] ?? null : null;
|
|
2302
2253
|
if (inline && effectiveOnBack) {
|
|
2303
2254
|
return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
2304
2255
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
|
|
@@ -2399,7 +2350,7 @@ function ModuleHeader({ nav }) {
|
|
|
2399
2350
|
const tabs = nav.map((item) => ({
|
|
2400
2351
|
value: item.id,
|
|
2401
2352
|
label: item.label,
|
|
2402
|
-
icon: item.icon ?
|
|
2353
|
+
icon: item.icon ? ICON_MAP[item.icon] ?? void 0 : void 0,
|
|
2403
2354
|
// Plan-gated views keep their upgrade marker — dropping it would hide the
|
|
2404
2355
|
// only signal that the tab costs an upgrade.
|
|
2405
2356
|
badge: item.premium ? /* @__PURE__ */ jsx(PremiumBadge, {}) : void 0
|
|
@@ -2445,5 +2396,5 @@ function ModulePage({ title: _title, subtitle, nav, children, className, headerA
|
|
|
2445
2396
|
}
|
|
2446
2397
|
|
|
2447
2398
|
export { AppShell, BackStyleProvider, HeaderTabs, ModuleLayoutProvider, ModulePage, NavTransitionProvider, PageHeader, PageHeaderActions, PageHeaderCrumb, PageRail, PageTabs, PageTransition, RailNavItem, SaveBar, SaveBarProvider, Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetOverlay, SheetPortal, SheetTitle, SheetTrigger, Sidebar, SubpageHeader, Topbar, useBackHandler, useBackStyle, useCrossModuleBack, useModuleHeaderActionsSlot, useModuleHeaderSlot, useModuleLayout, useNavTransition, useRailRow, useSaveBar, useSaveBarVisible };
|
|
2448
|
-
//# sourceMappingURL=chunk-
|
|
2449
|
-
//# sourceMappingURL=chunk-
|
|
2399
|
+
//# sourceMappingURL=chunk-NA3GE4H3.js.map
|
|
2400
|
+
//# sourceMappingURL=chunk-NA3GE4H3.js.map
|