@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
@@ -128,8 +128,17 @@ var ICON_MAP = {
128
128
  Workflow: lucideReact.Workflow,
129
129
  Boxes: lucideReact.Boxes,
130
130
  Clock3: lucideReact.Clock3,
131
- FileCheck2: lucideReact.FileCheck2
131
+ FileCheck2: lucideReact.FileCheck2,
132
+ GraduationCap: lucideReact.GraduationCap,
133
+ Repeat: lucideReact.Repeat,
134
+ User: lucideReact.User,
135
+ Palette: lucideReact.Palette,
136
+ ShieldCheck: lucideReact.ShieldCheck,
137
+ SlidersHorizontal: lucideReact.SlidersHorizontal,
138
+ Puzzle: lucideReact.Puzzle
132
139
  };
140
+ var RAIL_PUSH_MS = 260;
141
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React3__namespace.useLayoutEffect : React3__namespace.useEffect;
133
142
  function getIcon(name) {
134
143
  return ICON_MAP[name] ?? lucideReact.Home;
135
144
  }
@@ -154,6 +163,7 @@ function NavItem({
154
163
  /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4 shrink-0" }),
155
164
  !collapsed && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
156
165
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate text-left", children: item.label }),
166
+ item.premium && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Crown, { className: "ml-auto h-3.5 w-3.5 shrink-0 text-amber-500", "aria-hidden": true }),
157
167
  item.badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto rounded-full bg-primary px-2 py-0.5 text-xs font-semibold text-primary-foreground", children: item.badge })
158
168
  ] })
159
169
  ]
