@fayz-ai/ui 0.8.2 → 0.8.4

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 (63) hide show
  1. package/dist/{chunk-XAOGMWLC.cjs → chunk-7ZQQZD4Q.cjs} +354 -80
  2. package/dist/chunk-7ZQQZD4Q.cjs.map +1 -0
  3. package/dist/{chunk-IEYCOJTY.cjs → chunk-B3BTZDTA.cjs} +10 -42
  4. package/dist/chunk-B3BTZDTA.cjs.map +1 -0
  5. package/dist/{chunk-O5F4LLSL.js → chunk-DYMBFHD7.js} +8 -7
  6. package/dist/chunk-DYMBFHD7.js.map +1 -0
  7. package/dist/{chunk-FY7OZNKU.js → chunk-G6OKZ7WL.js} +35 -8
  8. package/dist/chunk-G6OKZ7WL.js.map +1 -0
  9. package/dist/{chunk-W5O2X277.js → chunk-M34ACV5E.js} +27 -4
  10. package/dist/chunk-M34ACV5E.js.map +1 -0
  11. package/dist/{chunk-NWPMNPGR.cjs → chunk-MUGRP5DD.cjs} +57 -34
  12. package/dist/chunk-MUGRP5DD.cjs.map +1 -0
  13. package/dist/{chunk-ODY3GZ3Y.cjs → chunk-NZV47HWO.cjs} +36 -7
  14. package/dist/chunk-NZV47HWO.cjs.map +1 -0
  15. package/dist/{chunk-J3IUFUNR.js → chunk-R4LPSXTT.js} +8 -38
  16. package/dist/chunk-R4LPSXTT.js.map +1 -0
  17. package/dist/{chunk-TDGSY5W6.cjs → chunk-R4SQ2GVD.cjs} +8 -7
  18. package/dist/chunk-R4SQ2GVD.cjs.map +1 -0
  19. package/dist/{chunk-MZZMZYSE.js → chunk-VVQ45ZDZ.js} +357 -83
  20. package/dist/chunk-VVQ45ZDZ.js.map +1 -0
  21. package/dist/dashboard/OnboardingWidget.d.ts.map +1 -1
  22. package/dist/dashboard/index.cjs +26 -26
  23. package/dist/dashboard/index.js +2 -2
  24. package/dist/index.cjs +137 -137
  25. package/dist/index.js +5 -5
  26. package/dist/layout/AppShell.d.ts +41 -1
  27. package/dist/layout/AppShell.d.ts.map +1 -1
  28. package/dist/layout/ModulePage.d.ts +9 -6
  29. package/dist/layout/ModulePage.d.ts.map +1 -1
  30. package/dist/layout/Sidebar.d.ts +24 -1
  31. package/dist/layout/Sidebar.d.ts.map +1 -1
  32. package/dist/layout/Topbar.d.ts +13 -1
  33. package/dist/layout/Topbar.d.ts.map +1 -1
  34. package/dist/layout/index.cjs +19 -19
  35. package/dist/layout/index.js +1 -1
  36. package/dist/primitives/data-table.d.ts.map +1 -1
  37. package/dist/primitives/index.cjs +83 -83
  38. package/dist/primitives/index.js +2 -2
  39. package/dist/primitives/search-select.d.ts +3 -1
  40. package/dist/primitives/search-select.d.ts.map +1 -1
  41. package/dist/theme/index.cjs +8 -8
  42. package/dist/theme/index.d.ts.map +1 -1
  43. package/dist/theme/index.js +1 -1
  44. package/package.json +3 -3
  45. package/src/dashboard/OnboardingWidget.tsx +41 -1
  46. package/src/layout/AppShell.tsx +255 -7
  47. package/src/layout/ModulePage.tsx +32 -3
  48. package/src/layout/Sidebar.tsx +198 -61
  49. package/src/layout/Topbar.tsx +51 -4
  50. package/src/primitives/data-table.tsx +10 -1
  51. package/src/primitives/search-select.tsx +12 -4
  52. package/src/styles.css +34 -0
  53. package/src/theme/index.ts +9 -6
  54. package/dist/chunk-FY7OZNKU.js.map +0 -1
  55. package/dist/chunk-IEYCOJTY.cjs.map +0 -1
  56. package/dist/chunk-J3IUFUNR.js.map +0 -1
  57. package/dist/chunk-MZZMZYSE.js.map +0 -1
  58. package/dist/chunk-NWPMNPGR.cjs.map +0 -1
  59. package/dist/chunk-O5F4LLSL.js.map +0 -1
  60. package/dist/chunk-ODY3GZ3Y.cjs.map +0 -1
  61. package/dist/chunk-TDGSY5W6.cjs.map +0 -1
  62. package/dist/chunk-W5O2X277.js.map +0 -1
  63. package/dist/chunk-XAOGMWLC.cjs.map +0 -1
