@fayz-ai/ui 0.8.2 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/{chunk-J3IUFUNR.js → chunk-2GDQUARM.js} +3 -3
  2. package/dist/{chunk-J3IUFUNR.js.map → chunk-2GDQUARM.js.map} +1 -1
  3. package/dist/{chunk-W5O2X277.js → chunk-A7O7KGNL.js} +8 -4
  4. package/dist/chunk-A7O7KGNL.js.map +1 -0
  5. package/dist/{chunk-FY7OZNKU.js → chunk-BVF2KPTT.js} +7 -7
  6. package/dist/{chunk-FY7OZNKU.js.map → chunk-BVF2KPTT.js.map} +1 -1
  7. package/dist/{chunk-MZZMZYSE.js → chunk-ID2HQK2Q.js} +328 -51
  8. package/dist/chunk-ID2HQK2Q.js.map +1 -0
  9. package/dist/{chunk-ODY3GZ3Y.cjs → chunk-MI6FOB4O.cjs} +7 -7
  10. package/dist/{chunk-ODY3GZ3Y.cjs.map → chunk-MI6FOB4O.cjs.map} +1 -1
  11. package/dist/{chunk-IEYCOJTY.cjs → chunk-SVVKUMSL.cjs} +6 -6
  12. package/dist/{chunk-IEYCOJTY.cjs.map → chunk-SVVKUMSL.cjs.map} +1 -1
  13. package/dist/{chunk-NWPMNPGR.cjs → chunk-WF3STNDX.cjs} +38 -34
  14. package/dist/chunk-WF3STNDX.cjs.map +1 -0
  15. package/dist/{chunk-XAOGMWLC.cjs → chunk-XIRJGVDK.cjs} +325 -48
  16. package/dist/chunk-XIRJGVDK.cjs.map +1 -0
  17. package/dist/dashboard/OnboardingWidget.d.ts.map +1 -1
  18. package/dist/dashboard/index.cjs +26 -26
  19. package/dist/dashboard/index.js +2 -2
  20. package/dist/index.cjs +122 -122
  21. package/dist/index.js +4 -4
  22. package/dist/layout/AppShell.d.ts +41 -1
  23. package/dist/layout/AppShell.d.ts.map +1 -1
  24. package/dist/layout/ModulePage.d.ts +9 -6
  25. package/dist/layout/ModulePage.d.ts.map +1 -1
  26. package/dist/layout/Sidebar.d.ts +20 -1
  27. package/dist/layout/Sidebar.d.ts.map +1 -1
  28. package/dist/layout/Topbar.d.ts +13 -1
  29. package/dist/layout/Topbar.d.ts.map +1 -1
  30. package/dist/layout/index.cjs +19 -19
  31. package/dist/layout/index.js +1 -1
  32. package/dist/primitives/data-table.d.ts.map +1 -1
  33. package/dist/primitives/index.cjs +77 -77
  34. package/dist/primitives/index.js +2 -2
  35. package/package.json +3 -3
  36. package/src/dashboard/OnboardingWidget.tsx +10 -1
  37. package/src/layout/AppShell.tsx +255 -7
  38. package/src/layout/ModulePage.tsx +32 -3
  39. package/src/layout/Sidebar.tsx +132 -35
  40. package/src/layout/Topbar.tsx +51 -4
  41. package/src/primitives/data-table.tsx +10 -1
  42. package/src/styles.css +34 -0
  43. package/dist/chunk-MZZMZYSE.js.map +0 -1
  44. package/dist/chunk-NWPMNPGR.cjs.map +0 -1
  45. package/dist/chunk-W5O2X277.js.map +0 -1
  46. package/dist/chunk-XAOGMWLC.cjs.map +0 -1
@@ -1,10 +1,10 @@
1
1
  import { useCrossModuleBack, useBackHandler, Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetBody, SaveBarProvider, SaveBar } from './chunk-75EFDLST.js';
2
2
  import { cn, Button } from './chunk-YRVE4FOD.js';
3
3
  import * as React3 from 'react';