@@ -170,6 +180,7 @@ function NavItem({
170
180
  className: "fayz-glass-surface z-50 rounded-md bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md",
171
181
  children: [
172
182
  item.label,
183
+ item.premium && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Crown, { className: "ml-1.5 inline h-3 w-3 text-amber-500", "aria-hidden": true }),
173
184
  item.badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 rounded-full bg-primary px-1.5 py-0.5 text-xs text-primary-foreground", children: item.badge }),
174
185
  /* @__PURE__ */ jsxRuntime.jsx(Tooltip__namespace.Arrow, { className: "fill-popover" })
175
186
  ]
@@ -282,7 +293,10 @@ function Sidebar({
282
293
  borderless,
283
294
  userMenuSlot,
284
295
  notificationSlot,
285
- unreadCount = 0
296
+ unreadCount = 0,
297
+ sectionLabels,
298
+ navKey,
299
+ navDirection = "forward"
286
300
  }) {
287
301
  const currentPath = currentPathProp;
288
302
  const setCommandPaletteOpen = useLayoutStore((s) => s.setCommandPaletteOpen);
@@ -293,6 +307,47 @@ function Sidebar({
293
307
  const handleNavigate = (route) => {
294
308
  onNavigate?.(route);
295
309
  };
310
+ const sectionHeading = (label) => label && !collapsed ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-2.5 pb-1 pt-1 text-[10px] font-semibold uppercase tracking-wider text-sidebar-muted", children: label }) : null;
311
+ const renderItem = (item) => item.children && item.children.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(NavGroup, { item, collapsed, activeRoute, onNavigate: handleNavigate }, item.id) : /* @__PURE__ */ jsxRuntime.jsx(
312
+ NavItem,
313
+ {
314
+ item,
315
+ collapsed,
316
+ isActive: item.route === activeRoute,
317
+ onNavigate: handleNavigate
318
+ },
319
+ item.id
320
+ );
321
+ const navBody = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
322
+ topContent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4 space-y-2", children: topContent }),
323
+ mainItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
324
+ sectionHeading(sectionLabels?.main),
325
+ mainItems.map(renderItem)
326
+ ] }),
327
+ secondaryItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 space-y-1", children: [
328
+ sectionHeading(sectionLabels?.secondary),
329
+ secondaryItems.map(renderItem)
330
+ ] })
331
+ ] });
332
+ const [outgoing, setOutgoing] = React3__namespace.useState(null);
333
+ const lastBodyRef = React3__namespace.useRef(null);
334
+ const lastKeyRef = React3__namespace.useRef(navKey);
335
+ const timerRef = React3__namespace.useRef(null);
336
+ useIsomorphicLayoutEffect(() => {
337
+ if (lastKeyRef.current !== navKey) {
338
+ const previousBody = lastBodyRef.current;
339
+ lastKeyRef.current = navKey;
340
+ if (previousBody) {
341
+ setOutgoing({ body: previousBody, direction: navDirection });
342
+ if (timerRef.current) clearTimeout(timerRef.current);
343
+ timerRef.current = setTimeout(() => setOutgoing(null), RAIL_PUSH_MS);
344
+ }
345
+ }
346
+ lastBodyRef.current = navBody;
347
+ });
348
+ React3__namespace.useEffect(() => () => {
349
+ if (timerRef.current) clearTimeout(timerRef.current);
350
+ }, []);
296
351
  return /* @__PURE__ */ jsxRuntime.jsx(Tooltip__namespace.Provider, { children: /* @__PURE__ */ jsxRuntime.jsxs(
297
352
  "aside",
298
353
  {
@@ -336,33 +391,39 @@ function Sidebar({
336
391
  ]
337
392
  }
338
393
  ),
339
- /* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "flex-1 space-y-1 overflow-y-auto p-2", children: [
340
- topContent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4 space-y-2", children: topContent }),
341
- mainItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: mainItems.map(
342
- (item) => item.children && item.children.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(NavGroup, { item, collapsed, activeRoute, onNavigate: handleNavigate }, item.id) : /* @__PURE__ */ jsxRuntime.jsx(
343
- NavItem,
344
- {
345
- item,
346
- collapsed,
347
- isActive: item.route === activeRoute,
348
- onNavigate: handleNavigate
349
- },
350
- item.id
351
- )
352
- ) }),
353
- secondaryItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-6 space-y-1", children: secondaryItems.map(
354
- (item) => item.children && item.children.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(NavGroup, { item, collapsed, activeRoute, onNavigate: handleNavigate }, item.id) : /* @__PURE__ */ jsxRuntime.jsx(
355
- NavItem,
356
- {
357
- item,
358
- collapsed,
359
- isActive: item.route === activeRoute,
360
- onNavigate: handleNavigate
361
- },
362
- item.id
363
- )
364
- ) })
365
- ] }),
394
+ /* @__PURE__ */ jsxRuntime.jsxs(
395
+ "nav",
396
+ {
397
+ className: chunkH6OULCHF_cjs.cn(
398
+ "relative flex-1 p-2",
399
+ outgoing ? "overflow-hidden" : "overflow-y-auto"
400
+ ),
401
+ children: [
402
+ outgoing && /* @__PURE__ */ jsxRuntime.jsx(
403
+ "div",
404
+ {
405
+ "aria-hidden": true,
406
+ className: chunkH6OULCHF_cjs.cn(
407
+ "pointer-events-none absolute inset-x-2 top-2 space-y-1",
408
+ outgoing.direction === "back" ? "saas-rail-out-back" : "saas-rail-out-forward"
409
+ ),
410
+ children: outgoing.body
411
+ }
412
+ ),
413
+ /* @__PURE__ */ jsxRuntime.jsx(
414
+ "div",
415
+ {
416
+ className: chunkH6OULCHF_cjs.cn(
417
+ "space-y-1",
418
+ outgoing && (outgoing.direction === "back" ? "saas-rail-in-back" : "saas-rail-in-forward")
419
+ ),
420
+ children: navBody
421
+ },
422
+ navKey
423
+ )
424
+ ]
425
+ }
426
+ ),
366
427
  settingsItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkH6OULCHF_cjs.cn("p-2 space-y-1", !borderless && "border-t border-sidebar-border"), children: settingsItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