@@ -61,6 +61,7 @@ var ICON_MAP = {
61
61
  ShoppingCart: lucideReact.ShoppingCart,
62
62
  Target: lucideReact.Target,
63
63
  Wrench: lucideReact.Wrench,
64
+ Truck: lucideReact.Truck,
64
65
  Receipt: lucideReact.Receipt,
65
66
  ShoppingBag: lucideReact.ShoppingBag,
66
67
  ClipboardList: lucideReact.ClipboardList,
@@ -128,8 +129,17 @@ var ICON_MAP = {
128
129
  Workflow: lucideReact.Workflow,
129
130
  Boxes: lucideReact.Boxes,
130
131
  Clock3: lucideReact.Clock3,
131
- FileCheck2: lucideReact.FileCheck2
132
+ FileCheck2: lucideReact.FileCheck2,
133
+ GraduationCap: lucideReact.GraduationCap,
134
+ Repeat: lucideReact.Repeat,
135
+ User: lucideReact.User,
136
+ Palette: lucideReact.Palette,
137
+ ShieldCheck: lucideReact.ShieldCheck,
138
+ SlidersHorizontal: lucideReact.SlidersHorizontal,
139
+ Puzzle: lucideReact.Puzzle
132
140
  };
141
+ var RAIL_PUSH_MS = 260;
142
+ var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React3__namespace.useLayoutEffect : React3__namespace.useEffect;
133
143
  function getIcon(name) {
134
144
  return ICON_MAP[name] ?? lucideReact.Home;
135
145
  }
@@ -140,25 +150,23 @@ function NavItem({
140
150
  onNavigate
141
151
  }) {
142
152
  const Icon = getIcon(item.icon);
143
- const content = /* @__PURE__ */ jsxRuntime.jsxs(
144
- "button",
145
- {
146
- onClick: () => onNavigate(item.route),
147
- className: chunkH6OULCHF_cjs.cn(
148
- "flex w-full items-center gap-3 rounded-md px-2.5 py-1.5 text-[13px] font-medium transition-colors",
149
- "hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground",
150
- isActive ? "bg-sidebar-accent font-semibold text-sidebar-accent-foreground shadow-sm" : "text-sidebar-foreground/80",
151
- collapsed && "justify-center px-2"
152
- ),
153
- children: [
154
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4 shrink-0" }),
155
- !collapsed && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
156
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate text-left", children: item.label }),
157
- 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
- ] })
159
- ]
160
- }
153
+ const isExternal = !!item.href;
154
+ const className = chunkH6OULCHF_cjs.cn(
155
+ "flex w-full items-center gap-3 rounded-md px-2.5 py-1.5 text-[13px] font-medium transition-colors",
156
+ "hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground",
157
+ isActive ? "bg-sidebar-accent font-semibold text-sidebar-accent-foreground shadow-sm" : "text-sidebar-foreground/80",
158
+ collapsed && "justify-center px-2"
161
159
  );