4
- import { FileCheck2, Clock3, Boxes, Workflow, UserX, UserPlus, UserCheck, TrendingUp, Star, Inbox, MessageSquare, LayoutDashboard, Award, Zap, Mic, UsersRound, Disc3, ListMusic, Eye, Music, Layers, CircleDollarSign, Landmark, Banknote, BadgeDollarSign, CalendarX, CalendarCheck2, CalendarDays, Radio, PartyPopper, Wheat, Egg, Apple, LeafyGreen, LayoutTemplate, FolderOpen, Heart, PawPrint, Cat, Dog, Clock, Ban, Shield, Search, ListPlus, List, Plus, Filter, Building2, Contact, Handshake, Map, MapPin, UtensilsCrossed, Camera, Tags, Tag, Percent, Globe, MessageCircle, BookOpenCheck, BookOpen, UserCog, Briefcase, ListChecks, ClipboardList, ShoppingBag, Receipt, Wrench, Target, ShoppingCart, Megaphone, DollarSign, Mail, FileText, BarChart3, Activity, Package, CalendarClock, Calendar, Bell, CreditCard, Settings, Users, Home, PanelLeftClose, PanelLeft, Menu, ChevronRight, ChevronLeft, PanelRightOpen, PanelRightClose, PanelRight, Newspaper, Clapperboard, Box, TreePalm, ArrowDownRight, ArrowUpRight, Ruler, Warehouse, Wallet, Sparkles, AlertTriangle, TableProperties, SlidersHorizontal, Plug, ArrowLeftRight, ArrowUpCircle, ArrowDownCircle, ChevronDown, ClipboardCheck, PiggyBank } from 'lucide-react';
4
+ import { Puzzle, SlidersHorizontal, ShieldCheck, Palette, User, Repeat, GraduationCap, FileCheck2, Clock3, Boxes, Workflow, UserX, UserPlus, UserCheck, TrendingUp, Star, Inbox, MessageSquare, LayoutDashboard, Award, Zap, Mic, UsersRound, Disc3, ListMusic, Eye, Music, Layers, CircleDollarSign, Landmark, Banknote, BadgeDollarSign, CalendarX, CalendarCheck2, CalendarDays, Radio, PartyPopper, Wheat, Egg, Apple, LeafyGreen, LayoutTemplate, FolderOpen, Heart, PawPrint, Cat, Dog, Clock, Ban, Shield, Search, ListPlus, List, Plus, Filter, Building2, Contact, Handshake, Map, MapPin, UtensilsCrossed, Camera, Tags, Tag, Percent, Globe, MessageCircle, BookOpenCheck, BookOpen, UserCog, Briefcase, ListChecks, ClipboardList, ShoppingBag, Receipt, Wrench, Target, ShoppingCart, Megaphone, DollarSign, Mail, FileText, BarChart3, Activity, Package, CalendarClock, Calendar, Bell, CreditCard, Settings, Users, Home, PanelLeftClose, PanelLeft, Menu, Crown, ChevronRight, ChevronLeft, PanelRightOpen, PanelRightClose, PanelRight, Newspaper, Clapperboard, Box, TreePalm, ArrowDownRight, ArrowUpRight, Ruler, Warehouse, Wallet, Sparkles, AlertTriangle, TableProperties, Plug, ArrowLeftRight, ArrowUpCircle, ArrowDownCircle, ChevronDown, ClipboardCheck, PiggyBank, LogOut } from 'lucide-react';
5
5
  import * as Tooltip from '@radix-ui/react-tooltip';
6
6
  import { create } from 'zustand';
7
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
8
8
  import * as Popover from '@radix-ui/react-popover';
9
9
  import { createPortal } from 'react-dom';
10
10
  import { useTranslation } from '@fayz-ai/core';
@@ -104,8 +104,17 @@ var ICON_MAP = {
104
104
  Workflow,
105
105
  Boxes,
106
106
  Clock3,
107
- FileCheck2
107
+ FileCheck2,
108
+ GraduationCap,
109
+ Repeat,
110
+ User,
111
+ Palette,
112
+ ShieldCheck,
113
+ SlidersHorizontal,
114
+ Puzzle
108
115
  };
116
+ var RAIL_PUSH_MS = 260;
117
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React3.useLayoutEffect : React3.useEffect;
109
118
  function getIcon(name) {
110
119
  return ICON_MAP[name] ?? Home;
111
120
  }
@@ -130,6 +139,7 @@ function NavItem({
130
139
  /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 shrink-0" }),
131
140
  !collapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
132
141
  /* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-left", children: item.label }),
142
+ item.premium && /* @__PURE__ */ jsx(Crown, { className: "ml-auto h-3.5 w-3.5 shrink-0 text-amber-500", "aria-hidden": true }),
133
143
  item.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: "ml-auto rounded-full bg-primary px-2 py-0.5 text-xs font-semibold text-primary-foreground", children: item.badge })
134
144
  ] })
135
145
  ]
@@ -146,6 +156,7 @@ function NavItem({
146
156
  className: "fayz-glass-surface z-50 rounded-md bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md",
147
157
  children: [
148
158
  item.label,
159
+ item.premium && /* @__PURE__ */ jsx(Crown, { className: "ml-1.5 inline h-3 w-3 text-amber-500", "aria-hidden": true }),
149
160
  item.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: "ml-2 rounded-full bg-primary px-1.5 py-0.5 text-xs text-primary-foreground", children: item.badge }),
150
161
  /* @__PURE__ */ jsx(Tooltip.Arrow, { className: "fill-popover" })
151
162
  ]