367
428
  NavItem,
368
429
  {
@@ -408,6 +469,8 @@ function Sidebar({
408
469
  }
409
470
  function TopbarUserMenu({
410
471
  user,
472
+ userPlan,
473
+ billingLabel = "Subscription",
411
474
  onSignOut,
412
475
  onProfile,
413
476
  onSettings,
@@ -458,11 +521,35 @@ function TopbarUserMenu({
458
521
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 space-y-0.5", children: [
459
522
  item("Perfil", onProfile, lucideReact.UserCog),
460
523
  item("Configura\xE7\xF5es", onSettings, lucideReact.Settings),
461
- item("Cobran\xE7a", onBilling, lucideReact.CreditCard),
524
+ onBilling && /* @__PURE__ */ jsxRuntime.jsxs(
525
+ "button",
526
+ {
527
+ onClick: () => {
528
+ setOpen(false);
529
+ onBilling();
530
+ },
531
+ 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",
532
+ children: [
533
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className: "h-4 w-4 text-muted-foreground" }),
534
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-left", children: billingLabel }),
535
+ userPlan && /* @__PURE__ */ jsxRuntime.jsxs(
536
+ "span",
537
+ {
538
+ 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",
539
+ children: [
540
+ userPlan.paid ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Crown, { className: "h-3 w-3" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-3 w-3" }),
541
+ userPlan.label
542
+ ]
543
+ }
544
+ )
545
+ ]
546
+ },
547
+ "billing"
548
+ ),
462
549
  userMenuExtras?.map((e) => item(e.label, e.onClick)),
463
550
  onSignOut && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
464
551
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-1 border-t border-border" }),
465
- item("Sair", onSignOut)
552
+ item("Sair", onSignOut, lucideReact.LogOut)
466
553
  ] })
467
554
  ] })
468
555
  ]
@@ -570,7 +657,9 @@ var ICON_MAP2 = {
570
657
  Star: lucideReact.Star,
571
658
  Zap: lucideReact.Zap,
572
659
  Clapperboard: lucideReact.Clapperboard,
573
- Newspaper: lucideReact.Newspaper
660
+ Newspaper: lucideReact.Newspaper,
661
+ GraduationCap: lucideReact.GraduationCap,
662
+ Repeat: lucideReact.Repeat
574
663
  };
575
664
  function getIcon2(name) {
576
665
  return ICON_MAP2[name] ?? lucideReact.Home;
@@ -634,6 +723,7 @@ function Topbar({
634
723
  logo,
635
724
  user,
636
725
  onMenuClick,
726
+ orgSwitcher,
637
727
  leftContent,
638
728
  rightContent,
639
729
  currentPath = "/",
@@ -643,6 +733,8 @@ function Topbar({
643
733
  onProfile,
644
734
  onSettings,
645
735
  onBilling,
736
+ userPlan,
737
+ billingLabel,
646
738
  userMenuExtras
647
739
  }) {
648
740
  const setCommandPaletteOpen = useLayoutStore((s) => s.setCommandPaletteOpen);
@@ -664,7 +756,8 @@ function Topbar({
664
756
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "h-5 w-5" })
665
757
  }
666
758
  ),
667
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden shrink-0 items-center md:flex", children: logo ?? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg font-bold", children: "App" }) })
759
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden shrink-0 items-center md:flex", children: logo ?? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg font-bold", children: "App" }) }),
760
+ orgSwitcher && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden min-w-0 items-center md:flex", children: orgSwitcher })
668
761
  ] }),
669
762
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-8 hidden max-w-sm flex-1 md:flex", children: /* @__PURE__ */ jsxRuntime.jsxs(
670
763
  "button",