160
+ const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
161
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4 shrink-0" }),
162
+ !collapsed && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
163
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate text-left", children: item.label }),
164
+ isExternal && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "ml-auto h-3.5 w-3.5 shrink-0 opacity-50", "aria-hidden": true }),
165
+ item.premium && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Crown, { className: chunkH6OULCHF_cjs.cn("h-3.5 w-3.5 shrink-0 text-amber-500", !isExternal && "ml-auto"), "aria-hidden": true }),
166
+ item.badge !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: chunkH6OULCHF_cjs.cn("rounded-full bg-primary px-2 py-0.5 text-xs font-semibold text-primary-foreground", !isExternal && !item.premium && "ml-auto"), children: item.badge })
167
+ ] })
168
+ ] });
169
+ const content = isExternal ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.href, target: "_blank", rel: "noopener noreferrer", className, children: inner }) : /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => onNavigate(item.route), className, children: inner });
162
170
  if (collapsed) {
163
171
  return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip__namespace.Root, { delayDuration: 0, children: [
164
172
  /* @__PURE__ */ jsxRuntime.jsx(Tooltip__namespace.Trigger, { asChild: true, children: content }),
@@ -170,6 +178,7 @@ function NavItem({
170
178
  className: "fayz-glass-surface z-50 rounded-md bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md",
171
179
  children: [
172
180
  item.label,
181
+ item.premium && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Crown, { className: "ml-1.5 inline h-3 w-3 text-amber-500", "aria-hidden": true }),
173
182
  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
183
  /* @__PURE__ */ jsxRuntime.jsx(Tooltip__namespace.Arrow, { className: "fill-popover" })
175
184
  ]
@@ -250,21 +259,18 @@ function NavGroup({
250
259
  open && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-4 mt-0.5 space-y-0.5 border-l border-sidebar-border/50 pl-3", children: item.children?.map((child) => {
251
260
  const ChildIcon = getIcon(child.icon);
252
261
  const isActive = child.route === activeRoute;
253
- return /* @__PURE__ */ jsxRuntime.jsxs(
254
- "button",
255
- {
256
- onClick: () => onNavigate(child.route),
257
- className: chunkH6OULCHF_cjs.cn(
258
- "flex w-full items-center gap-2.5 rounded-md px-2 py-1.5 text-sm transition-colors",
259
- isActive ? "font-medium text-sidebar-accent-foreground" : "text-sidebar-muted hover:text-sidebar-accent-foreground"
260
- ),
261
- children: [
262
- /* @__PURE__ */ jsxRuntime.jsx(ChildIcon, { className: "h-3.5 w-3.5 shrink-0" }),
263
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: child.label })
264
- ]
265
- },
266
- child.id
262
+ const childExternal = !!child.href;
263
+ const childClass = chunkH6OULCHF_cjs.cn(
264
+ "flex w-full items-center gap-2.5 rounded-md px-2 py-1.5 text-sm transition-colors",
265
+ isActive ? "font-medium text-sidebar-accent-foreground" : "text-sidebar-muted hover:text-sidebar-accent-foreground"
267
266
  );
267
+ const childInner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
268
+ /* @__PURE__ */ jsxRuntime.jsx(ChildIcon, { className: "h-3.5 w-3.5 shrink-0" }),
269
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate text-left", children: child.label }),
270
+ childExternal && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-3 w-3 shrink-0 opacity-50", "aria-hidden": true }),
271
+ child.premium && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Crown, { className: "h-3 w-3 shrink-0 text-amber-500", "aria-hidden": true })
272
+ ] });
273
+ return childExternal ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: child.href, target: "_blank", rel: "noopener noreferrer", className: childClass, children: childInner }, child.id) : /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => onNavigate(child.route), className: childClass, children: childInner }, child.id);
268
274
  }) })
269
275
  ] });
270
276
  }
@@ -282,7 +288,10 @@ function Sidebar({
282
288
  borderless,
283
289
  userMenuSlot,
284
290
  notificationSlot,
285
- unreadCount = 0
291
+ unreadCount = 0,
292
+ sectionLabels,
293
+ navKey,
294
+ navDirection = "forward"
286
295
  }) {
287
296
  const currentPath = currentPathProp;
288
297
  const setCommandPaletteOpen = useLayoutStore((s) => s.setCommandPaletteOpen);
@@ -293,6 +302,47 @@ function Sidebar({
293
302
  const handleNavigate = (route) => {
294
303
  onNavigate?.(route);
295
304
  };
305
+ 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;
306
+ const renderItem = (item) => item.children && item.children.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(NavGroup, { item, collapsed, activeRoute, onNavigate: handleNavigate }, item.id) : /* @__PURE__ */ jsxRuntime.jsx(
307
+ NavItem,
308
+ {
309
+ item,
310
+ collapsed,
311
+ isActive: item.route === activeRoute,
312
+ onNavigate: handleNavigate
313
+ },
314
+ item.id
315
+ );
316
+ const navBody = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
317
+ topContent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4 space-y-2", children: React3__namespace.isValidElement(topContent) ? React3__namespace.cloneElement(topContent, { collapsed }) : topContent }),
318
+ mainItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
319
+ sectionHeading(sectionLabels?.main),
320
+ mainItems.map(renderItem)
321
+ ] }),
322
+ secondaryItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-6 space-y-1", children: [
323
+ sectionHeading(sectionLabels?.secondary),
324
+ secondaryItems.map(renderItem)
325
+ ] })
326
+ ] });
327
+ const [outgoing, setOutgoing] = React3__namespace.useState(null);
328
+ const lastBodyRef = React3__namespace.useRef(null);
329
+ const lastKeyRef = React3__namespace.useRef(navKey);
330
+ const timerRef = React3__namespace.useRef(null);
331
+ useIsomorphicLayoutEffect(() => {
332
+ if (lastKeyRef.current !== navKey) {
333
+ const previousBody = lastBodyRef.current;
334
+ lastKeyRef.current = navKey;
335
+ if (previousBody) {
336
+ setOutgoing({ body: previousBody, direction: navDirection });
337
+ if (timerRef.current) clearTimeout(timerRef.current);
338
+ timerRef.current = setTimeout(() => setOutgoing(null), RAIL_PUSH_MS);
339
+ }
340
+ }
341
+ lastBodyRef.current = navBody;
342
+ });
343
+ React3__namespace.useEffect(() => () => {
344
+ if (timerRef.current) clearTimeout(timerRef.current);
345
+ }, []);
296
346
  return /* @__PURE__ */ jsxRuntime.jsx(Tooltip__namespace.Provider, { children: /* @__PURE__ */ jsxRuntime.jsxs(
297
347
  "aside",
298
348
  {
@@ -336,33 +386,41 @@ function Sidebar({
336
386
  ]
337
387
  }
338
388
  ),
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
- ] }),
389
+ /* @__PURE__ */ jsxRuntime.jsxs(
390
+ "nav",
391
+ {
392
+ className: chunkH6OULCHF_cjs.cn(
393
+ "relative flex-1 p-2",
394
+ // scrollbar-none: the rail still scrolls, but without the native
395
+ // scrollbar gutter eating into the nav items.
396
+ outgoing ? "overflow-hidden" : "overflow-y-auto scrollbar-none"
397
+ ),
398
+ children: [
399
+ outgoing && /* @__PURE__ */ jsxRuntime.jsx(
400
+ "div",
401
+ {
402
+ "aria-hidden": true,
403
+ className: chunkH6OULCHF_cjs.cn(
404
+ "pointer-events-none absolute inset-x-2 top-2 space-y-1",
405
+ outgoing.direction === "back" ? "saas-rail-out-back" : "saas-rail-out-forward"
406
+ ),
407
+ children: outgoing.body
408
+ }
409
+ ),
410
+ /* @__PURE__ */ jsxRuntime.jsx(
411
+ "div",
412
+ {
413
+ className: chunkH6OULCHF_cjs.cn(
414
+ "space-y-1",
415
+ outgoing && (outgoing.direction === "back" ? "saas-rail-in-back" : "saas-rail-in-forward")
416
+ ),
417
+ children: navBody
418
+ },
419
+ navKey
420
+ )
421
+ ]
422
+ }
423
+ ),
366
424
  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