@@ -258,7 +269,10 @@ function Sidebar({
258
269
  borderless,
259
270
  userMenuSlot,
260
271
  notificationSlot,
261
- unreadCount = 0
272
+ unreadCount = 0,
273
+ sectionLabels,
274
+ navKey,
275
+ navDirection = "forward"
262
276
  }) {
263
277
  const currentPath = currentPathProp;
264
278
  const setCommandPaletteOpen = useLayoutStore((s) => s.setCommandPaletteOpen);
@@ -269,6 +283,47 @@ function Sidebar({
269
283
  const handleNavigate = (route) => {
270
284
  onNavigate?.(route);
271
285
  };
286
+ const sectionHeading = (label) => label && !collapsed ? /* @__PURE__ */ jsx("p", { className: "px-2.5 pb-1 pt-1 text-[10px] font-semibold uppercase tracking-wider text-sidebar-muted", children: label }) : null;
287
+ const renderItem = (item) => item.children && item.children.length > 0 ? /* @__PURE__ */ jsx(NavGroup, { item, collapsed, activeRoute, onNavigate: handleNavigate }, item.id) : /* @__PURE__ */ jsx(
288
+ NavItem,
289
+ {
290
+ item,
291
+ collapsed,
292
+ isActive: item.route === activeRoute,
293
+ onNavigate: handleNavigate
294
+ },
295
+ item.id
296
+ );
297
+ const navBody = /* @__PURE__ */ jsxs(Fragment, { children: [
298
+ topContent && /* @__PURE__ */ jsx("div", { className: "mb-4 space-y-2", children: topContent }),
299
+ mainItems.length > 0 && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
300
+ sectionHeading(sectionLabels?.main),
301
+ mainItems.map(renderItem)
302
+ ] }),
303
+ secondaryItems.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-6 space-y-1", children: [
304
+ sectionHeading(sectionLabels?.secondary),
305
+ secondaryItems.map(renderItem)
306
+ ] })
307
+ ] });
308
+ const [outgoing, setOutgoing] = React3.useState(null);
309
+ const lastBodyRef = React3.useRef(null);
310
+ const lastKeyRef = React3.useRef(navKey);
311
+ const timerRef = React3.useRef(null);
312
+ useIsomorphicLayoutEffect(() => {
313
+ if (lastKeyRef.current !== navKey) {
314
+ const previousBody = lastBodyRef.current;
315
+ lastKeyRef.current = navKey;
316
+ if (previousBody) {
317
+ setOutgoing({ body: previousBody, direction: navDirection });
318
+ if (timerRef.current) clearTimeout(timerRef.current);
319
+ timerRef.current = setTimeout(() => setOutgoing(null), RAIL_PUSH_MS);
320
+ }
321
+ }
322
+ lastBodyRef.current = navBody;
323
+ });
324
+ React3.useEffect(() => () => {
325
+ if (timerRef.current) clearTimeout(timerRef.current);
326
+ }, []);
272
327
  return /* @__PURE__ */ jsx(Tooltip.Provider, { children: /* @__PURE__ */ jsxs(
273
328
  "aside",
274
329
  {
@@ -312,33 +367,39 @@ function Sidebar({
312
367
  ]
313
368
  }
314
369
  ),
315
- /* @__PURE__ */ jsxs("nav", { className: "flex-1 space-y-1 overflow-y-auto p-2", children: [
316
- topContent && /* @__PURE__ */ jsx("div", { className: "mb-4 space-y-2", children: topContent }),
317
- mainItems.length > 0 && /* @__PURE__ */ jsx("div", { className: "space-y-1", children: mainItems.map(
318
- (item) => item.children && item.children.length > 0 ? /* @__PURE__ */ jsx(NavGroup, { item, collapsed, activeRoute, onNavigate: handleNavigate }, item.id) : /* @__PURE__ */ jsx(
319
- NavItem,
320
- {
321
- item,
322
- collapsed,
323
- isActive: item.route === activeRoute,
324
- onNavigate: handleNavigate
325
- },
326
- item.id
327
- )
328
- ) }),
329
- secondaryItems.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-6 space-y-1", children: secondaryItems.map(
330
- (item) => item.children && item.children.length > 0 ? /* @__PURE__ */ jsx(NavGroup, { item, collapsed, activeRoute, onNavigate: handleNavigate }, item.id) : /* @__PURE__ */ jsx(
331
- NavItem,
332
- {
333
- item,
334
- collapsed,
335
- isActive: item.route === activeRoute,
336
- onNavigate: handleNavigate
337
- },
338
- item.id
339
- )
340
- ) })
341
- ] }),
370
+ /* @__PURE__ */ jsxs(
371
+ "nav",
372
+ {
373
+ className: cn(
374
+ "relative flex-1 p-2",
375
+ outgoing ? "overflow-hidden" : "overflow-y-auto"
376
+ ),
377
+ children: [
378
+ outgoing && /* @__PURE__ */ jsx(
379
+ "div",
380
+ {
381
+ "aria-hidden": true,
382
+ className: cn(
383
+ "pointer-events-none absolute inset-x-2 top-2 space-y-1",
384
+ outgoing.direction === "back" ? "saas-rail-out-back" : "saas-rail-out-forward"
385
+ ),
386
+ children: outgoing.body
387
+ }
388
+ ),
389
+ /* @__PURE__ */ jsx(
390
+ "div",
391
+ {
392
+ className: cn(
393
+ "space-y-1",
394
+ outgoing && (outgoing.direction === "back" ? "saas-rail-in-back" : "saas-rail-in-forward")
395
+ ),
396
+ children: navBody
397
+ },
398
+ navKey
399
+ )
400
+ ]
401
+ }
402
+ ),
342
403
  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(
343
404
  NavItem,
344
405
  {
@@ -384,6 +445,8 @@ function Sidebar({
384
445
  }
385
446
  function TopbarUserMenu({
386
447
  user,
448
+ userPlan,
449
+ billingLabel = "Subscription",
387
450
  onSignOut,
388
451
  onProfile,
389
452
  onSettings,
@@ -434,11 +497,35 @@ function TopbarUserMenu({
434
497
  /* @__PURE__ */ jsxs("div", { className: "mt-1 space-y-0.5", children: [
435
498
  item("Perfil", onProfile, UserCog),
436
499
  item("Configura\xE7\xF5es", onSettings, Settings),
437
- item("Cobran\xE7a", onBilling, CreditCard),
500
+ onBilling && /* @__PURE__ */ jsxs(
501
+ "button",
502
+ {
503
+ onClick: () => {
504
+ setOpen(false);
505
+ onBilling();
506
+ },
507
+ 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",
508
+ children: [
509
+ /* @__PURE__ */ jsx(CreditCard, { className: "h-4 w-4 text-muted-foreground" }),
510
+ /* @__PURE__ */ jsx("span", { className: "flex-1 text-left", children: billingLabel }),
511
+ userPlan && /* @__PURE__ */ jsxs(
512
+ "span",
513
+ {
514
+ 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",
515
+ children: [
516
+ userPlan.paid ? /* @__PURE__ */ jsx(Crown, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(Sparkles, { className: "h-3 w-3" }),
517
+ userPlan.label
518
+ ]
519
+ }
520
+ )
521
+ ]
522
+ },
523
+ "billing"
524
+ ),
438
525
  userMenuExtras?.map((e) => item(e.label, e.onClick)),
439
526
  onSignOut && /* @__PURE__ */ jsxs(Fragment, { children: [
440
527
  /* @__PURE__ */ jsx("div", { className: "my-1 border-t border-border" }),
441
- item("Sair", onSignOut)
528
+ item("Sair", onSignOut, LogOut)
442
529
  ] })
443
530
  ] })
444
531
  ]
@@ -503,7 +590,7 @@ var ICON_MAP2 = {
503
590
  ArrowUpCircle,
504
591
  ArrowLeftRight,
505
592
  Plug,
506
- SlidersHorizontal,
593
+ SlidersHorizontal: SlidersHorizontal,
507
594
  TableProperties,
508
595
  Landmark: Landmark,
509
596
  Receipt: Receipt,
@@ -546,7 +633,9 @@ var ICON_MAP2 = {
546
633
  Star: Star,
547
634
  Zap: Zap,
548
635
  Clapperboard,
549
- Newspaper
636
+ Newspaper,
637
+ GraduationCap: GraduationCap,
638
+ Repeat: Repeat
550
639
  };
551
640
  function getIcon2(name) {
552
641
  return ICON_MAP2[name] ?? Home;
@@ -610,6 +699,7 @@ function Topbar({
610
699
  logo,
611
700
  user,
612
701
  onMenuClick,
702
+ orgSwitcher,
613
703
  leftContent,
614
704
  rightContent,
615
705
  currentPath = "/",
@@ -619,6 +709,8 @@ function Topbar({
619
709
  onProfile,
620
710
  onSettings,
621
711
  onBilling,
712
+ userPlan,
713
+ billingLabel,
622
714
  userMenuExtras
623
715
  }) {
624
716
  const setCommandPaletteOpen = useLayoutStore((s) => s.setCommandPaletteOpen);
@@ -640,7 +732,8 @@ function Topbar({
640
732
  children: /* @__PURE__ */ jsx(Menu, { className: "h-5 w-5" })
641
733
  }
642
734
  ),
643
- /* @__PURE__ */ jsx("div", { className: "hidden shrink-0 items-center md:flex", children: logo ?? /* @__PURE__ */ jsx("span", { className: "text-lg font-bold", children: "App" }) })
735
+ /* @__PURE__ */ jsx("div", { className: "hidden shrink-0 items-center md:flex", children: logo ?? /* @__PURE__ */ jsx("span", { className: "text-lg font-bold", children: "App" }) }),
736
+ orgSwitcher && /* @__PURE__ */ jsx("div", { className: "hidden min-w-0 items-center md:flex", children: orgSwitcher })
644
737
  ] }),
645
738
  /* @__PURE__ */ jsx("div", { className: "mx-8 hidden max-w-sm flex-1 md:flex", children: /* @__PURE__ */ jsxs(
646
739
  "button",
@@ -661,6 +754,8 @@ function Topbar({
661
754
  TopbarUserMenu,
662
755
  {
663
756
  user,
757
+ userPlan,
758
+ billingLabel,
664
759
  onSignOut,
665
760
  onProfile,
666
761
  onSettings,
@@ -703,6 +798,7 @@ function Topbar({
703
798
  children: [
704
799
  /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }),
705
800
  /* @__PURE__ */ jsx("span", { children: item.label }),
801
+ item.premium && /* @__PURE__ */ jsx(Crown, { className: "h-3 w-3 text-amber-500", "aria-hidden": true }),
706
802
  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 })
707
803
  ]
708
804
  },
@@ -742,7 +838,10 @@ function SidebarLayout({
742
838
  notificationSlot,
743
839
  unreadCount = 0,
744
840
  hasBottomNav = false,
745
- mobileHeader = "minimal"
841
+ mobileHeader = "minimal",
842
+ sidebarSectionLabels,
843
+ sidebarNavKey,
844
+ sidebarNavDirection
746
845
  }) {
747
846
  const sidebarCollapsed = useLayoutStore((s) => s.sidebarCollapsed);
748
847
  const setSidebarCollapsed = useLayoutStore((s) => s.setSidebarCollapsed);
@@ -776,7 +875,10 @@ function SidebarLayout({
776
875
  borderless: false,
777
876
  userMenuSlot,
778
877
  notificationSlot,
779
- unreadCount
878
+ unreadCount,
879
+ sectionLabels: sidebarSectionLabels,
880
+ navKey: sidebarNavKey,
881
+ navDirection: sidebarNavDirection
780
882
  }
781
883
  ) }),
782
884
  /* @__PURE__ */ jsxs("div", { className: cn(
@@ -806,7 +908,7 @@ function SidebarLayout({
806
908
  topbarEnd
807
909
  ] })
808
910
  ] }),
809
- /* @__PURE__ */ jsx("main", { className: "flex-1 overflow-y-auto pb-16 md:pb-0", children }),
911
+ /* @__PURE__ */ jsx("main", { className: "min-w-0 flex-1 overflow-y-auto pb-16 md:pb-0", children }),
810
912
  /* @__PURE__ */ jsx(SaveBar, {})
811
913
  ] }),
812
914
  mobileMenuOpen && /* @__PURE__ */ jsx(
@@ -842,11 +944,15 @@ function TopbarLayout({
842
944
  onProfile,
843
945
  onSettings,
844
946
  onBilling,
947
+ userPlan,
948
+ billingLabel,
845
949
  userMenuExtras,
950
+ orgSwitcher,
846
951
  frame,
847
952
  currentPath,
848
953
  topbarStart,
849
954
  topbarEnd,
955
+ notificationSlot,
850
956
  hasBottomNav = false
851
957
  }) {
852
958
  const [mobileMenuOpen, setMobileMenuOpen] = React3.useState(false);
@@ -863,13 +969,19 @@ function TopbarLayout({
863
969
  onProfile,
864
970
  onSettings,
865
971
  onBilling,
972
+ userPlan,
973
+ billingLabel,
866
974
  userMenuExtras,
975
+ orgSwitcher,
867
976
  leftContent: topbarStart,
868
- rightContent: topbarEnd,
977
+ rightContent: topbarEnd || notificationSlot ? /* @__PURE__ */ jsxs(Fragment, { children: [
978
+ topbarEnd,
979
+ notificationSlot
980
+ ] }) : void 0,
869
981
  onMenuClick: hasBottomNav ? void 0 : () => setMobileMenuOpen(true)
870
982
  }
871
983
  ),
872
- /* @__PURE__ */ jsx("main", { className: cn("flex-1 overflow-y-auto pb-16 md:pb-0", frame && "md:bg-sidebar md:p-2"), children: /* @__PURE__ */ jsx("div", { className: cn("min-h-full", frame && "md:rounded-xl md:border md:border-border md:bg-card"), children }) }),
984
+ /* @__PURE__ */ jsx("main", { className: cn("flex min-w-0 min-h-0 flex-1 flex-col overflow-hidden", frame && "md:bg-sidebar md:p-2"), children: /* @__PURE__ */ jsx("div", { className: cn("flex min-w-0 min-h-0 flex-1 flex-col overflow-hidden", frame && "md:rounded-xl md:border md:border-border md:bg-card"), children: /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-y-auto pb-16 md:pb-0", children }) }) }),
873
985
  /* @__PURE__ */ jsx(SaveBar, {}),
874
986
  mobileMenuOpen && /* @__PURE__ */ jsx(
875
987
  MobileOverlay,
@@ -883,6 +995,7 @@ function TopbarLayout({
883
995
  onProfile,
884
996
  onSettings,
885
997
  onBilling,
998
+ orgSwitcher,
886
999
  userMenuSlot: user ? /* @__PURE__ */ jsx(DrawerUserRow, { user }) : void 0,
887
1000
  onClose: () => setMobileMenuOpen(false)
888
1001
  }
@@ -907,7 +1020,7 @@ function MinimalLayout({
907
1020
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3", children: logo ?? /* @__PURE__ */ jsx("span", { className: "text-lg font-bold", children: "App" }) }),
908
1021
  headerEnd && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: headerEnd })
909
1022
  ] }),
910
- /* @__PURE__ */ jsx("main", { className: "flex-1 overflow-y-auto pb-16 md:pb-0", children })
1023
+ /* @__PURE__ */ jsx("main", { className: "min-w-0 flex-1 overflow-y-auto pb-16 md:pb-0", children })
911
1024
  ] });
912
1025
  }
913
1026
  function MobileOverlay({ onClose, onNavigate, ...sidebarProps }) {
@@ -1057,6 +1170,8 @@ function AppShell({
1057
1170
  onProfile,
1058
1171
  onSettings,
1059
1172
  onBilling,
1173
+ userPlan,
1174
+ billingLabel,
1060
1175
  pageTitle,
1061
1176
  currentPath,
1062
1177
  userMenuExtras,
@@ -1070,7 +1185,17 @@ function AppShell({
1070
1185
  mobileHeader = "minimal",
1071
1186
  userMenuSlot,
1072
1187
  notificationSlot,
1073
- unreadCount = 0
1188
+ unreadCount = 0,
1189
+ sidebarSectionLabels,
1190
+ sidebarNavKey,
1191
+ sidebarNavDirection,
1192
+ rightRail,
1193
+ rightRailOpen = true,
1194
+ defaultRightRailWidth,
1195
+ onRightRailWidthChange,
1196
+ rightRailMinWidth,
1197
+ rightRailMaxWidth,
1198
+ rightRailResizeLabel
1074
1199
  }) {
1075
1200
  const hasBottomNav = !!bottomNav?.length;
1076
1201
  const bottomBar = hasBottomNav ? /* @__PURE__ */ jsx(
@@ -1111,6 +1236,9 @@ function AppShell({
1111
1236
  unreadCount,
1112
1237
  hasBottomNav,
1113
1238
  mobileHeader,
1239
+ sidebarSectionLabels,
1240
+ sidebarNavKey,
1241
+ sidebarNavDirection,
1114
1242
  children
1115
1243
  }
1116
1244
  );
@@ -1127,11 +1255,15 @@ function AppShell({
1127
1255
  onProfile,
1128
1256
  onSettings,
1129
1257
  onBilling,
1258
+ userPlan,
1259
+ billingLabel,
1130
1260
  userMenuExtras,
1261
+ orgSwitcher,
1131
1262
  frame: contentFrame,
1132
1263
  currentPath,
1133
1264
  topbarStart,
1134
1265
  topbarEnd,
1266
+ notificationSlot,
1135
1267
  hasBottomNav,
1136
1268
  children
1137
1269
  }
@@ -1145,11 +1277,142 @@ function AppShell({
1145
1277
  }
1146
1278
  }
1147
1279
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1148
- layoutElement,
1280
+ rightRail ? /* @__PURE__ */ jsx(
1281
+ SplitWithRightRail,
1282
+ {
1283
+ rail: rightRail,
1284
+ open: rightRailOpen,
1285
+ frame: contentFrame,
1286
+ defaultWidth: defaultRightRailWidth,
1287
+ onWidthChange: onRightRailWidthChange,
1288
+ minWidth: rightRailMinWidth,
1289
+ maxWidth: rightRailMaxWidth,
1290
+ resizeLabel: rightRailResizeLabel,
1291
+ children: layoutElement
1292
+ }
1293
+ ) : layoutElement,
1149
1294
  floatingAvatar,
1150
1295
  bottomBar
1151
1296
  ] });
1152
1297
  }
1298
+ function SplitWithRightRail({
1299
+ children,
1300
+ rail,
1301
+ open,
1302
+ frame,
1303
+ defaultWidth = 380,
1304
+ onWidthChange,
1305
+ minWidth = 300,
1306
+ maxWidth = 720,
1307
+ resizeLabel = "Resize panel"
1308
+ }) {
1309
+ const [width, setWidth] = React3.useState(defaultWidth);
1310
+ const [dragging, setDragging] = React3.useState(false);
1311
+ const clamp = React3.useCallback(
1312
+ (value) => Math.min(maxWidth, Math.max(minWidth, value)),
1313
+ [minWidth, maxWidth]
1314
+ );
1315
+ React3.useEffect(() => {
1316
+ if (!dragging) return;
1317
+ const onMove = (event) => {
1318
+ event.preventDefault();
1319
+ setWidth(clamp(window.innerWidth - event.clientX));
1320
+ };
1321
+ const stop = () => setDragging(false);
1322
+ window.addEventListener("pointermove", onMove);
1323
+ window.addEventListener("pointerup", stop);
1324
+ window.addEventListener("pointercancel", stop);
1325
+ const previousSelect = document.body.style.userSelect;
1326
+ const previousCursor = document.body.style.cursor;
1327
+ document.body.style.userSelect = "none";
1328
+ document.body.style.cursor = "col-resize";
1329
+ return () => {
1330
+ window.removeEventListener("pointermove", onMove);
1331
+ window.removeEventListener("pointerup", stop);
1332
+ window.removeEventListener("pointercancel", stop);
1333
+ document.body.style.userSelect = previousSelect;
1334
+ document.body.style.cursor = previousCursor;
1335
+ };
1336
+ }, [dragging, clamp]);
1337
+ React3.useEffect(() => {
1338
+ if (dragging) return;
1339
+ onWidthChange?.(width);
1340
+ }, [dragging]);
1341
+ const nudge = (delta) => setWidth((current) => clamp(current + delta));
1342
+ return (
1343
+ // Sidebar tone always: the gutter and the divider sit in the shell's
1344
+ // chrome, next to the menu — painting them page-white put a bright strip
1345
+ // between the dark chrome and the rail, which read as a seam rather than
1346
+ // as space.
1347
+ /* @__PURE__ */ jsxs("div", { className: cn("flex h-screen w-full overflow-hidden bg-sidebar", !frame && "md:bg-background"), children: [
1348
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children }),
1349
+ /* @__PURE__ */ jsxs(
1350
+ "div",
1351
+ {
1352
+ role: "separator",
1353
+ "aria-orientation": "vertical",
1354
+ "aria-label": resizeLabel,
1355
+ "aria-valuenow": width,
1356
+ "aria-valuemin": minWidth,
1357
+ "aria-valuemax": maxWidth,
1358
+ tabIndex: 0,
1359
+ onPointerDown: (event) => {
1360
+ event.preventDefault();
1361
+ setDragging(true);
1362
+ },
1363
+ onDoubleClick: () => setWidth(clamp(defaultWidth)),
1364
+ onKeyDown: (event) => {
1365
+ if (event.key === "ArrowLeft") {
1366
+ event.preventDefault();
1367
+ nudge(24);
1368
+ } else if (event.key === "ArrowRight") {
1369
+ event.preventDefault();
1370
+ nudge(-24);
1371
+ } else if (event.key === "Home") {
1372
+ event.preventDefault();
1373
+ setWidth(maxWidth);
1374
+ } else if (event.key === "End") {
1375
+ event.preventDefault();
1376
+ setWidth(minWidth);
1377
+ }
1378
+ },
1379
+ className: cn(
1380
+ "group relative hidden w-1 shrink-0 cursor-col-resize focus-visible:outline-none",
1381
+ open && "md:block"
1382
+ ),
1383
+ children: [
1384
+ /* @__PURE__ */ jsx(
1385
+ "span",
1386
+ {
1387
+ className: cn(
1388
+ "absolute inset-y-6 left-1/2 w-px -translate-x-1/2 rounded-full bg-transparent transition-colors",
1389
+ "group-hover:bg-primary/60 group-focus-visible:bg-primary",
1390
+ dragging && "bg-primary"
1391
+ )
1392
+ }
1393
+ ),
1394
+ /* @__PURE__ */ jsx("span", { className: "absolute inset-y-0 -left-1.5 -right-1.5" })
1395
+ ]
1396
+ }
1397
+ ),
1398
+ /* @__PURE__ */ jsx(
1399
+ "aside",
1400
+ {
1401
+ style: { ["--fayz-rail-w"]: `${width}px` },
1402
+ className: cn(
1403
+ "w-0 shrink-0 overflow-hidden",
1404
+ // Animating WIDTH is what makes the app glide back instead of
1405
+ // snapping; skipped mid-drag so the divider stays glued to the cursor.
1406
+ !dragging && "motion-safe:transition-[width] motion-safe:duration-200 motion-safe:ease-out",
1407
+ open && "md:w-[var(--fayz-rail-w)]",
1408
+ frame && "md:py-2 md:pr-2"
1409
+ ),
1410
+ children: rail
1411
+ }
1412
+ )
1413
+ ] })
1414
+ );
1415
+ }
1153
1416
  var NavTransitionContext = React3.createContext("slide");
1154
1417
  function NavTransitionProvider({ value, children }) {
1155
1418
  return /* @__PURE__ */ jsx(NavTransitionContext.Provider, { value, children });
@@ -1179,6 +1442,11 @@ function PageHeaderActions({ children }) {
1179
1442
  if (slot) return createPortal(children, slot);
1180
1443
  return /* @__PURE__ */ jsx("div", { className: "mb-4 flex items-center justify-end gap-2", children });
1181
1444
  }
1445
+ function PremiumBadge({ className }) {
1446
+ const t = useTranslation();
1447
+ const tip = t("upgrade.badgeTooltip");
1448
+ return /* @__PURE__ */ jsx("span", { title: tip, "aria-label": tip, className: cn("inline-flex shrink-0", className), children: /* @__PURE__ */ jsx(Crown, { className: "h-3.5 w-3.5 text-amber-500", "aria-hidden": true }) });
1449
+ }
1182
1450
  var ModuleLayoutContext = React3.createContext("rail");
1183
1451
  function ModuleLayoutProvider({ variant, children }) {
1184
1452
  return /* @__PURE__ */ jsx(ModuleLayoutContext.Provider, { value: variant, children });
@@ -1205,11 +1473,12 @@ function NavItem2({ item }) {
1205
1473
  children: [
1206
1474
  Icon && /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 shrink-0" }),
1207
1475
  /* @__PURE__ */ jsx("span", { className: "flex-1 text-left truncate", children: item.label }),
1476
+ item.premium && /* @__PURE__ */ jsx(PremiumBadge, { className: "ml-1" }),
1208
1477
  hasChildren && (expanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5 shrink-0 opacity-50" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-3.5 w-3.5 shrink-0 opacity-50" }))
1209
1478
  ]
1210
1479
  }
1211
1480
  ),
1212
- hasChildren && expanded && /* @__PURE__ */ jsx("div", { className: "ml-4 mt-0.5 space-y-0.5 border-l pl-2", children: item.children.map((child) => /* @__PURE__ */ jsx(
1481
+ hasChildren && expanded && /* @__PURE__ */ jsx("div", { className: "ml-4 mt-0.5 space-y-0.5 border-l pl-2", children: item.children.map((child) => /* @__PURE__ */ jsxs(
1213
1482
  "button",
1214
1483
  {
1215
1484
  type: "button",
@@ -1218,7 +1487,10 @@ function NavItem2({ item }) {
1218
1487
  "flex items-center w-full rounded-md px-2.5 py-1 text-xs transition-colors",
1219
1488
  child.active ? "text-primary font-medium bg-primary/5" : "text-muted-foreground hover:text-foreground hover:bg-muted/50"
1220
1489
  ),
1221
- children: child.label
1490
+ children: [
1491
+ /* @__PURE__ */ jsx("span", { className: "flex-1 text-left truncate", children: child.label }),
1492
+ child.premium && /* @__PURE__ */ jsx(PremiumBadge, { className: "ml-1" })
1493
+ ]
1222
1494
  },
1223
1495
  child.id
1224
1496
  )) })
@@ -1262,6 +1534,7 @@ function MobileTabs({ nav }) {
1262
1534
  children: [
1263
1535
  Icon && /* @__PURE__ */ jsx(Icon, { className: "h-3 w-3" }),
1264
1536
  item.label,
1537
+ item.premium && /* @__PURE__ */ jsx(PremiumBadge, {}),
1265
1538
  hasChildren && /* @__PURE__ */ jsx(ChevronDown, { className: cn("h-2.5 w-2.5 transition-transform", isExpanded && "rotate-180") })
1266
1539
  ]
1267
1540
  },
@@ -1271,7 +1544,7 @@ function MobileTabs({ nav }) {
1271
1544
  expandedId && (() => {
1272
1545
  const item = nav.find((n) => n.id === expandedId);
1273
1546
  if (!item?.children) return null;
1274
- return /* @__PURE__ */ jsx("div", { className: "flex gap-1 px-2 pb-2 animate-in fade-in-0 slide-in-from-top-1", children: item.children.map((child) => /* @__PURE__ */ jsx(
1547
+ return /* @__PURE__ */ jsx("div", { className: "flex gap-1 px-2 pb-2 animate-in fade-in-0 slide-in-from-top-1", children: item.children.map((child) => /* @__PURE__ */ jsxs(
1275
1548
  "button",
1276
1549
  {
1277
1550
  type: "button",
@@ -1283,7 +1556,10 @@ function MobileTabs({ nav }) {
1283
1556
  "whitespace-nowrap rounded-full px-2.5 py-1 text-[11px] font-medium transition-colors shrink-0",
1284
1557
  child.active ? "bg-foreground/10 text-foreground" : "text-muted-foreground hover:text-foreground"
1285
1558
  ),
1286
- children: child.label
1559
+ children: [
1560
+ child.label,
1561
+ child.premium && /* @__PURE__ */ jsx(PremiumBadge, {})
1562
+ ]
1287
1563
  },
1288
1564
  child.id
1289
1565
  )) });
@@ -1375,7 +1651,8 @@ function ModuleHeader({ nav }) {
1375
1651
  ),
1376
1652
  children: [
1377
1653
  Icon && /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }),
1378
- item.label
1654
+ item.label,
1655
+ item.premium && /* @__PURE__ */ jsx(PremiumBadge, {})
1379
1656
  ]
1380
1657
  },
1381
1658
  item.id
@@ -1503,5 +1780,5 @@ function ContentSplitTrigger({ label, iconOnly, className }) {
1503
1780
  }
1504
1781
 
1505
1782
  export { AppShell, BackStyleProvider, ContentSplit, ContentSplitTrigger, ICON_MAP, ModuleLayoutProvider, ModulePage, NavTransitionProvider, PageHeaderActions, PageTransition, Sidebar, SubpageHeader, Topbar, useBackStyle, useLayoutStore, useModuleHeaderActionsSlot, useModuleHeaderSlot, useModuleLayout, useNavTransition };
1506
- //# sourceMappingURL=chunk-MZZMZYSE.js.map
1507
- //# sourceMappingURL=chunk-MZZMZYSE.js.map
1783
+ //# sourceMappingURL=chunk-ID2HQK2Q.js.map
1784
+ //# sourceMappingURL=chunk-ID2HQK2Q.js.map