@@ -685,6 +778,8 @@ function Topbar({
685
778
  TopbarUserMenu,
686
779
  {
687
780
  user,
781
+ userPlan,
782
+ billingLabel,
688
783
  onSignOut,
689
784
  onProfile,
690
785
  onSettings,
@@ -727,6 +822,7 @@ function Topbar({
727
822
  children: [
728
823
  /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4" }),
729
824
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: item.label }),
825
+ item.premium && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Crown, { className: "h-3 w-3 text-amber-500", "aria-hidden": true }),
730
826
  item.badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full bg-primary px-1.5 py-0.5 text-[10px] font-semibold text-primary-foreground", children: item.badge })
731
827
  ]
732
828
  },
@@ -766,7 +862,10 @@ function SidebarLayout({
766
862
  notificationSlot,
767
863
  unreadCount = 0,
768
864
  hasBottomNav = false,
769
- mobileHeader = "minimal"
865
+ mobileHeader = "minimal",
866
+ sidebarSectionLabels,
867
+ sidebarNavKey,
868
+ sidebarNavDirection
770
869
  }) {
771
870
  const sidebarCollapsed = useLayoutStore((s) => s.sidebarCollapsed);
772
871
  const setSidebarCollapsed = useLayoutStore((s) => s.setSidebarCollapsed);
@@ -800,7 +899,10 @@ function SidebarLayout({
800
899
  borderless: false,
801
900
  userMenuSlot,
802
901
  notificationSlot,
803
- unreadCount
902
+ unreadCount,
903
+ sectionLabels: sidebarSectionLabels,
904
+ navKey: sidebarNavKey,
905
+ navDirection: sidebarNavDirection
804
906
  }
805
907
  ) }),
806
908
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkH6OULCHF_cjs.cn(
@@ -830,7 +932,7 @@ function SidebarLayout({
830
932
  topbarEnd
831
933
  ] })
832
934
  ] }),
833
- /* @__PURE__ */ jsxRuntime.jsx("main", { className: "flex-1 overflow-y-auto pb-16 md:pb-0", children }),
935
+ /* @__PURE__ */ jsxRuntime.jsx("main", { className: "min-w-0 flex-1 overflow-y-auto pb-16 md:pb-0", children }),
834
936
  /* @__PURE__ */ jsxRuntime.jsx(chunkOW73RZOU_cjs.SaveBar, {})
835
937
  ] }),
836
938
  mobileMenuOpen && /* @__PURE__ */ jsxRuntime.jsx(
@@ -866,11 +968,15 @@ function TopbarLayout({
866
968
  onProfile,
867
969
  onSettings,
868
970
  onBilling,
971
+ userPlan,
972
+ billingLabel,
869
973
  userMenuExtras,
974
+ orgSwitcher,
870
975
  frame,
871
976
  currentPath,
872
977
  topbarStart,
873
978
  topbarEnd,
979
+ notificationSlot,
874
980
  hasBottomNav = false
875
981
  }) {
876
982
  const [mobileMenuOpen, setMobileMenuOpen] = React3__namespace.useState(false);
@@ -887,13 +993,19 @@ function TopbarLayout({
887
993
  onProfile,
888
994
  onSettings,
889
995
  onBilling,
996
+ userPlan,
997
+ billingLabel,
890
998
  userMenuExtras,
999
+ orgSwitcher,
891
1000
  leftContent: topbarStart,
892
- rightContent: topbarEnd,
1001
+ rightContent: topbarEnd || notificationSlot ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1002
+ topbarEnd,
1003
+ notificationSlot
1004
+ ] }) : void 0,
893
1005
  onMenuClick: hasBottomNav ? void 0 : () => setMobileMenuOpen(true)
894
1006
  }
895
1007
  ),