425
  NavItem,
368
426
  {
@@ -408,6 +466,8 @@ function Sidebar({
408
466
  }
409
467
  function TopbarUserMenu({
410
468
  user,
469
+ userPlan,
470
+ billingLabel = "Subscription",
411
471
  onSignOut,
412
472
  onProfile,
413
473
  onSettings,
@@ -458,11 +518,35 @@ function TopbarUserMenu({
458
518
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 space-y-0.5", children: [
459
519
  item("Perfil", onProfile, lucideReact.UserCog),
460
520
  item("Configura\xE7\xF5es", onSettings, lucideReact.Settings),
461
- item("Cobran\xE7a", onBilling, lucideReact.CreditCard),
521
+ onBilling && /* @__PURE__ */ jsxRuntime.jsxs(
522
+ "button",
523
+ {
524
+ onClick: () => {
525
+ setOpen(false);
526
+ onBilling();
527
+ },
528
+ 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",
529
+ children: [
530
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CreditCard, { className: "h-4 w-4 text-muted-foreground" }),
531
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-left", children: billingLabel }),
532
+ userPlan && /* @__PURE__ */ jsxRuntime.jsxs(
533
+ "span",
534
+ {
535
+ 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",
536
+ children: [
537
+ userPlan.paid ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Crown, { className: "h-3 w-3" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "h-3 w-3" }),
538
+ userPlan.label
539
+ ]
540
+ }
541
+ )
542
+ ]
543
+ },
544
+ "billing"
545
+ ),
462
546
  userMenuExtras?.map((e) => item(e.label, e.onClick)),
463
547
  onSignOut && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
464
548
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-1 border-t border-border" }),
465
- item("Sair", onSignOut)
549
+ item("Sair", onSignOut, lucideReact.LogOut)
466
550
  ] })
467
551
  ] })
468
552
  ]
@@ -570,7 +654,9 @@ var ICON_MAP2 = {
570
654
  Star: lucideReact.Star,
571
655
  Zap: lucideReact.Zap,
572
656
  Clapperboard: lucideReact.Clapperboard,
573
- Newspaper: lucideReact.Newspaper
657
+ Newspaper: lucideReact.Newspaper,
658
+ GraduationCap: lucideReact.GraduationCap,
659
+ Repeat: lucideReact.Repeat
574
660
  };