896
- /* @__PURE__ */ jsxRuntime.jsx("main", { className: chunkH6OULCHF_cjs.cn("flex-1 overflow-y-auto pb-16 md:pb-0", frame && "md:bg-sidebar md:p-2"), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkH6OULCHF_cjs.cn("min-h-full", frame && "md:rounded-xl md:border md:border-border md:bg-card"), children }) }),
1008
+ /* @__PURE__ */ jsxRuntime.jsx("main", { className: chunkH6OULCHF_cjs.cn("flex min-w-0 min-h-0 flex-1 flex-col overflow-hidden", frame && "md:bg-sidebar md:p-2"), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkH6OULCHF_cjs.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__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1 overflow-y-auto pb-16 md:pb-0", children }) }) }),
897
1009
  /* @__PURE__ */ jsxRuntime.jsx(chunkOW73RZOU_cjs.SaveBar, {}),
898
1010
  mobileMenuOpen && /* @__PURE__ */ jsxRuntime.jsx(
899
1011
  MobileOverlay,
@@ -907,6 +1019,7 @@ function TopbarLayout({
907
1019
  onProfile,
908
1020
  onSettings,
909
1021
  onBilling,
1022
+ orgSwitcher,
910
1023
  userMenuSlot: user ? /* @__PURE__ */ jsxRuntime.jsx(DrawerUserRow, { user }) : void 0,
911
1024
  onClose: () => setMobileMenuOpen(false)
912
1025
  }
@@ -931,7 +1044,7 @@ function MinimalLayout({
931
1044
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3", children: logo ?? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg font-bold", children: "App" }) }),
932
1045
  headerEnd && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: headerEnd })
933
1046
  ] }),
934
- /* @__PURE__ */ jsxRuntime.jsx("main", { className: "flex-1 overflow-y-auto pb-16 md:pb-0", children })
1047
+ /* @__PURE__ */ jsxRuntime.jsx("main", { className: "min-w-0 flex-1 overflow-y-auto pb-16 md:pb-0", children })
935
1048
  ] });
936
1049
  }
937
1050
  function MobileOverlay({ onClose, onNavigate, ...sidebarProps }) {
@@ -1081,6 +1194,8 @@ function AppShell({
1081
1194
  onProfile,
1082
1195
  onSettings,
1083
1196
  onBilling,
1197
+ userPlan,
1198
+ billingLabel,
1084
1199
  pageTitle,
1085
1200
  currentPath,
1086
1201
  userMenuExtras,
@@ -1094,7 +1209,17 @@ function AppShell({
1094
1209
  mobileHeader = "minimal",
1095
1210
  userMenuSlot,
1096
1211
  notificationSlot,
1097
- unreadCount = 0
1212
+ unreadCount = 0,
1213
+ sidebarSectionLabels,
1214
+ sidebarNavKey,
1215
+ sidebarNavDirection,
1216
+ rightRail,
1217
+ rightRailOpen = true,
1218
+ defaultRightRailWidth,
1219
+ onRightRailWidthChange,
1220
+ rightRailMinWidth,
1221
+ rightRailMaxWidth,
1222
+ rightRailResizeLabel
1098
1223
  }) {
1099
1224
  const hasBottomNav = !!bottomNav?.length;
1100
1225
  const bottomBar = hasBottomNav ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -1135,6 +1260,9 @@ function AppShell({
1135
1260
  unreadCount,
1136
1261
  hasBottomNav,
1137
1262
  mobileHeader,
1263
+ sidebarSectionLabels,
1264
+ sidebarNavKey,
1265
+ sidebarNavDirection,
1138
1266
  children
1139
1267
  }
1140
1268
  );
@@ -1151,11 +1279,15 @@ function AppShell({
1151
1279
  onProfile,
1152
1280
  onSettings,
1153
1281
  onBilling,
1282
+ userPlan,
1283
+ billingLabel,
1154
1284
  userMenuExtras,
1285
+ orgSwitcher,
1155
1286
  frame: contentFrame,
1156
1287
  currentPath,
1157
1288
  topbarStart,
1158
1289
  topbarEnd,
1290
+ notificationSlot,
1159
1291
  hasBottomNav,
1160
1292
  children
1161
1293
  }
@@ -1169,11 +1301,142 @@ function AppShell({
1169
1301
  }
1170
1302
  }
1171
1303
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1172
- layoutElement,
1304
+ rightRail ? /* @__PURE__ */ jsxRuntime.jsx(
1305
+ SplitWithRightRail,
1306
+ {
1307
+ rail: rightRail,
1308
+ open: rightRailOpen,
1309
+ frame: contentFrame,
1310
+ defaultWidth: defaultRightRailWidth,
1311
+ onWidthChange: onRightRailWidthChange,
1312
+ minWidth: rightRailMinWidth,
1313
+ maxWidth: rightRailMaxWidth,
1314
+ resizeLabel: rightRailResizeLabel,
1315
+ children: layoutElement
1316
+ }
1317
+ ) : layoutElement,
1173
1318
  floatingAvatar,
1174
1319
  bottomBar
1175
1320
  ] });
1176
1321
  }
1322
+ function SplitWithRightRail({
1323
+ children,
1324
+ rail,
1325
+ open,
1326
+ frame,
1327
+ defaultWidth = 380,
1328
+ onWidthChange,
1329
+ minWidth = 300,
1330
+ maxWidth = 720,
1331
+ resizeLabel = "Resize panel"
1332
+ }) {
1333
+ const [width, setWidth] = React3__namespace.useState(defaultWidth);
1334
+ const [dragging, setDragging] = React3__namespace.useState(false);
1335
+ const clamp = React3__namespace.useCallback(
1336
+ (value) => Math.min(maxWidth, Math.max(minWidth, value)),
1337
+ [minWidth, maxWidth]
1338
+ );
1339
+ React3__namespace.useEffect(() => {
1340
+ if (!dragging) return;
1341
+ const onMove = (event) => {
1342
+ event.preventDefault();
1343
+ setWidth(clamp(window.innerWidth - event.clientX));
1344
+ };
1345
+ const stop = () => setDragging(false);
1346
+ window.addEventListener("pointermove", onMove);
1347
+ window.addEventListener("pointerup", stop);
1348
+ window.addEventListener("pointercancel", stop);
1349
+ const previousSelect = document.body.style.userSelect;
1350
+ const previousCursor = document.body.style.cursor;
1351
+ document.body.style.userSelect = "none";
1352
+ document.body.style.cursor = "col-resize";
1353
+ return () => {
1354
+ window.removeEventListener("pointermove", onMove);
1355
+ window.removeEventListener("pointerup", stop);
1356
+ window.removeEventListener("pointercancel", stop);
1357
+ document.body.style.userSelect = previousSelect;
1358
+ document.body.style.cursor = previousCursor;
1359
+ };
1360
+ }, [dragging, clamp]);
1361
+ React3__namespace.useEffect(() => {
1362
+ if (dragging) return;
1363
+ onWidthChange?.(width);
1364
+ }, [dragging]);
1365
+ const nudge = (delta) => setWidth((current) => clamp(current + delta));
1366
+ return (
1367
+ // Sidebar tone always: the gutter and the divider sit in the shell's
1368
+ // chrome, next to the menu — painting them page-white put a bright strip
1369
+ // between the dark chrome and the rail, which read as a seam rather than
1370
+ // as space.
1371
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkH6OULCHF_cjs.cn("flex h-screen w-full overflow-hidden bg-sidebar", !frame && "md:bg-background"), children: [
1372
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children }),
1373
+ /* @__PURE__ */ jsxRuntime.jsxs(
1374
+ "div",
1375
+ {
1376
+ role: "separator",
1377
+ "aria-orientation": "vertical",
1378
+ "aria-label": resizeLabel,
1379
+ "aria-valuenow": width,
1380
+ "aria-valuemin": minWidth,
1381
+ "aria-valuemax": maxWidth,
1382
+ tabIndex: 0,
1383
+ onPointerDown: (event) => {
1384
+ event.preventDefault();
1385
+ setDragging(true);
1386
+ },
1387
+ onDoubleClick: () => setWidth(clamp(defaultWidth)),
1388
+ onKeyDown: (event) => {
1389
+ if (event.key === "ArrowLeft") {
1390
+ event.preventDefault();
1391
+ nudge(24);
1392
+ } else if (event.key === "ArrowRight") {
1393
+ event.preventDefault();
1394
+ nudge(-24);
1395
+ } else if (event.key === "Home") {
1396
+ event.preventDefault();
1397
+ setWidth(maxWidth);
1398
+ } else if (event.key === "End") {
1399
+ event.preventDefault();
1400
+ setWidth(minWidth);
1401
+ }
1402
+ },
1403
+ className: chunkH6OULCHF_cjs.cn(
1404
+ "group relative hidden w-1 shrink-0 cursor-col-resize focus-visible:outline-none",
1405
+ open && "md:block"
1406
+ ),
1407
+ children: [
1408
+ /* @__PURE__ */ jsxRuntime.jsx(
1409
+ "span",
1410
+ {
1411
+ className: chunkH6OULCHF_cjs.cn(
1412
+ "absolute inset-y-6 left-1/2 w-px -translate-x-1/2 rounded-full bg-transparent transition-colors",
1413
+ "group-hover:bg-primary/60 group-focus-visible:bg-primary",
1414
+ dragging && "bg-primary"
1415
+ )
1416
+ }
1417
+ ),
1418
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-y-0 -left-1.5 -right-1.5" })
1419
+ ]
1420
+ }
1421
+ ),
1422
+ /* @__PURE__ */ jsxRuntime.jsx(
1423
+ "aside",
1424
+ {
1425
+ style: { ["--fayz-rail-w"]: `${width}px` },
1426
+ className: chunkH6OULCHF_cjs.cn(
1427
+ "w-0 shrink-0 overflow-hidden",
1428
+ // Animating WIDTH is what makes the app glide back instead of
1429
+ // snapping; skipped mid-drag so the divider stays glued to the cursor.
1430
+ !dragging && "motion-safe:transition-[width] motion-safe:duration-200 motion-safe:ease-out",
1431
+ open && "md:w-[var(--fayz-rail-w)]",
1432
+ frame && "md:py-2 md:pr-2"
1433
+ ),
1434
+ children: rail
1435
+ }
1436
+ )
1437
+ ] })
1438
+ );
1439
+ }
1177
1440
  var NavTransitionContext = React3__namespace.createContext("slide");