575
661
  function getIcon2(name) {
576
662
  return ICON_MAP2[name] ?? lucideReact.Home;
@@ -634,6 +720,7 @@ function Topbar({
634
720
  logo,
635
721
  user,
636
722
  onMenuClick,
723
+ orgSwitcher,
637
724
  leftContent,
638
725
  rightContent,
639
726
  currentPath = "/",
@@ -643,6 +730,8 @@ function Topbar({
643
730
  onProfile,
644
731
  onSettings,
645
732
  onBilling,
733
+ userPlan,
734
+ billingLabel,
646
735
  userMenuExtras
647
736
  }) {
648
737
  const setCommandPaletteOpen = useLayoutStore((s) => s.setCommandPaletteOpen);
@@ -664,7 +753,8 @@ function Topbar({
664
753
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "h-5 w-5" })
665
754
  }
666
755
  ),
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" }) })
756
+ /* @__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" }) }),
757
+ orgSwitcher && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden min-w-0 items-center md:flex", children: orgSwitcher })
668
758
  ] }),
669
759
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-8 hidden max-w-sm flex-1 md:flex", children: /* @__PURE__ */ jsxRuntime.jsxs(
670
760
  "button",
@@ -685,6 +775,8 @@ function Topbar({
685
775
  TopbarUserMenu,
686
776
  {
687
777
  user,
778
+ userPlan,
779
+ billingLabel,
688
780
  onSignOut,
689
781
  onProfile,
690
782
  onSettings,
@@ -727,6 +819,7 @@ function Topbar({
727
819
  children: [
728
820
  /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4" }),
729
821
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: item.label }),
822
+ item.premium && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Crown, { className: "h-3 w-3 text-amber-500", "aria-hidden": true }),
730
823
  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
824
  ]
732
825
  },
@@ -766,7 +859,10 @@ function SidebarLayout({
766
859
  notificationSlot,
767
860
  unreadCount = 0,
768
861
  hasBottomNav = false,
769
- mobileHeader = "minimal"
862
+ mobileHeader = "minimal",
863
+ sidebarSectionLabels,
864
+ sidebarNavKey,
865
+ sidebarNavDirection
770
866
  }) {
771
867
  const sidebarCollapsed = useLayoutStore((s) => s.sidebarCollapsed);
772
868
  const setSidebarCollapsed = useLayoutStore((s) => s.setSidebarCollapsed);
@@ -800,7 +896,10 @@ function SidebarLayout({
800
896
  borderless: false,
801
897
  userMenuSlot,
802
898
  notificationSlot,
803
- unreadCount
899
+ unreadCount,
900
+ sectionLabels: sidebarSectionLabels,
901
+ navKey: sidebarNavKey,
902
+ navDirection: sidebarNavDirection
804
903
  }
805
904
  ) }),
806
905
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkH6OULCHF_cjs.cn(
@@ -830,7 +929,7 @@ function SidebarLayout({
830
929
  topbarEnd
831
930
  ] })
832
931
  ] }),
833
- /* @__PURE__ */ jsxRuntime.jsx("main", { className: "flex-1 overflow-y-auto pb-16 md:pb-0", children }),
932
+ /* @__PURE__ */ jsxRuntime.jsx("main", { className: "min-w-0 flex-1 overflow-y-auto pb-16 md:pb-0", children }),
834
933
  /* @__PURE__ */ jsxRuntime.jsx(chunkOW73RZOU_cjs.SaveBar, {})
835
934
  ] }),
836
935
  mobileMenuOpen && /* @__PURE__ */ jsxRuntime.jsx(
@@ -866,11 +965,15 @@ function TopbarLayout({
866
965
  onProfile,
867
966
  onSettings,
868
967
  onBilling,
968
+ userPlan,
969
+ billingLabel,
869
970
  userMenuExtras,
971
+ orgSwitcher,
870
972
  frame,
871
973
  currentPath,
872
974
  topbarStart,
873
975
  topbarEnd,
976
+ notificationSlot,
874
977
  hasBottomNav = false
875
978
  }) {
876
979
  const [mobileMenuOpen, setMobileMenuOpen] = React3__namespace.useState(false);
@@ -887,13 +990,19 @@ function TopbarLayout({
887
990
  onProfile,
888
991
  onSettings,
889
992
  onBilling,
993
+ userPlan,
994
+ billingLabel,
890
995
  userMenuExtras,
996
+ orgSwitcher,
891
997
  leftContent: topbarStart,
892
- rightContent: topbarEnd,
998
+ rightContent: topbarEnd || notificationSlot ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
999
+ topbarEnd,
1000
+ notificationSlot
1001
+ ] }) : void 0,
893
1002
  onMenuClick: hasBottomNav ? void 0 : () => setMobileMenuOpen(true)
894
1003
  }
895
1004
  ),
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 }) }),
1005
+ /* @__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
1006
  /* @__PURE__ */ jsxRuntime.jsx(chunkOW73RZOU_cjs.SaveBar, {}),
898
1007
  mobileMenuOpen && /* @__PURE__ */ jsxRuntime.jsx(
899
1008
  MobileOverlay,
@@ -907,6 +1016,7 @@ function TopbarLayout({
907
1016
  onProfile,
908
1017
  onSettings,
909
1018
  onBilling,
1019
+ orgSwitcher,
910
1020
  userMenuSlot: user ? /* @__PURE__ */ jsxRuntime.jsx(DrawerUserRow, { user }) : void 0,
911
1021
  onClose: () => setMobileMenuOpen(false)
912
1022
  }
@@ -931,7 +1041,7 @@ function MinimalLayout({
931
1041
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3", children: logo ?? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg font-bold", children: "App" }) }),
932
1042
  headerEnd && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: headerEnd })
933
1043
  ] }),
934
- /* @__PURE__ */ jsxRuntime.jsx("main", { className: "flex-1 overflow-y-auto pb-16 md:pb-0", children })
1044
+ /* @__PURE__ */ jsxRuntime.jsx("main", { className: "min-w-0 flex-1 overflow-y-auto pb-16 md:pb-0", children })
935
1045
  ] });
936
1046
  }
937
1047
  function MobileOverlay({ onClose, onNavigate, ...sidebarProps }) {
@@ -1081,6 +1191,8 @@ function AppShell({
1081
1191
  onProfile,
1082
1192
  onSettings,
1083
1193
  onBilling,
1194
+ userPlan,
1195
+ billingLabel,
1084
1196
  pageTitle,
1085
1197
  currentPath,
1086
1198
  userMenuExtras,
@@ -1094,7 +1206,17 @@ function AppShell({
1094
1206
  mobileHeader = "minimal",
1095
1207
  userMenuSlot,
1096
1208
  notificationSlot,
1097
- unreadCount = 0
1209
+ unreadCount = 0,
1210
+ sidebarSectionLabels,
1211
+ sidebarNavKey,
1212
+ sidebarNavDirection,
1213
+ rightRail,
1214
+ rightRailOpen = true,
1215
+ defaultRightRailWidth,
1216
+ onRightRailWidthChange,
1217
+ rightRailMinWidth,
1218
+ rightRailMaxWidth,
1219
+ rightRailResizeLabel
1098
1220
  }) {
1099
1221
  const hasBottomNav = !!bottomNav?.length;
1100
1222
  const bottomBar = hasBottomNav ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -1135,6 +1257,9 @@ function AppShell({
1135
1257
  unreadCount,
1136
1258
  hasBottomNav,
1137
1259
  mobileHeader,
1260
+ sidebarSectionLabels,
1261
+ sidebarNavKey,
1262
+ sidebarNavDirection,
1138
1263
  children
1139
1264
  }
1140
1265
  );
@@ -1151,11 +1276,15 @@ function AppShell({
1151
1276
  onProfile,
1152
1277
  onSettings,
1153
1278
  onBilling,
1279
+ userPlan,
1280
+ billingLabel,
1154
1281
  userMenuExtras,
1282
+ orgSwitcher,
1155
1283
  frame: contentFrame,
1156
1284
  currentPath,
1157
1285
  topbarStart,
1158
1286
  topbarEnd,
1287
+ notificationSlot,
1159
1288
  hasBottomNav,
1160
1289
  children
1161
1290
  }
@@ -1169,11 +1298,142 @@ function AppShell({
1169
1298
  }
1170
1299
  }
1171
1300
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1172
- layoutElement,
1301
+ rightRail ? /* @__PURE__ */ jsxRuntime.jsx(
1302
+ SplitWithRightRail,
1303
+ {
1304
+ rail: rightRail,
1305
+ open: rightRailOpen,
1306
+ frame: contentFrame,
1307
+ defaultWidth: defaultRightRailWidth,
1308
+ onWidthChange: onRightRailWidthChange,
1309
+ minWidth: rightRailMinWidth,
1310
+ maxWidth: rightRailMaxWidth,
1311
+ resizeLabel: rightRailResizeLabel,
1312
+ children: layoutElement
1313
+ }
1314
+ ) : layoutElement,
1173
1315
  floatingAvatar,
1174
1316
  bottomBar
1175
1317
  ] });
1176
1318
  }
1319
+ function SplitWithRightRail({
1320
+ children,
1321
+ rail,
1322
+ open,
1323
+ frame,
1324
+ defaultWidth = 380,
1325
+ onWidthChange,
1326
+ minWidth = 300,
1327
+ maxWidth = 720,
1328
+ resizeLabel = "Resize panel"
1329
+ }) {
1330
+ const [width, setWidth] = React3__namespace.useState(defaultWidth);
1331
+ const [dragging, setDragging] = React3__namespace.useState(false);
1332
+ const clamp = React3__namespace.useCallback(
1333
+ (value) => Math.min(maxWidth, Math.max(minWidth, value)),
1334
+ [minWidth, maxWidth]
1335
+ );
1336
+ React3__namespace.useEffect(() => {
1337
+ if (!dragging) return;
1338
+ const onMove = (event) => {
1339
+ event.preventDefault();
1340
+ setWidth(clamp(window.innerWidth - event.clientX));
1341
+ };
1342
+ const stop = () => setDragging(false);
1343
+ window.addEventListener("pointermove", onMove);
1344
+ window.addEventListener("pointerup", stop);
1345
+ window.addEventListener("pointercancel", stop);
1346
+ const previousSelect = document.body.style.userSelect;
1347
+ const previousCursor = document.body.style.cursor;
1348
+ document.body.style.userSelect = "none";
1349
+ document.body.style.cursor = "col-resize";
1350
+ return () => {
1351
+ window.removeEventListener("pointermove", onMove);
1352
+ window.removeEventListener("pointerup", stop);
1353
+ window.removeEventListener("pointercancel", stop);
1354
+ document.body.style.userSelect = previousSelect;
1355
+ document.body.style.cursor = previousCursor;
1356
+ };
1357
+ }, [dragging, clamp]);
1358
+ React3__namespace.useEffect(() => {
1359
+ if (dragging) return;
1360
+ onWidthChange?.(width);
1361
+ }, [dragging]);
1362
+ const nudge = (delta) => setWidth((current) => clamp(current + delta));
1363
+ return (
1364
+ // Sidebar tone always: the gutter and the divider sit in the shell's
1365
+ // chrome, next to the menu — painting them page-white put a bright strip
1366
+ // between the dark chrome and the rail, which read as a seam rather than
1367
+ // as space.
1368
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkH6OULCHF_cjs.cn("flex h-screen w-full overflow-hidden bg-sidebar", !frame && "md:bg-background"), children: [
1369
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children }),
1370
+ /* @__PURE__ */ jsxRuntime.jsxs(
1371
+ "div",
1372
+ {
1373
+ role: "separator",
1374
+ "aria-orientation": "vertical",
1375
+ "aria-label": resizeLabel,
1376
+ "aria-valuenow": width,
1377
+ "aria-valuemin": minWidth,
1378
+ "aria-valuemax": maxWidth,
1379
+ tabIndex: 0,
1380
+ onPointerDown: (event) => {
1381
+ event.preventDefault();
1382
+ setDragging(true);
1383
+ },
1384
+ onDoubleClick: () => setWidth(clamp(defaultWidth)),
1385
+ onKeyDown: (event) => {
1386
+ if (event.key === "ArrowLeft") {
1387
+ event.preventDefault();
1388
+ nudge(24);
1389
+ } else if (event.key === "ArrowRight") {
1390
+ event.preventDefault();
1391
+ nudge(-24);
1392
+ } else if (event.key === "Home") {
1393
+ event.preventDefault();
1394
+ setWidth(maxWidth);
1395
+ } else if (event.key === "End") {
1396
+ event.preventDefault();
1397
+ setWidth(minWidth);
1398
+ }
1399
+ },
1400
+ className: chunkH6OULCHF_cjs.cn(
1401
+ "group relative hidden w-1 shrink-0 cursor-col-resize focus-visible:outline-none",
1402
+ open && "md:block"
1403
+ ),
1404
+ children: [
1405
+ /* @__PURE__ */ jsxRuntime.jsx(
1406
+ "span",
1407
+ {
1408
+ className: chunkH6OULCHF_cjs.cn(
1409
+ "absolute inset-y-6 left-1/2 w-px -translate-x-1/2 rounded-full bg-transparent transition-colors",
1410
+ "group-hover:bg-primary/60 group-focus-visible:bg-primary",
1411
+ dragging && "bg-primary"
1412
+ )
1413
+ }
1414
+ ),
1415
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-y-0 -left-1.5 -right-1.5" })
1416
+ ]
1417
+ }
1418
+ ),
1419
+ /* @__PURE__ */ jsxRuntime.jsx(
1420
+ "aside",
1421
+ {
1422
+ style: { ["--fayz-rail-w"]: `${width}px` },
1423
+ className: chunkH6OULCHF_cjs.cn(
1424
+ "w-0 shrink-0 overflow-hidden",
1425
+ // Animating WIDTH is what makes the app glide back instead of
1426
+ // snapping; skipped mid-drag so the divider stays glued to the cursor.
1427
+ !dragging && "motion-safe:transition-[width] motion-safe:duration-200 motion-safe:ease-out",
1428
+ open && "md:w-[var(--fayz-rail-w)]",
1429
+ frame && "md:py-2 md:pr-2"
1430
+ ),
1431
+ children: rail
1432
+ }
1433
+ )
1434
+ ] })
1435
+ );
1436
+ }
1177
1437
  var NavTransitionContext = React3__namespace.createContext("slide");