1178
1441
  function NavTransitionProvider({ value, children }) {
1179
1442
  return /* @__PURE__ */ jsxRuntime.jsx(NavTransitionContext.Provider, { value, children });
@@ -1203,6 +1466,11 @@ function PageHeaderActions({ children }) {
1203
1466
  if (slot) return reactDom.createPortal(children, slot);
1204
1467
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4 flex items-center justify-end gap-2", children });
1205
1468
  }
1469
+ function PremiumBadge({ className }) {
1470
+ const t = core.useTranslation();
1471
+ const tip = t("upgrade.badgeTooltip");
1472
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { title: tip, "aria-label": tip, className: chunkH6OULCHF_cjs.cn("inline-flex shrink-0", className), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Crown, { className: "h-3.5 w-3.5 text-amber-500", "aria-hidden": true }) });
1473
+ }
1206
1474
  var ModuleLayoutContext = React3__namespace.createContext("rail");
1207
1475
  function ModuleLayoutProvider({ variant, children }) {
1208
1476
  return /* @__PURE__ */ jsxRuntime.jsx(ModuleLayoutContext.Provider, { value: variant, children });
@@ -1229,11 +1497,12 @@ function NavItem2({ item }) {
1229
1497
  children: [
1230
1498
  Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4 shrink-0" }),
1231
1499
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-left truncate", children: item.label }),
1500
+ item.premium && /* @__PURE__ */ jsxRuntime.jsx(PremiumBadge, { className: "ml-1" }),
1232
1501
  hasChildren && (expanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-3.5 w-3.5 shrink-0 opacity-50" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-3.5 w-3.5 shrink-0 opacity-50" }))
1233
1502
  ]