1178
1438
  function NavTransitionProvider({ value, children }) {
1179
1439
  return /* @__PURE__ */ jsxRuntime.jsx(NavTransitionContext.Provider, { value, children });
@@ -1203,6 +1463,11 @@ function PageHeaderActions({ children }) {
1203
1463
  if (slot) return reactDom.createPortal(children, slot);
1204
1464
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4 flex items-center justify-end gap-2", children });
1205
1465
  }
1466
+ function PremiumBadge({ className }) {
1467
+ const t = core.useTranslation();
1468
+ const tip = t("upgrade.badgeTooltip");
1469
+ 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 }) });
1470
+ }
1206
1471
  var ModuleLayoutContext = React3__namespace.createContext("rail");
1207
1472
  function ModuleLayoutProvider({ variant, children }) {
1208
1473
  return /* @__PURE__ */ jsxRuntime.jsx(ModuleLayoutContext.Provider, { value: variant, children });
@@ -1229,11 +1494,12 @@ function NavItem2({ item }) {
1229
1494
  children: [
1230
1495
  Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4 shrink-0" }),
1231
1496
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-left truncate", children: item.label }),
1497
+ item.premium && /* @__PURE__ */ jsxRuntime.jsx(PremiumBadge, { className: "ml-1" }),
1232
1498
  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
1499
  ]
1234
1500
  }
1235
1501
  ),
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(
1502
+ 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
1503
  "button",
1238
1504
  {
1239
1505
  type: "button",
@@ -1242,7 +1508,10 @@ function NavItem2({ item }) {
1242
1508
  "flex items-center w-full rounded-md px-2.5 py-1 text-xs transition-colors",
1243
1509
  child.active ? "text-primary font-medium bg-primary/5" : "text-muted-foreground hover:text-foreground hover:bg-muted/50"
1244
1510
  ),
1245
- children: child.label
1511
+ children: [
1512
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-left truncate", children: child.label }),
1513
+ child.premium && /* @__PURE__ */ jsxRuntime.jsx(PremiumBadge, { className: "ml-1" })
1514
+ ]
1246
1515
  },
1247
1516
  child.id
1248
1517
  )) })