1234
1503
  }
1235
1504
  ),
1236
- hasChildren && expanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-4 mt-0.5 space-y-0.5 border-l pl-2", children: item.children.map((child) => /* @__PURE__ */ jsxRuntime.jsx(
1505
+ hasChildren && expanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-4 mt-0.5 space-y-0.5 border-l pl-2", children: item.children.map((child) => /* @__PURE__ */ jsxRuntime.jsxs(
1237
1506
  "button",
1238
1507
  {
1239
1508
  type: "button",
@@ -1242,7 +1511,10 @@ function NavItem2({ item }) {
1242
1511
  "flex items-center w-full rounded-md px-2.5 py-1 text-xs transition-colors",
1243
1512
  child.active ? "text-primary font-medium bg-primary/5" : "text-muted-foreground hover:text-foreground hover:bg-muted/50"
1244
1513
  ),
1245
- children: child.label
1514
+ children: [
1515
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-left truncate", children: child.label }),
1516
+ child.premium && /* @__PURE__ */ jsxRuntime.jsx(PremiumBadge, { className: "ml-1" })
1517
+ ]
1246
1518
  },
1247
1519
  child.id
1248
1520
  )) })
@@ -1286,6 +1558,7 @@ function MobileTabs({ nav }) {
1286
1558
  children: [
1287
1559
  Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-3 w-3" }),
1288
1560
  item.label,
1561
+ item.premium && /* @__PURE__ */ jsxRuntime.jsx(PremiumBadge, {}),
1289
1562
  hasChildren && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: chunkH6OULCHF_cjs.cn("h-2.5 w-2.5 transition-transform", isExpanded && "rotate-180") })
1290
1563
  ]
1291
1564
  },
@@ -1295,7 +1568,7 @@ function MobileTabs({ nav }) {
1295
1568
  expandedId && (() => {
1296
1569
  const item = nav.find((n) => n.id === expandedId);
1297
1570
  if (!item?.children) return null;
1298
- return /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsx(
1571
+ return /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.jsxs(
1299
1572
  "button",
1300
1573
  {
1301
1574
  type: "button",
@@ -1307,7 +1580,10 @@ function MobileTabs({ nav }) {
1307
1580
  "whitespace-nowrap rounded-full px-2.5 py-1 text-[11px] font-medium transition-colors shrink-0",
1308
1581
  child.active ? "bg-foreground/10 text-foreground" : "text-muted-foreground hover:text-foreground"
1309
1582
  ),
1310
- children: child.label
1583
+ children: [
1584
+ child.label,
1585
+ child.premium && /* @__PURE__ */ jsxRuntime.jsx(PremiumBadge, {})
1586
+ ]
1311
1587
  },
1312
1588
  child.id
1313
1589
  )) });
@@ -1399,7 +1675,8 @@ function ModuleHeader({ nav }) {
1399
1675
  ),
1400
1676
  children: [
1401
1677
  Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4" }),
1402
- item.label
1678
+ item.label,
1679
+ item.premium && /* @__PURE__ */ jsxRuntime.jsx(PremiumBadge, {})
1403
1680
  ]
1404
1681
  },
1405
1682
  item.id
@@ -1545,5 +1822,5 @@ exports.useModuleHeaderActionsSlot = useModuleHeaderActionsSlot;
1545
1822
  exports.useModuleHeaderSlot = useModuleHeaderSlot;
1546
1823
  exports.useModuleLayout = useModuleLayout;
1547
1824
  exports.useNavTransition = useNavTransition;
1548
- //# sourceMappingURL=chunk-XAOGMWLC.cjs.map
1549
- //# sourceMappingURL=chunk-XAOGMWLC.cjs.map
1825
+ //# sourceMappingURL=chunk-XIRJGVDK.cjs.map
1826
+ //# sourceMappingURL=chunk-XIRJGVDK.cjs.map