@@ -1286,6 +1555,7 @@ function MobileTabs({ nav }) {
1286
1555
  children: [
1287
1556
  Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-3 w-3" }),
1288
1557
  item.label,
1558
+ item.premium && /* @__PURE__ */ jsxRuntime.jsx(PremiumBadge, {}),
1289
1559
  hasChildren && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: chunkH6OULCHF_cjs.cn("h-2.5 w-2.5 transition-transform", isExpanded && "rotate-180") })
1290
1560
  ]
1291
1561
  },
@@ -1295,7 +1565,7 @@ function MobileTabs({ nav }) {
1295
1565
  expandedId && (() => {
1296
1566
  const item = nav.find((n) => n.id === expandedId);
1297
1567
  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(
1568
+ 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
1569
  "button",
1300
1570
  {
1301
1571
  type: "button",
@@ -1307,7 +1577,10 @@ function MobileTabs({ nav }) {
1307
1577
  "whitespace-nowrap rounded-full px-2.5 py-1 text-[11px] font-medium transition-colors shrink-0",
1308
1578
  child.active ? "bg-foreground/10 text-foreground" : "text-muted-foreground hover:text-foreground"
1309
1579
  ),
1310
- children: child.label
1580
+ children: [
1581
+ child.label,
1582
+ child.premium && /* @__PURE__ */ jsxRuntime.jsx(PremiumBadge, {})
1583
+ ]
1311
1584
  },
1312
1585
  child.id
1313
1586
  )) });
@@ -1399,7 +1672,8 @@ function ModuleHeader({ nav }) {
1399
1672
  ),
1400
1673
  children: [
1401
1674
  Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4" }),
1402
- item.label
1675
+ item.label,
1676
+ item.premium && /* @__PURE__ */ jsxRuntime.jsx(PremiumBadge, {})
1403
1677
  ]
1404
1678
  },
1405
1679
  item.id
@@ -1545,5 +1819,5 @@ exports.useModuleHeaderActionsSlot = useModuleHeaderActionsSlot;
1545
1819
  exports.useModuleHeaderSlot = useModuleHeaderSlot;
1546
1820
  exports.useModuleLayout = useModuleLayout;
1547
1821
  exports.useNavTransition = useNavTransition;
1548
- //# sourceMappingURL=chunk-XAOGMWLC.cjs.map
1549
- //# sourceMappingURL=chunk-XAOGMWLC.cjs.map
1822
+ //# sourceMappingURL=chunk-7ZQQZD4Q.cjs.map
1823
+ //# sourceMappingURL=chunk-7ZQQZD4Q.cjs.map