@fayz-ai/ui 0.8.4 → 0.8.5

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 (78) hide show
  1. package/dist/ChartWidgetInner-GDE5PBTR.js +46 -0
  2. package/dist/ChartWidgetInner-GDE5PBTR.js.map +1 -0
  3. package/dist/{chunk-VVQ45ZDZ.js → chunk-KV3MHB6N.js} +85 -179
  4. package/dist/chunk-KV3MHB6N.js.map +1 -0
  5. package/dist/{chunk-M34ACV5E.js → chunk-OUPJDGKE.js} +6 -41
  6. package/dist/chunk-OUPJDGKE.js.map +1 -0
  7. package/dist/chunk-PVIB724L.js +161 -0
  8. package/dist/chunk-PVIB724L.js.map +1 -0
  9. package/dist/{chunk-DYMBFHD7.js → chunk-VDAYIQX4.js} +202 -3
  10. package/dist/chunk-VDAYIQX4.js.map +1 -0
  11. package/dist/{chunk-R4LPSXTT.js → chunk-YLQGUJAQ.js} +18 -6
  12. package/dist/chunk-YLQGUJAQ.js.map +1 -0
  13. package/dist/dashboard/ChartWidget.d.ts.map +1 -1
  14. package/dist/dashboard/ChartWidgetInner.d.ts +11 -0
  15. package/dist/dashboard/ChartWidgetInner.d.ts.map +1 -0
  16. package/dist/dashboard/index.js +2 -1
  17. package/dist/icons.d.ts +8 -0
  18. package/dist/icons.d.ts.map +1 -0
  19. package/dist/icons.js +3 -0
  20. package/dist/icons.js.map +1 -0
  21. package/dist/index.d.ts +1 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +5 -5
  24. package/dist/layout/Sidebar.d.ts +1 -2
  25. package/dist/layout/Sidebar.d.ts.map +1 -1
  26. package/dist/layout/index.js +2 -1
  27. package/dist/preset.cjs +201 -11
  28. package/dist/preset.cjs.map +1 -1
  29. package/dist/preset.js +201 -1
  30. package/dist/preset.js.map +1 -1
  31. package/dist/primitives/date-picker.d.ts +7 -1
  32. package/dist/primitives/date-picker.d.ts.map +1 -1
  33. package/dist/primitives/index.js +1 -1
  34. package/dist/tailwind.cjs +199 -2
  35. package/dist/tailwind.cjs.map +1 -1
  36. package/dist/tailwind.js +198 -1
  37. package/dist/tailwind.js.map +1 -1
  38. package/dist/theme/index.js +1 -2
  39. package/package.json +24 -22
  40. package/src/dashboard/ChartWidget.tsx +8 -65
  41. package/src/dashboard/ChartWidgetInner.tsx +83 -0
  42. package/src/dashboard/icon.ts +2 -2
  43. package/src/icons.ts +66 -0
  44. package/src/index.ts +4 -0
  45. package/src/layout/Sidebar.tsx +4 -110
  46. package/src/primitives/date-picker.tsx +30 -4
  47. package/dist/chunk-2P7T6QQK.cjs +0 -206
  48. package/dist/chunk-2P7T6QQK.cjs.map +0 -1
  49. package/dist/chunk-7ZQQZD4Q.cjs +0 -1823
  50. package/dist/chunk-7ZQQZD4Q.cjs.map +0 -1
  51. package/dist/chunk-B3BTZDTA.cjs +0 -1701
  52. package/dist/chunk-B3BTZDTA.cjs.map +0 -1
  53. package/dist/chunk-DYMBFHD7.js.map +0 -1
  54. package/dist/chunk-H6OULCHF.cjs +0 -81
  55. package/dist/chunk-H6OULCHF.cjs.map +0 -1
  56. package/dist/chunk-IWBXYV4U.js +0 -203
  57. package/dist/chunk-IWBXYV4U.js.map +0 -1
  58. package/dist/chunk-M34ACV5E.js.map +0 -1
  59. package/dist/chunk-MUGRP5DD.cjs +0 -701
  60. package/dist/chunk-MUGRP5DD.cjs.map +0 -1
  61. package/dist/chunk-NZV47HWO.cjs +0 -380
  62. package/dist/chunk-NZV47HWO.cjs.map +0 -1
  63. package/dist/chunk-OW73RZOU.cjs +0 -313
  64. package/dist/chunk-OW73RZOU.cjs.map +0 -1
  65. package/dist/chunk-R4LPSXTT.js.map +0 -1
  66. package/dist/chunk-R4SQ2GVD.cjs +0 -475
  67. package/dist/chunk-R4SQ2GVD.cjs.map +0 -1
  68. package/dist/chunk-VVQ45ZDZ.js.map +0 -1
  69. package/dist/dashboard/index.cjs +0 -106
  70. package/dist/dashboard/index.cjs.map +0 -1
  71. package/dist/index.cjs +0 -650
  72. package/dist/index.cjs.map +0 -1
  73. package/dist/layout/index.cjs +0 -98
  74. package/dist/layout/index.cjs.map +0 -1
  75. package/dist/primitives/index.cjs +0 -363
  76. package/dist/primitives/index.cjs.map +0 -1
  77. package/dist/theme/index.cjs +0 -41
  78. package/dist/theme/index.cjs.map +0 -1
@@ -1,1823 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkOW73RZOU_cjs = require('./chunk-OW73RZOU.cjs');
4
- var chunkH6OULCHF_cjs = require('./chunk-H6OULCHF.cjs');
5
- var React3 = require('react');
6
- var lucideReact = require('lucide-react');
7
- var Tooltip = require('@radix-ui/react-tooltip');
8
- var zustand = require('zustand');
9
- var jsxRuntime = require('react/jsx-runtime');
10
- var Popover = require('@radix-ui/react-popover');
11
- var reactDom = require('react-dom');
12
- var core = require('@fayz-ai/core');
13
-
14
- function _interopNamespace(e) {
15
- if (e && e.__esModule) return e;
16
- var n = Object.create(null);
17
- if (e) {
18
- Object.keys(e).forEach(function (k) {
19
- if (k !== 'default') {
20
- var d = Object.getOwnPropertyDescriptor(e, k);
21
- Object.defineProperty(n, k, d.get ? d : {
22
- enumerable: true,
23
- get: function () { return e[k]; }
24
- });
25
- }
26
- });
27
- }
28
- n.default = e;
29
- return Object.freeze(n);
30
- }
31
-
32
- var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
33
- var Tooltip__namespace = /*#__PURE__*/_interopNamespace(Tooltip);
34
- var Popover__namespace = /*#__PURE__*/_interopNamespace(Popover);
35
-
36
- var useLayoutStore = zustand.create((set) => ({
37
- sidebarOpen: true,
38
- sidebarCollapsed: false,
39
- mobileDrawerOpen: false,
40
- commandPaletteOpen: false,
41
- toggleSidebar: () => set((state) => ({ sidebarOpen: !state.sidebarOpen })),
42
- setSidebarCollapsed: (collapsed) => set({ sidebarCollapsed: collapsed }),
43
- toggleMobileDrawer: () => set((state) => ({ mobileDrawerOpen: !state.mobileDrawerOpen })),
44
- setCommandPaletteOpen: (open) => set({ commandPaletteOpen: open })
45
- }));
46
- var ICON_MAP = {
47
- Home: lucideReact.Home,
48
- Users: lucideReact.Users,
49
- Settings: lucideReact.Settings,
50
- CreditCard: lucideReact.CreditCard,
51
- Bell: lucideReact.Bell,
52
- Calendar: lucideReact.Calendar,
53
- CalendarClock: lucideReact.CalendarClock,
54
- Package: lucideReact.Package,
55
- Activity: lucideReact.Activity,
56
- BarChart3: lucideReact.BarChart3,
57
- FileText: lucideReact.FileText,
58
- Mail: lucideReact.Mail,
59
- DollarSign: lucideReact.DollarSign,
60
- Megaphone: lucideReact.Megaphone,
61
- ShoppingCart: lucideReact.ShoppingCart,
62
- Target: lucideReact.Target,
63
- Wrench: lucideReact.Wrench,
64
- Truck: lucideReact.Truck,
65
- Receipt: lucideReact.Receipt,
66
- ShoppingBag: lucideReact.ShoppingBag,
67
- ClipboardList: lucideReact.ClipboardList,
68
- ListChecks: lucideReact.ListChecks,
69
- Briefcase: lucideReact.Briefcase,
70
- UserCog: lucideReact.UserCog,
71
- BookOpen: lucideReact.BookOpen,
72
- BookOpenCheck: lucideReact.BookOpenCheck,
73
- MessageCircle: lucideReact.MessageCircle,
74
- Globe: lucideReact.Globe,
75
- Percent: lucideReact.Percent,
76
- Tag: lucideReact.Tag,
77
- Tags: lucideReact.Tags,
78
- Camera: lucideReact.Camera,
79
- UtensilsCrossed: lucideReact.UtensilsCrossed,
80
- MapPin: lucideReact.MapPin,
81
- Map: lucideReact.Map,
82
- Handshake: lucideReact.Handshake,
83
- Contact: lucideReact.Contact,
84
- Building2: lucideReact.Building2,
85
- Filter: lucideReact.Filter,
86
- Plus: lucideReact.Plus,
87
- List: lucideReact.List,
88
- ListPlus: lucideReact.ListPlus,
89
- Search: lucideReact.Search,
90
- Shield: lucideReact.Shield,
91
- Ban: lucideReact.Ban,
92
- Clock: lucideReact.Clock,
93
- Dog: lucideReact.Dog,
94
- Cat: lucideReact.Cat,
95
- PawPrint: lucideReact.PawPrint,
96
- Heart: lucideReact.Heart,
97
- FolderOpen: lucideReact.FolderOpen,
98
- LayoutTemplate: lucideReact.LayoutTemplate,
99
- LeafyGreen: lucideReact.LeafyGreen,
100
- Apple: lucideReact.Apple,
101
- Egg: lucideReact.Egg,
102
- Wheat: lucideReact.Wheat,
103
- PartyPopper: lucideReact.PartyPopper,
104
- Radio: lucideReact.Radio,
105
- CalendarDays: lucideReact.CalendarDays,
106
- CalendarCheck2: lucideReact.CalendarCheck2,
107
- CalendarX: lucideReact.CalendarX,
108
- BadgeDollarSign: lucideReact.BadgeDollarSign,
109
- Banknote: lucideReact.Banknote,
110
- Landmark: lucideReact.Landmark,
111
- CircleDollarSign: lucideReact.CircleDollarSign,
112
- Layers: lucideReact.Layers,
113
- Music: lucideReact.Music,
114
- Eye: lucideReact.Eye,
115
- ListMusic: lucideReact.ListMusic,
116
- Disc3: lucideReact.Disc3,
117
- UsersRound: lucideReact.UsersRound,
118
- Mic: lucideReact.Mic,
119
- Zap: lucideReact.Zap,
120
- Award: lucideReact.Award,
121
- LayoutDashboard: lucideReact.LayoutDashboard,
122
- MessageSquare: lucideReact.MessageSquare,
123
- Inbox: lucideReact.Inbox,
124
- Star: lucideReact.Star,
125
- TrendingUp: lucideReact.TrendingUp,
126
- UserCheck: lucideReact.UserCheck,
127
- UserPlus: lucideReact.UserPlus,
128
- UserX: lucideReact.UserX,
129
- Workflow: lucideReact.Workflow,
130
- Boxes: lucideReact.Boxes,
131
- Clock3: lucideReact.Clock3,
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
140
- };
141
- var RAIL_PUSH_MS = 260;
142
- var useIsomorphicLayoutEffect = typeof window !== "undefined" ? React3__namespace.useLayoutEffect : React3__namespace.useEffect;
143
- function getIcon(name) {
144
- return ICON_MAP[name] ?? lucideReact.Home;
145
- }
146
- function NavItem({
147
- item,
148
- collapsed,
149
- isActive,
150
- onNavigate
151
- }) {
152
- const Icon = getIcon(item.icon);
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"
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 });
170
- if (collapsed) {
171
- return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip__namespace.Root, { delayDuration: 0, children: [
172
- /* @__PURE__ */ jsxRuntime.jsx(Tooltip__namespace.Trigger, { asChild: true, children: content }),
173
- /* @__PURE__ */ jsxRuntime.jsx(Tooltip__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
174
- Tooltip__namespace.Content,
175
- {
176
- side: "right",
177
- sideOffset: 8,
178
- className: "fayz-glass-surface z-50 rounded-md bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md",
179
- children: [
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 }),
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 }),
183
- /* @__PURE__ */ jsxRuntime.jsx(Tooltip__namespace.Arrow, { className: "fill-popover" })
184
- ]
185
- }
186
- ) })
187
- ] });
188
- }
189
- return content;
190
- }
191
- function routeMatchScore(route, path) {
192
- if (path === route) return route.length + 1;
193
- if (route !== "/" && path.startsWith(route + "/")) return route.length;
194
- return -1;
195
- }
196
- function resolveActiveRoute(navigation, path) {
197
- let best = null;
198
- let bestScore = 0;
199
- const consider = (route) => {
200
- if (!route) return;
201
- const score = routeMatchScore(route, path);
202
- if (score > bestScore) {
203
- bestScore = score;
204
- best = route;
205
- }
206
- };
207
- for (const item of navigation) {
208
- consider(item.route);
209
- for (const child of item.children ?? []) consider(child.route);
210
- }
211
- return best;
212
- }
213
- function NavGroup({
214
- item,
215
- collapsed,
216
- activeRoute,
217
- onNavigate
218
- }) {
219
- const isChildActive = item.children?.some((c) => c.route === activeRoute);
220
- const [open, setOpen] = React3__namespace.useState(() => isChildActive ?? false);
221
- const Icon = getIcon(item.icon);
222
- if (collapsed) {
223
- return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip__namespace.Root, { delayDuration: 0, children: [
224
- /* @__PURE__ */ jsxRuntime.jsx(Tooltip__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
225
- "button",
226
- {
227
- onClick: () => onNavigate(item.route),
228
- className: chunkH6OULCHF_cjs.cn(
229
- "flex w-full items-center justify-center rounded-md px-2 py-2 text-sm font-medium transition-colors",
230
- "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
231
- isChildActive ? "bg-sidebar-accent text-sidebar-accent-foreground" : "text-sidebar-muted"
232
- ),
233
- children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4 shrink-0" })
234
- }
235
- ) }),
236
- /* @__PURE__ */ jsxRuntime.jsx(Tooltip__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(Tooltip__namespace.Content, { side: "right", sideOffset: 8, className: "fayz-glass-surface z-50 rounded-md bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md", children: [
237
- item.label,
238
- /* @__PURE__ */ jsxRuntime.jsx(Tooltip__namespace.Arrow, { className: "fill-popover" })
239
- ] }) })
240
- ] });
241
- }
242
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
243
- /* @__PURE__ */ jsxRuntime.jsxs(
244
- "button",
245
- {
246
- onClick: () => setOpen(!open),
247
- className: chunkH6OULCHF_cjs.cn(
248
- "flex w-full items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors",
249
- "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
250
- isChildActive ? "text-sidebar-accent-foreground" : "text-sidebar-muted"
251
- ),
252
- children: [
253
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4 shrink-0" }),
254
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate text-left", children: item.label }),
255
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: chunkH6OULCHF_cjs.cn("h-3.5 w-3.5 shrink-0 transition-transform", open && "rotate-180") })
256
- ]
257
- }
258
- ),
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) => {
260
- const ChildIcon = getIcon(child.icon);
261
- const isActive = child.route === activeRoute;
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"
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);
274
- }) })
275
- ] });
276
- }
277
- function Sidebar({
278
- navigation,
279
- logo,
280
- collapsed,
281
- onToggle,
282
- onNavigate,
283
- currentPath: currentPathProp = "/",
284
- user: _user,
285
- orgSwitcher,
286
- topContent,
287
- footerContent,
288
- borderless,
289
- userMenuSlot,
290
- notificationSlot,
291
- unreadCount = 0,
292
- sectionLabels,
293
- navKey,
294
- navDirection = "forward"
295
- }) {
296
- const currentPath = currentPathProp;
297
- const setCommandPaletteOpen = useLayoutStore((s) => s.setCommandPaletteOpen);
298
- const activeRoute = resolveActiveRoute(navigation, currentPath);
299
- const mainItems = navigation.filter((item) => item.section === "main");
300
- const secondaryItems = navigation.filter((item) => item.section === "secondary");
301
- const settingsItems = navigation.filter((item) => item.section === "settings");
302
- const handleNavigate = (route) => {
303
- onNavigate?.(route);
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
- }, []);
346
- return /* @__PURE__ */ jsxRuntime.jsx(Tooltip__namespace.Provider, { children: /* @__PURE__ */ jsxRuntime.jsxs(
347
- "aside",
348
- {
349
- "data-print": "hide",
350
- className: chunkH6OULCHF_cjs.cn(
351
- "flex h-full flex-col bg-sidebar text-sidebar-foreground transition-all duration-200",
352
- !borderless && "border-r border-sidebar-border",
353
- collapsed ? "w-16" : "w-64"
354
- ),
355
- children: [
356
- /* @__PURE__ */ jsxRuntime.jsxs(
357
- "div",
358
- {
359
- className: chunkH6OULCHF_cjs.cn(
360
- "flex h-14 items-center justify-between px-4",
361
- !borderless && "border-b border-sidebar-border",
362
- collapsed && "justify-center px-2"
363
- ),
364
- children: [
365
- !collapsed && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
366
- logo ?? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg font-bold", children: "App" }),
367
- /* @__PURE__ */ jsxRuntime.jsx(
368
- "button",
369
- {
370
- onClick: onToggle,
371
- className: "ml-auto rounded-md p-1.5 text-sidebar-muted transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
372
- "aria-label": "Collapse sidebar",
373
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelLeftClose, { className: "h-4 w-4" })
374
- }
375
- )
376
- ] }),
377
- collapsed && /* @__PURE__ */ jsxRuntime.jsx(
378
- "button",
379
- {
380
- onClick: onToggle,
381
- className: "rounded-md p-1.5 text-sidebar-muted transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
382
- "aria-label": "Expand sidebar",
383
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelLeft, { className: "h-4 w-4" })
384
- }
385
- )
386
- ]
387
- }
388
- ),
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
- ),
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(
425
- NavItem,
426
- {
427
- item,
428
- collapsed,
429
- isActive: item.route === activeRoute,
430
- onNavigate: handleNavigate
431
- },
432
- item.id
433
- )) }),
434
- footerContent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkH6OULCHF_cjs.cn("p-2", !borderless && "border-t border-sidebar-border"), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: footerContent }) }),
435
- orgSwitcher && React3__namespace.isValidElement(orgSwitcher) ? React3__namespace.cloneElement(orgSwitcher, { collapsed }) : orgSwitcher,
436
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkH6OULCHF_cjs.cn("p-2", !borderless && "border-t border-sidebar-border"), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkH6OULCHF_cjs.cn(
437
- "flex items-center rounded-md",
438
- collapsed ? "flex-col gap-1" : "gap-1 px-1"
439
- ), children: [
440
- userMenuSlot,
441
- !collapsed && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1" }),
442
- /* @__PURE__ */ jsxRuntime.jsx(
443
- "button",
444
- {
445
- onClick: () => setCommandPaletteOpen(true),
446
- className: "inline-flex shrink-0 items-center justify-center rounded-md p-2 text-sidebar-muted transition-colors hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground",
447
- "aria-label": "Search",
448
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "h-4 w-4" })
449
- }
450
- ),
451
- notificationSlot ?? /* @__PURE__ */ jsxRuntime.jsxs(
452
- "button",
453
- {
454
- className: "relative inline-flex shrink-0 items-center justify-center rounded-md p-2 text-sidebar-muted transition-colors hover:bg-sidebar-accent/50 hover:text-sidebar-accent-foreground",
455
- "aria-label": unreadCount > 0 ? `${unreadCount} unread notifications` : "Notifications",
456
- children: [
457
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bell, { className: "h-4 w-4" }),
458
- unreadCount > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute right-1 top-1 h-2 w-2 rounded-full bg-destructive" })
459
- ]
460
- }
461
- )
462
- ] }) })
463
- ]
464
- }
465
- ) });
466
- }
467
- function TopbarUserMenu({
468
- user,
469
- userPlan,
470
- billingLabel = "Subscription",
471
- onSignOut,
472
- onProfile,
473
- onSettings,
474
- onBilling,
475
- userMenuExtras
476
- }) {
477
- const [open, setOpen] = React3__namespace.useState(false);
478
- if (!user) return null;
479
- const initial = (user.fullName?.trim()?.[0] ?? user.email?.[0] ?? "?").toUpperCase();
480
- const item = (label, onClick, Icon) => onClick ? /* @__PURE__ */ jsxRuntime.jsxs(
481
- "button",
482
- {
483
- onClick: () => {
484
- setOpen(false);
485
- onClick();
486
- },
487
- 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",
488
- children: [
489
- Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4 text-muted-foreground" }),
490
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: label })
491
- ]
492
- },
493
- label
494
- ) : null;
495
- return /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open, onOpenChange: setOpen, children: [
496
- /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
497
- "button",
498
- {
499
- "aria-label": "User menu",
500
- className: "ml-1 flex h-9 w-9 items-center justify-center overflow-hidden rounded-full bg-primary text-xs font-semibold text-primary-foreground ring-2 ring-transparent transition hover:ring-sidebar-border",
501
- children: user.avatarUrl ? (
502
- // eslint-disable-next-line @next/next/no-img-element
503
- /* @__PURE__ */ jsxRuntime.jsx("img", { src: user.avatarUrl, alt: "", className: "h-full w-full object-cover" })
504
- ) : initial
505
- }
506
- ) }),
507
- /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
508
- Popover__namespace.Content,
509
- {
510
- align: "end",
511
- sideOffset: 8,
512
- className: "fayz-glass-surface z-50 min-w-[220px] rounded-xl border border-border bg-popover p-1.5 shadow-lg animate-in fade-in-0 zoom-in-95",
513
- children: [
514
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-border px-3 py-2", children: [
515
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-sm font-medium text-foreground", children: user.fullName || user.email }),
516
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-xs text-muted-foreground", children: user.email })
517
- ] }),
518
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-1 space-y-0.5", children: [
519
- item("Perfil", onProfile, lucideReact.UserCog),
520
- item("Configura\xE7\xF5es", onSettings, lucideReact.Settings),
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
- ),
546
- userMenuExtras?.map((e) => item(e.label, e.onClick)),
547
- onSignOut && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
548
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-1 border-t border-border" }),
549
- item("Sair", onSignOut, lucideReact.LogOut)
550
- ] })
551
- ] })
552
- ]
553
- }
554
- ) })
555
- ] });
556
- }
557
- var ICON_MAP2 = {
558
- Home: lucideReact.Home,
559
- Users: lucideReact.Users,
560
- Settings: lucideReact.Settings,
561
- CreditCard: lucideReact.CreditCard,
562
- Bell: lucideReact.Bell,
563
- Calendar: lucideReact.Calendar,
564
- CalendarClock: lucideReact.CalendarClock,
565
- Package: lucideReact.Package,
566
- Activity: lucideReact.Activity,
567
- BarChart3: lucideReact.BarChart3,
568
- FileText: lucideReact.FileText,
569
- Mail: lucideReact.Mail,
570
- DollarSign: lucideReact.DollarSign,
571
- Megaphone: lucideReact.Megaphone,
572
- ShoppingCart: lucideReact.ShoppingCart,
573
- ShoppingBag: lucideReact.ShoppingBag,
574
- Target: lucideReact.Target,
575
- Wrench: lucideReact.Wrench,
576
- ClipboardList: lucideReact.ClipboardList,
577
- ClipboardCheck: lucideReact.ClipboardCheck,
578
- Briefcase: lucideReact.Briefcase,
579
- UserCog: lucideReact.UserCog,
580
- BookOpen: lucideReact.BookOpen,
581
- MessageCircle: lucideReact.MessageCircle,
582
- Globe: lucideReact.Globe,
583
- BookOpenCheck: lucideReact.BookOpenCheck,
584
- Percent: lucideReact.Percent,
585
- Tag: lucideReact.Tag,
586
- Tags: lucideReact.Tags,
587
- Camera: lucideReact.Camera,
588
- UtensilsCrossed: lucideReact.UtensilsCrossed,
589
- Search: lucideReact.Search,
590
- MapPin: lucideReact.MapPin,
591
- Handshake: lucideReact.Handshake,
592
- Contact: lucideReact.Contact,
593
- Building2: lucideReact.Building2,
594
- ChevronDown: lucideReact.ChevronDown,
595
- Filter: lucideReact.Filter,
596
- Plus: lucideReact.Plus,
597
- Shield: lucideReact.Shield,
598
- List: lucideReact.List,
599
- ListChecks: lucideReact.ListChecks,
600
- FolderOpen: lucideReact.FolderOpen,
601
- Dog: lucideReact.Dog,
602
- Cat: lucideReact.Cat,
603
- PawPrint: lucideReact.PawPrint,
604
- Heart: lucideReact.Heart,
605
- LayoutTemplate: lucideReact.LayoutTemplate,
606
- LeafyGreen: lucideReact.LeafyGreen,
607
- Apple: lucideReact.Apple,
608
- Egg: lucideReact.Egg,
609
- Wheat: lucideReact.Wheat,
610
- ArrowDownCircle: lucideReact.ArrowDownCircle,
611
- ArrowUpCircle: lucideReact.ArrowUpCircle,
612
- ArrowLeftRight: lucideReact.ArrowLeftRight,
613
- Plug: lucideReact.Plug,
614
- SlidersHorizontal: lucideReact.SlidersHorizontal,
615
- TableProperties: lucideReact.TableProperties,
616
- Landmark: lucideReact.Landmark,
617
- Receipt: lucideReact.Receipt,
618
- TrendingUp: lucideReact.TrendingUp,
619
- CircleDollarSign: lucideReact.CircleDollarSign,
620
- Clock: lucideReact.Clock,
621
- AlertTriangle: lucideReact.AlertTriangle,
622
- Sparkles: lucideReact.Sparkles,
623
- Wallet: lucideReact.Wallet,
624
- Warehouse: lucideReact.Warehouse,
625
- Ruler: lucideReact.Ruler,
626
- ArrowUpRight: lucideReact.ArrowUpRight,
627
- ArrowDownRight: lucideReact.ArrowDownRight,
628
- UserPlus: lucideReact.UserPlus,
629
- UserX: lucideReact.UserX,
630
- TreePalm: lucideReact.TreePalm,
631
- Boxes: lucideReact.Boxes,
632
- Box: lucideReact.Box,
633
- FileCheck2: lucideReact.FileCheck2,
634
- PartyPopper: lucideReact.PartyPopper,
635
- Radio: lucideReact.Radio,
636
- CalendarDays: lucideReact.CalendarDays,
637
- BadgeDollarSign: lucideReact.BadgeDollarSign,
638
- Banknote: lucideReact.Banknote,
639
- Layers: lucideReact.Layers,
640
- Music: lucideReact.Music,
641
- Eye: lucideReact.Eye,
642
- ListMusic: lucideReact.ListMusic,
643
- Disc3: lucideReact.Disc3,
644
- UsersRound: lucideReact.UsersRound,
645
- Mic: lucideReact.Mic,
646
- CalendarCheck2: lucideReact.CalendarCheck2,
647
- CalendarX: lucideReact.CalendarX,
648
- ListPlus: lucideReact.ListPlus,
649
- Map: lucideReact.Map,
650
- Ban: lucideReact.Ban,
651
- Clock3: lucideReact.Clock3,
652
- Inbox: lucideReact.Inbox,
653
- UserCheck: lucideReact.UserCheck,
654
- Star: lucideReact.Star,
655
- Zap: lucideReact.Zap,
656
- Clapperboard: lucideReact.Clapperboard,
657
- Newspaper: lucideReact.Newspaper,
658
- GraduationCap: lucideReact.GraduationCap,
659
- Repeat: lucideReact.Repeat
660
- };
661
- function getIcon2(name) {
662
- return ICON_MAP2[name] ?? lucideReact.Home;
663
- }
664
- function NavDropdown({ item, currentPath, onNavigate }) {
665
- const [open, setOpen] = React3__namespace.useState(false);
666
- const Icon = getIcon2(item.icon);
667
- const isChildActive = item.children?.some(
668
- (child) => currentPath === child.route || currentPath.startsWith(child.route + "/")
669
- );
670
- return /* @__PURE__ */ jsxRuntime.jsxs(Popover__namespace.Root, { open, onOpenChange: setOpen, children: [
671
- /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Trigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
672
- "button",
673
- {
674
- "data-nav-active": isChildActive || void 0,
675
- className: chunkH6OULCHF_cjs.cn(
676
- "flex items-center gap-1.5 whitespace-nowrap border-b-2 px-3 py-2 text-sm transition-colors",
677
- isChildActive ? "border-sidebar-accent-foreground font-semibold text-sidebar-foreground" : "border-transparent text-sidebar-muted hover:text-sidebar-foreground"
678
- ),
679
- children: [
680
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4" }),
681
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: item.label }),
682
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: chunkH6OULCHF_cjs.cn("h-3 w-3 transition-transform", open && "rotate-180") })
683
- ]
684
- }
685
- ) }),
686
- /* @__PURE__ */ jsxRuntime.jsx(Popover__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
687
- Popover__namespace.Content,
688
- {
689
- align: "start",
690
- sideOffset: 4,
691
- className: "fayz-glass-surface z-50 min-w-[200px] rounded-xl border border-border bg-popover p-1.5 shadow-lg animate-in fade-in-0 zoom-in-95",
692
- children: item.children?.map((child) => {
693
- const ChildIcon = getIcon2(child.icon);
694
- const isActive = currentPath === child.route || currentPath.startsWith(child.route + "/");
695
- return /* @__PURE__ */ jsxRuntime.jsxs(
696
- "button",
697
- {
698
- onClick: () => {
699
- onNavigate(child.route);
700
- setOpen(false);
701
- },
702
- className: chunkH6OULCHF_cjs.cn(
703
- "flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-sm transition-colors",
704
- isActive ? "bg-muted font-medium text-foreground" : "text-popover-foreground hover:bg-muted/70"
705
- ),
706
- children: [
707
- /* @__PURE__ */ jsxRuntime.jsx(ChildIcon, { className: "h-4 w-4 text-muted-foreground" }),
708
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: child.label })
709
- ]
710
- },
711
- child.id
712
- );
713
- })
714
- }
715
- ) })
716
- ] });
717
- }
718
- function Topbar({
719
- navigation,
720
- logo,
721
- user,
722
- onMenuClick,
723
- orgSwitcher,
724
- leftContent,
725
- rightContent,
726
- currentPath = "/",
727
- onNavigate,
728
- searchPlaceholder = "Search...",
729
- onSignOut,
730
- onProfile,
731
- onSettings,
732
- onBilling,
733
- userPlan,
734
- billingLabel,
735
- userMenuExtras
736
- }) {
737
- const setCommandPaletteOpen = useLayoutStore((s) => s.setCommandPaletteOpen);
738
- const mainNav = navigation.filter((item) => item.section === "main");
739
- const secondaryNav = navigation.filter((item) => item.section === "secondary");
740
- const allNav = [...mainNav, ...secondaryNav];
741
- const handleNavigate = (route) => {
742
- onNavigate?.(route);
743
- };
744
- return /* @__PURE__ */ jsxRuntime.jsxs("header", { "data-print": "hide", className: "sticky top-0 z-50 w-full shrink-0", children: [
745
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-sidebar-border bg-sidebar text-sidebar-foreground", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-14 w-full items-center justify-between px-4 md:px-6", children: [
746
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
747
- onMenuClick && /* @__PURE__ */ jsxRuntime.jsx(
748
- "button",
749
- {
750
- onClick: onMenuClick,
751
- className: "inline-flex items-center justify-center rounded-md p-2 text-sidebar-foreground/70 hover:bg-sidebar/30 hover:text-sidebar-foreground md:hidden",
752
- "aria-label": "Open menu",
753
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "h-5 w-5" })
754
- }
755
- ),
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 })
758
- ] }),
759
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-8 hidden max-w-sm flex-1 md:flex", children: /* @__PURE__ */ jsxRuntime.jsxs(
760
- "button",
761
- {
762
- onClick: () => setCommandPaletteOpen(true),
763
- className: "relative flex h-8 w-full items-center rounded-md border border-sidebar-border bg-sidebar-accent px-3 pl-8 text-sm text-sidebar-muted shadow-sm transition-colors hover:border-sidebar-foreground/25 hover:bg-sidebar-foreground/10 hover:text-sidebar-foreground",
764
- children: [
765
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-sidebar-muted" }),
766
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", children: searchPlaceholder }),
767
- /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: "ml-auto hidden rounded border border-sidebar-border bg-sidebar-accent px-1.5 py-0.5 text-[10px] font-medium text-sidebar-muted sm:inline-block", children: "\u2318K" })
768
- ]
769
- }
770
- ) }),
771
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
772
- leftContent,
773
- rightContent,
774
- /* @__PURE__ */ jsxRuntime.jsx(
775
- TopbarUserMenu,
776
- {
777
- user,
778
- userPlan,
779
- billingLabel,
780
- onSignOut,
781
- onProfile,
782
- onSettings,
783
- onBilling,
784
- userMenuExtras
785
- }
786
- )
787
- ] })
788
- ] }) }),
789
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden md:block bg-sidebar", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-11 w-full items-center px-4 md:px-6", children: /* @__PURE__ */ jsxRuntime.jsx("nav", { ref: (el) => {
790
- if (!el) return;
791
- const active = el.querySelector('[data-nav-active="true"]');
792
- if (active) {
793
- const left = active.offsetLeft - el.offsetWidth / 2 + active.offsetWidth / 2;
794
- el.scrollTo({ left: Math.max(0, left), behavior: "smooth" });
795
- }
796
- }, className: "flex items-center gap-0.5 overflow-x-auto scrollbar-none", children: allNav.map((item) => {
797
- if (item.children && item.children.length > 0) {
798
- return /* @__PURE__ */ jsxRuntime.jsx(
799
- NavDropdown,
800
- {
801
- item,
802
- currentPath,
803
- onNavigate: handleNavigate
804
- },
805
- item.id
806
- );
807
- }
808
- const Icon = getIcon2(item.icon);
809
- const isActive = item.route === "/" ? currentPath === "/" : currentPath === item.route || currentPath.startsWith(item.route + "/");
810
- return /* @__PURE__ */ jsxRuntime.jsxs(
811
- "button",
812
- {
813
- "data-nav-active": isActive || void 0,
814
- onClick: () => handleNavigate(item.route),
815
- className: chunkH6OULCHF_cjs.cn(
816
- "flex items-center gap-1.5 whitespace-nowrap border-b-2 px-3 py-2 text-sm transition-colors",
817
- isActive ? "border-primary font-semibold text-sidebar-foreground" : "border-transparent text-sidebar-muted hover:text-sidebar-foreground"
818
- ),
819
- children: [
820
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4" }),
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 }),
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 })
824
- ]
825
- },
826
- item.id
827
- );
828
- }) }) }) })
829
- ] });
830
- }
831
- var ModuleHeaderSlotContext = React3__namespace.createContext(null);
832
- function useModuleHeaderSlot() {
833
- return React3__namespace.useContext(ModuleHeaderSlotContext);
834
- }
835
- var ModuleHeaderActionsSlotContext = React3__namespace.createContext(null);
836
- function useModuleHeaderActionsSlot() {
837
- return React3__namespace.useContext(ModuleHeaderActionsSlotContext);
838
- }
839
- function SidebarLayout({
840
- navigation = [],
841
- logo,
842
- user,
843
- children,
844
- onNavigate,
845
- onSignOut,
846
- onProfile,
847
- onSettings,
848
- onBilling,
849
- userMenuExtras: _userMenuExtras,
850
- orgSwitcher,
851
- sidebarTopContent,
852
- sidebarFooterContent,
853
- frame,
854
- currentPath,
855
- pageTitle,
856
- topbarStart,
857
- topbarEnd,
858
- userMenuSlot,
859
- notificationSlot,
860
- unreadCount = 0,
861
- hasBottomNav = false,
862
- mobileHeader = "minimal",
863
- sidebarSectionLabels,
864
- sidebarNavKey,
865
- sidebarNavDirection
866
- }) {
867
- const sidebarCollapsed = useLayoutStore((s) => s.sidebarCollapsed);
868
- const setSidebarCollapsed = useLayoutStore((s) => s.setSidebarCollapsed);
869
- const [mobileMenuOpen, setMobileMenuOpen] = React3__namespace.useState(false);
870
- const [headerSlot, setHeaderSlot] = React3__namespace.useState(null);
871
- const [actionsSlot, setActionsSlot] = React3__namespace.useState(null);
872
- return /* @__PURE__ */ jsxRuntime.jsx(chunkOW73RZOU_cjs.SaveBarProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(ModuleHeaderSlotContext.Provider, { value: headerSlot, children: /* @__PURE__ */ jsxRuntime.jsx(ModuleHeaderActionsSlotContext.Provider, { value: actionsSlot, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkH6OULCHF_cjs.cn(
873
- "flex h-screen overflow-hidden bg-background",
874
- // Frame mode: the inset gap around the framed card takes the sidebar (menu)
875
- // color, so the white card reads as a panel floating on the same tone as the
876
- // left menu. The card's own md:m-2 margin reveals this behind it.
877
- frame && "md:bg-sidebar"
878
- ), children: [
879
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden md:flex", children: /* @__PURE__ */ jsxRuntime.jsx(
880
- Sidebar,
881
- {
882
- navigation,
883
- logo,
884
- collapsed: sidebarCollapsed,
885
- onToggle: () => setSidebarCollapsed(!sidebarCollapsed),
886
- onNavigate,
887
- currentPath,
888
- user,
889
- onSignOut,
890
- onProfile,
891
- onSettings,
892
- onBilling,
893
- orgSwitcher,
894
- topContent: sidebarTopContent,
895
- footerContent: sidebarFooterContent,
896
- borderless: false,
897
- userMenuSlot,
898
- notificationSlot,
899
- unreadCount,
900
- sectionLabels: sidebarSectionLabels,
901
- navKey: sidebarNavKey,
902
- navDirection: sidebarNavDirection
903
- }
904
- ) }),
905
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkH6OULCHF_cjs.cn(
906
- "relative flex flex-1 flex-col overflow-hidden",
907
- frame && "md:m-2 md:rounded-xl md:border md:border-border md:bg-card"
908
- ), children: [
909
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkH6OULCHF_cjs.cn(
910
- "flex min-h-14 shrink-0 items-center justify-between gap-3 border-b border-border bg-card px-4 py-2",
911
- mobileHeader !== "minimal" && "hidden md:flex"
912
- ), children: [
913
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-3", children: [
914
- !hasBottomNav && /* @__PURE__ */ jsxRuntime.jsx(
915
- "button",
916
- {
917
- onClick: () => setMobileMenuOpen(true),
918
- className: "inline-flex items-center justify-center rounded-md p-2 text-muted-foreground hover:bg-accent md:hidden",
919
- "aria-label": "Open menu",
920
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "h-5 w-5" })
921
- }
922
- ),
923
- pageTitle && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "font-semibold text-lg", children: pageTitle }),
924
- topbarStart,
925
- /* @__PURE__ */ jsxRuntime.jsx("div", { ref: setHeaderSlot, className: "flex min-w-0 flex-1 items-center" })
926
- ] }),
927
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [
928
- /* @__PURE__ */ jsxRuntime.jsx("div", { ref: setActionsSlot, className: "flex items-center gap-2" }),
929
- topbarEnd
930
- ] })
931
- ] }),
932
- /* @__PURE__ */ jsxRuntime.jsx("main", { className: "min-w-0 flex-1 overflow-y-auto pb-16 md:pb-0", children }),
933
- /* @__PURE__ */ jsxRuntime.jsx(chunkOW73RZOU_cjs.SaveBar, {})
934
- ] }),
935
- mobileMenuOpen && /* @__PURE__ */ jsxRuntime.jsx(
936
- MobileOverlay,
937
- {
938
- navigation,
939
- logo,
940
- user,
941
- currentPath,
942
- onNavigate,
943
- onSignOut,
944
- onProfile,
945
- onSettings,
946
- onBilling,
947
- orgSwitcher,
948
- topContent: sidebarTopContent,
949
- footerContent: sidebarFooterContent,
950
- userMenuSlot,
951
- notificationSlot,
952
- unreadCount,
953
- onClose: () => setMobileMenuOpen(false)
954
- }
955
- )
956
- ] }) }) }) });
957
- }
958
- function TopbarLayout({
959
- navigation = [],
960
- logo,
961
- user,
962
- children,
963
- onNavigate,
964
- onSignOut,
965
- onProfile,
966
- onSettings,
967
- onBilling,
968
- userPlan,
969
- billingLabel,
970
- userMenuExtras,
971
- orgSwitcher,
972
- frame,
973
- currentPath,
974
- topbarStart,
975
- topbarEnd,
976
- notificationSlot,
977
- hasBottomNav = false
978
- }) {
979
- const [mobileMenuOpen, setMobileMenuOpen] = React3__namespace.useState(false);
980
- return /* @__PURE__ */ jsxRuntime.jsx(chunkOW73RZOU_cjs.SaveBarProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex h-screen flex-col overflow-hidden bg-background", children: [
981
- /* @__PURE__ */ jsxRuntime.jsx(
982
- Topbar,
983
- {
984
- navigation,
985
- logo,
986
- user,
987
- currentPath,
988
- onNavigate,
989
- onSignOut,
990
- onProfile,
991
- onSettings,
992
- onBilling,
993
- userPlan,
994
- billingLabel,
995
- userMenuExtras,
996
- orgSwitcher,
997
- leftContent: topbarStart,
998
- rightContent: topbarEnd || notificationSlot ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
999
- topbarEnd,
1000
- notificationSlot
1001
- ] }) : void 0,
1002
- onMenuClick: hasBottomNav ? void 0 : () => setMobileMenuOpen(true)
1003
- }
1004
- ),
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 }) }) }),
1006
- /* @__PURE__ */ jsxRuntime.jsx(chunkOW73RZOU_cjs.SaveBar, {}),
1007
- mobileMenuOpen && /* @__PURE__ */ jsxRuntime.jsx(
1008
- MobileOverlay,
1009
- {
1010
- navigation,
1011
- logo,
1012
- user,
1013
- currentPath,
1014
- onNavigate,
1015
- onSignOut,
1016
- onProfile,
1017
- onSettings,
1018
- onBilling,
1019
- orgSwitcher,
1020
- userMenuSlot: user ? /* @__PURE__ */ jsxRuntime.jsx(DrawerUserRow, { user }) : void 0,
1021
- onClose: () => setMobileMenuOpen(false)
1022
- }
1023
- )
1024
- ] }) });
1025
- }
1026
- function DrawerUserRow({ user }) {
1027
- const label = user.fullName || user.email;
1028
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-center gap-2 px-1", children: [
1029
- user.avatarUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: user.avatarUrl, alt: "", className: "h-7 w-7 shrink-0 rounded-full object-cover" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-primary text-xs font-semibold text-primary-foreground", children: (label || "?").charAt(0).toUpperCase() }),
1030
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-sm font-medium text-sidebar-foreground", children: label })
1031
- ] });
1032
- }
1033
- function MinimalLayout({
1034
- logo,
1035
- user: _user,
1036
- children,
1037
- headerEnd
1038
- }) {
1039
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-screen flex-col", children: [
1040
- /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex h-14 shrink-0 items-center justify-between border-b border-border bg-card px-4 md:px-6", children: [
1041
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3", children: logo ?? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg font-bold", children: "App" }) }),
1042
- headerEnd && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: headerEnd })
1043
- ] }),
1044
- /* @__PURE__ */ jsxRuntime.jsx("main", { className: "min-w-0 flex-1 overflow-y-auto pb-16 md:pb-0", children })
1045
- ] });
1046
- }
1047
- function MobileOverlay({ onClose, onNavigate, ...sidebarProps }) {
1048
- const [visible, setVisible] = React3__namespace.useState(false);
1049
- React3__namespace.useEffect(() => {
1050
- const id = requestAnimationFrame(() => setVisible(true));
1051
- return () => cancelAnimationFrame(id);
1052
- }, []);
1053
- const close = React3__namespace.useCallback(() => {
1054
- setVisible(false);
1055
- window.setTimeout(onClose, 250);
1056
- }, [onClose]);
1057
- React3__namespace.useEffect(() => {
1058
- const previous = document.body.style.overflow;
1059
- document.body.style.overflow = "hidden";
1060
- return () => {
1061
- document.body.style.overflow = previous;
1062
- };
1063
- }, []);
1064
- React3__namespace.useEffect(() => {
1065
- const onKey = (e) => {
1066
- if (e.key === "Escape") close();
1067
- };
1068
- window.addEventListener("keydown", onKey);
1069
- return () => window.removeEventListener("keydown", onKey);
1070
- }, [close]);
1071
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-[60] md:hidden", children: [
1072
- /* @__PURE__ */ jsxRuntime.jsx(
1073
- "div",
1074
- {
1075
- className: chunkH6OULCHF_cjs.cn(
1076
- "absolute inset-0 bg-black/50 transition-opacity duration-300 ease-out",
1077
- visible ? "opacity-100" : "opacity-0"
1078
- ),
1079
- onClick: close
1080
- }
1081
- ),
1082
- /* @__PURE__ */ jsxRuntime.jsx(
1083
- "div",
1084
- {
1085
- className: chunkH6OULCHF_cjs.cn(
1086
- "absolute inset-y-0 left-0 shadow-2xl transition-transform duration-300 ease-out will-change-transform",
1087
- visible ? "translate-x-0" : "-translate-x-full"
1088
- ),
1089
- children: /* @__PURE__ */ jsxRuntime.jsx(
1090
- Sidebar,
1091
- {
1092
- ...sidebarProps,
1093
- collapsed: false,
1094
- onToggle: close,
1095
- borderless: true,
1096
- onNavigate: (route) => {
1097
- onNavigate?.(route);
1098
- close();
1099
- }
1100
- }
1101
- )
1102
- }
1103
- )
1104
- ] });
1105
- }
1106
- var BOTTOM_NAV_ICONS = {
1107
- Home: lucideReact.Home,
1108
- Receipt: lucideReact.Receipt,
1109
- ArrowLeftRight: lucideReact.ArrowLeftRight,
1110
- Calendar: lucideReact.Calendar,
1111
- CreditCard: lucideReact.CreditCard,
1112
- Settings: lucideReact.Settings,
1113
- Menu: lucideReact.Menu,
1114
- MessageCircle: lucideReact.MessageCircle,
1115
- Wallet: lucideReact.Wallet,
1116
- PiggyBank: lucideReact.PiggyBank,
1117
- Plus: lucideReact.Plus
1118
- };
1119
- function FloatingProfileAvatar({ user, onClick }) {
1120
- if (!user) return null;
1121
- const label = user.fullName || user.email;
1122
- return /* @__PURE__ */ jsxRuntime.jsx(
1123
- "button",
1124
- {
1125
- type: "button",
1126
- onClick,
1127
- "aria-label": "Profile",
1128
- className: "fixed right-3 top-3 z-40 md:hidden",
1129
- children: user.avatarUrl ? /* @__PURE__ */ jsxRuntime.jsx(
1130
- "img",
1131
- {
1132
- src: user.avatarUrl,
1133
- alt: "",
1134
- className: "h-9 w-9 rounded-full object-cover shadow-md ring-2 ring-background"
1135
- }
1136
- ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-9 w-9 items-center justify-center rounded-full bg-primary text-sm font-semibold text-primary-foreground shadow-md ring-2 ring-background", children: (label || "?").charAt(0).toUpperCase() })
1137
- }
1138
- );
1139
- }
1140
- function MobileBottomNav({
1141
- items,
1142
- currentPath,
1143
- onNavigate,
1144
- onAction
1145
- }) {
1146
- const path = currentPath ?? "";
1147
- return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "fixed inset-x-0 bottom-0 z-50 flex h-16 items-center justify-around border-t border-border bg-background md:hidden", children: items.map((item) => {
1148
- if (item.kind === "action") {
1149
- const ActionIcon = BOTTOM_NAV_ICONS[item.icon] ?? lucideReact.Plus;
1150
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-1 items-start justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
1151
- "button",
1152
- {
1153
- type: "button",
1154
- onClick: () => onAction?.(item.id),
1155
- "aria-label": item.label ?? "Add",
1156
- className: "-mt-6 flex h-14 w-14 items-center justify-center rounded-full bg-primary text-primary-foreground shadow-lg shadow-primary/30 ring-4 ring-background transition-transform active:scale-95",
1157
- children: /* @__PURE__ */ jsxRuntime.jsx(ActionIcon, { className: "h-6 w-6" })
1158
- }
1159
- ) }, item.id);
1160
- }
1161
- const isActive = item.route === "/" ? path === "/" || path === "" : path === item.route || path.startsWith(item.route + "/");
1162
- const Icon = BOTTOM_NAV_ICONS[item.icon] ?? lucideReact.Home;
1163
- return /* @__PURE__ */ jsxRuntime.jsxs(
1164
- "button",
1165
- {
1166
- type: "button",
1167
- onClick: () => onNavigate?.(item.route),
1168
- className: chunkH6OULCHF_cjs.cn(
1169
- "flex flex-1 flex-col items-center justify-center gap-0.5 px-1 py-1 transition-colors",
1170
- isActive ? "text-primary" : "text-muted-foreground"
1171
- ),
1172
- "aria-current": isActive ? "page" : void 0,
1173
- children: [
1174
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-5 w-5" }),
1175
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", children: item.label })
1176
- ]
1177
- },
1178
- item.route
1179
- );
1180
- }) });
1181
- }
1182
- function AppShell({
1183
- variant,
1184
- contentFrame,
1185
- navigation = [],
1186
- logo,
1187
- user,
1188
- children,
1189
- onNavigate,
1190
- onSignOut,
1191
- onProfile,
1192
- onSettings,
1193
- onBilling,
1194
- userPlan,
1195
- billingLabel,
1196
- pageTitle,
1197
- currentPath,
1198
- userMenuExtras,
1199
- orgSwitcher,
1200
- topbarStart,
1201
- topbarEnd,
1202
- sidebarTopContent,
1203
- sidebarFooterContent,
1204
- bottomNav,
1205
- onBottomNavAction,
1206
- mobileHeader = "minimal",
1207
- userMenuSlot,
1208
- notificationSlot,
1209
- unreadCount = 0,
1210
- sidebarSectionLabels,
1211
- sidebarNavKey,
1212
- sidebarNavDirection,
1213
- rightRail,
1214
- rightRailOpen = true,
1215
- defaultRightRailWidth,
1216
- onRightRailWidthChange,
1217
- rightRailMinWidth,
1218
- rightRailMaxWidth,
1219
- rightRailResizeLabel
1220
- }) {
1221
- const hasBottomNav = !!bottomNav?.length;
1222
- const bottomBar = hasBottomNav ? /* @__PURE__ */ jsxRuntime.jsx(
1223
- MobileBottomNav,
1224
- {
1225
- items: bottomNav,
1226
- currentPath,
1227
- onNavigate,
1228
- onAction: onBottomNavAction
1229
- }
1230
- ) : null;
1231
- const floatingAvatar = mobileHeader === "transparent" && user ? /* @__PURE__ */ jsxRuntime.jsx(FloatingProfileAvatar, { user, onClick: onProfile }) : null;
1232
- let layoutElement;
1233
- switch (variant) {
1234
- case "sidebar":
1235
- layoutElement = /* @__PURE__ */ jsxRuntime.jsx(
1236
- SidebarLayout,
1237
- {
1238
- navigation,
1239
- logo,
1240
- user,
1241
- onNavigate,
1242
- onSignOut,
1243
- onProfile,
1244
- onSettings,
1245
- onBilling,
1246
- userMenuExtras,
1247
- orgSwitcher,
1248
- sidebarTopContent,
1249
- sidebarFooterContent,
1250
- frame: contentFrame,
1251
- currentPath,
1252
- pageTitle,
1253
- topbarStart,
1254
- topbarEnd,
1255
- userMenuSlot,
1256
- notificationSlot,
1257
- unreadCount,
1258
- hasBottomNav,
1259
- mobileHeader,
1260
- sidebarSectionLabels,
1261
- sidebarNavKey,
1262
- sidebarNavDirection,
1263
- children
1264
- }
1265
- );
1266
- break;
1267
- case "topbar":
1268
- layoutElement = /* @__PURE__ */ jsxRuntime.jsx(
1269
- TopbarLayout,
1270
- {
1271
- navigation,
1272
- logo,
1273
- user,
1274
- onNavigate,
1275
- onSignOut,
1276
- onProfile,
1277
- onSettings,
1278
- onBilling,
1279
- userPlan,
1280
- billingLabel,
1281
- userMenuExtras,
1282
- orgSwitcher,
1283
- frame: contentFrame,
1284
- currentPath,
1285
- topbarStart,
1286
- topbarEnd,
1287
- notificationSlot,
1288
- hasBottomNav,
1289
- children
1290
- }
1291
- );
1292
- break;
1293
- case "minimal":
1294
- layoutElement = /* @__PURE__ */ jsxRuntime.jsx(MinimalLayout, { logo, user, headerEnd: topbarEnd, children });
1295
- break;
1296
- default: {
1297
- return null;
1298
- }
1299
- }
1300
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
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,
1315
- floatingAvatar,
1316
- bottomBar
1317
- ] });
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
- }
1437
- var NavTransitionContext = React3__namespace.createContext("slide");
1438
- function NavTransitionProvider({ value, children }) {
1439
- return /* @__PURE__ */ jsxRuntime.jsx(NavTransitionContext.Provider, { value, children });
1440
- }
1441
- function useNavTransition() {
1442
- return React3__namespace.useContext(NavTransitionContext);
1443
- }
1444
- function resolveTransitionClass(transition, direction) {
1445
- if (transition === "none") return "";
1446
- if (transition === "fade") return "saas-page-enter";
1447
- if (direction === "back") return "saas-nav-back";
1448
- if (direction === "forward") return "saas-nav-forward";
1449
- return "saas-page-enter";
1450
- }
1451
- function PageTransition({
1452
- transitionKey,
1453
- direction,
1454
- className,
1455
- children
1456
- }) {
1457
- const transition = useNavTransition();
1458
- const animClass = resolveTransitionClass(transition, direction);
1459
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: chunkH6OULCHF_cjs.cn(animClass, className), children }, transitionKey);
1460
- }
1461
- function PageHeaderActions({ children }) {
1462
- const slot = useModuleHeaderActionsSlot();
1463
- if (slot) return reactDom.createPortal(children, slot);
1464
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4 flex items-center justify-end gap-2", children });
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
- }
1471
- var ModuleLayoutContext = React3__namespace.createContext("rail");
1472
- function ModuleLayoutProvider({ variant, children }) {
1473
- return /* @__PURE__ */ jsxRuntime.jsx(ModuleLayoutContext.Provider, { value: variant, children });
1474
- }
1475
- function useModuleLayout() {
1476
- return React3__namespace.useContext(ModuleLayoutContext);
1477
- }
1478
- function NavItem2({ item }) {
1479
- const [expanded, setExpanded] = React3__namespace.useState(true);
1480
- const Icon = item.icon ? ICON_MAP2[item.icon] ?? null : null;
1481
- const hasChildren = item.children && item.children.length > 0;
1482
- const hasActiveChild = hasChildren && item.children.some((c) => c.active);
1483
- const isActive = item.active || hasActiveChild;
1484
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1485
- /* @__PURE__ */ jsxRuntime.jsxs(
1486
- "button",
1487
- {
1488
- type: "button",
1489
- onClick: () => hasChildren ? setExpanded(!expanded) : item.onClick?.(),
1490
- className: chunkH6OULCHF_cjs.cn(
1491
- "flex items-center gap-2 w-full rounded-md px-2.5 py-1.5 text-sm transition-colors",
1492
- isActive ? "bg-primary/10 text-primary font-medium" : "text-muted-foreground hover:text-foreground hover:bg-muted/50"
1493
- ),
1494
- children: [
1495
- Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4 shrink-0" }),
1496
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 text-left truncate", children: item.label }),
1497
- item.premium && /* @__PURE__ */ jsxRuntime.jsx(PremiumBadge, { className: "ml-1" }),
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" }))
1499
- ]
1500
- }
1501
- ),
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(
1503
- "button",
1504
- {
1505
- type: "button",
1506
- onClick: child.onClick,
1507
- className: chunkH6OULCHF_cjs.cn(
1508
- "flex items-center w-full rounded-md px-2.5 py-1 text-xs transition-colors",
1509
- child.active ? "text-primary font-medium bg-primary/5" : "text-muted-foreground hover:text-foreground hover:bg-muted/50"
1510
- ),
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
- ]
1515
- },
1516
- child.id
1517
- )) })
1518
- ] });
1519
- }
1520
- function MobileTabs({ nav }) {
1521
- const scrollRef = React3__namespace.useRef(null);
1522
- const [expandedId, setExpandedId] = React3__namespace.useState(null);
1523
- React3__namespace.useEffect(() => {
1524
- const container = scrollRef.current;
1525
- if (!container) return;
1526
- const activeEl = container.querySelector('[data-active="true"]');
1527
- if (activeEl) {
1528
- const left = activeEl.offsetLeft - container.offsetWidth / 2 + activeEl.offsetWidth / 2;
1529
- container.scrollTo({ left: Math.max(0, left), behavior: "smooth" });
1530
- }
1531
- }, [nav]);
1532
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:hidden -mx-1 mb-4 no-print", children: [
1533
- /* @__PURE__ */ jsxRuntime.jsx("div", { ref: scrollRef, className: "flex gap-1 px-1 pb-2 overflow-x-auto scrollbar-none", children: nav.map((item) => {
1534
- const Icon = item.icon ? ICON_MAP2[item.icon] ?? null : null;
1535
- const hasChildren = item.children && item.children.length > 0;
1536
- const isActive = item.active || item.children?.some((c) => c.active);
1537
- const isExpanded = expandedId === item.id;
1538
- return /* @__PURE__ */ jsxRuntime.jsxs(
1539
- "button",
1540
- {
1541
- type: "button",
1542
- "data-active": isActive || void 0,
1543
- onClick: () => {
1544
- if (hasChildren) {
1545
- setExpandedId(isExpanded ? null : item.id);
1546
- } else {
1547
- item.onClick?.();
1548
- setExpandedId(null);
1549
- }
1550
- },
1551
- className: chunkH6OULCHF_cjs.cn(
1552
- "flex items-center gap-1.5 whitespace-nowrap rounded-full px-3 py-1.5 text-xs font-medium transition-colors shrink-0",
1553
- isActive ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground hover:text-foreground"
1554
- ),
1555
- children: [
1556
- Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-3 w-3" }),
1557
- item.label,
1558
- item.premium && /* @__PURE__ */ jsxRuntime.jsx(PremiumBadge, {}),
1559
- hasChildren && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: chunkH6OULCHF_cjs.cn("h-2.5 w-2.5 transition-transform", isExpanded && "rotate-180") })
1560
- ]
1561
- },
1562
- item.id
1563
- );
1564
- }) }),
1565
- expandedId && (() => {
1566
- const item = nav.find((n) => n.id === expandedId);
1567
- if (!item?.children) return null;
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(
1569
- "button",
1570
- {
1571
- type: "button",
1572
- onClick: () => {
1573
- child.onClick?.();
1574
- setExpandedId(null);
1575
- },
1576
- className: chunkH6OULCHF_cjs.cn(
1577
- "whitespace-nowrap rounded-full px-2.5 py-1 text-[11px] font-medium transition-colors shrink-0",
1578
- child.active ? "bg-foreground/10 text-foreground" : "text-muted-foreground hover:text-foreground"
1579
- ),
1580
- children: [
1581
- child.label,
1582
- child.premium && /* @__PURE__ */ jsxRuntime.jsx(PremiumBadge, {})
1583
- ]
1584
- },
1585
- child.id
1586
- )) });
1587
- })()
1588
- ] });
1589
- }
1590
- var BackStyleContext = React3__namespace.createContext("link");
1591
- function BackStyleProvider({ style, children }) {
1592
- return /* @__PURE__ */ jsxRuntime.jsx(BackStyleContext.Provider, { value: style, children });
1593
- }
1594
- function useBackStyle() {
1595
- return React3__namespace.useContext(BackStyleContext);
1596
- }
1597
- function SubpageHeader({ title, subtitle, icon, onBack, parentLabel, actions, backStyle }) {
1598
- const t = core.useTranslation();
1599
- const appStyle = useBackStyle();
1600
- const { onBack: effectiveOnBack, parentLabel: effectiveParentLabel } = chunkOW73RZOU_cjs.useCrossModuleBack(onBack, parentLabel);
1601
- chunkOW73RZOU_cjs.useBackHandler(effectiveOnBack);
1602
- const Icon = icon ? ICON_MAP2[icon] ?? null : null;
1603
- const style = !effectiveOnBack ? "icon" : backStyle ?? appStyle;
1604
- const effectiveStyle = style !== "icon" && !effectiveParentLabel ? "icon" : style;
1605
- const titleBlock = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4", children: [
1606
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
1607
- effectiveStyle === "icon" && effectiveOnBack && /* @__PURE__ */ jsxRuntime.jsx(
1608
- "button",
1609
- {
1610
- onClick: effectiveOnBack,
1611
- className: "flex h-8 w-8 items-center justify-center rounded-lg border hover:bg-muted bg-card shadow-button active:shadow-button-inset transition-colors",
1612
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "h-4 w-4" })
1613
- }
1614
- ),
1615
- Icon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-10 w-10 items-center justify-center rounded-xl bg-muted", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-5 w-5 text-muted-foreground" }) }),
1616
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1617
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-bold", children: title }),
1618
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: subtitle })
1619
- ] })
1620
- ] }),
1621
- actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "no-print", children: actions })
1622
- ] });
1623
- if (effectiveStyle === "breadcrumb") {
1624
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 mb-6", children: [
1625
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4", children: [
1626
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
1627
- /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: effectiveOnBack, className: "hover:text-foreground transition-colors", children: effectiveParentLabel }),
1628
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-3.5 w-3.5" }),
1629
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground font-medium", children: title })
1630
- ] }),
1631
- actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "no-print", children: actions })
1632
- ] }),
1633
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground -mt-2", children: subtitle })
1634
- ] });
1635
- }
1636
- if (effectiveStyle === "link") {
1637
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 mb-6", children: [
1638
- /* @__PURE__ */ jsxRuntime.jsxs(
1639
- "button",
1640
- {
1641
- onClick: effectiveOnBack,
1642
- className: "inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground transition-colors",
1643
- children: [
1644
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { className: "h-4 w-4" }),
1645
- t("crud.detail.backTo", { entities: effectiveParentLabel })
1646
- ]
1647
- }
1648
- ),
1649
- titleBlock
1650
- ] });
1651
- }
1652
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4 mb-6", children: titleBlock });
1653
- }
1654
- function ModuleHeader({ nav }) {
1655
- const slot = useModuleHeaderSlot();
1656
- function defaultChild(item) {
1657
- const kids = item.children ?? [];
1658
- return kids.find((c) => /list/i.test(c.id) || /^list$/i.test(c.label)) ?? kids[kids.length - 1];
1659
- }
1660
- const content = /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex w-full min-w-0 items-center gap-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-0 items-center gap-0.5 overflow-x-auto scrollbar-none", children: nav.map((item) => {
1661
- const Icon = item.icon ? ICON_MAP2[item.icon] ?? null : null;
1662
- const hasChildren = item.children && item.children.length > 0;
1663
- const isActive = item.active || item.children?.some((c) => c.active);
1664
- return /* @__PURE__ */ jsxRuntime.jsxs(
1665
- "button",
1666
- {
1667
- type: "button",
1668
- onClick: () => hasChildren ? defaultChild(item)?.onClick?.() : item.onClick?.(),
1669
- className: chunkH6OULCHF_cjs.cn(
1670
- "flex shrink-0 items-center gap-1.5 whitespace-nowrap border-b-2 px-2.5 py-1.5 text-sm font-medium transition-colors",
1671
- isActive ? "border-primary text-foreground" : "border-transparent text-muted-foreground hover:text-foreground"
1672
- ),
1673
- children: [
1674
- Icon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4" }),
1675
- item.label,
1676
- item.premium && /* @__PURE__ */ jsxRuntime.jsx(PremiumBadge, {})
1677
- ]
1678
- },
1679
- item.id
1680
- );
1681
- }) }) });
1682
- if (slot) return reactDom.createPortal(content, slot);
1683
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-5 border-b border-border pb-2", children: content });
1684
- }
1685
- function ModulePage({ title, subtitle, nav, children, className, headerAction, showHeader = true, sidebarFooter, navVariant, viewKey, direction }) {
1686
- const ctxVariant = useModuleLayout();
1687
- const variant = navVariant ?? ctxVariant;
1688
- const transitionKey = viewKey ?? "view";
1689
- if (variant === "tabs") {
1690
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1691
- /* @__PURE__ */ jsxRuntime.jsx(ModuleHeader, { nav }),
1692
- showHeader && headerAction && /* @__PURE__ */ jsxRuntime.jsx(PageHeaderActions, { children: headerAction }),
1693
- /* @__PURE__ */ jsxRuntime.jsx(PageTransition, { transitionKey, direction, className: chunkH6OULCHF_cjs.cn("min-w-0", className), children })
1694
- ] });
1695
- }
1696
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkH6OULCHF_cjs.cn("flex gap-6 -mt-2", className), children: [
1697
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-48 shrink-0 hidden md:block no-print", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkH6OULCHF_cjs.cn(sidebarFooter && "sticky top-4 flex flex-col"), style: sidebarFooter ? { height: "calc(100vh - 8rem)" } : void 0, children: [
1698
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1699
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-semibold text-muted-foreground uppercase tracking-wider px-2.5 mb-2", children: title }),
1700
- /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "space-y-0.5", children: nav.map((item) => /* @__PURE__ */ jsxRuntime.jsx(NavItem2, { item }, item.id)) })
1701
- ] }),
1702
- sidebarFooter && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto", children: sidebarFooter })
1703
- ] }) }),
1704
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
1705
- showHeader && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-6 flex items-start justify-between gap-3", children: [
1706
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1707
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-bold", children: title }),
1708
- subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: subtitle })
1709
- ] }),
1710
- headerAction
1711
- ] }),
1712
- /* @__PURE__ */ jsxRuntime.jsx(MobileTabs, { nav }),
1713
- /* @__PURE__ */ jsxRuntime.jsx(PageTransition, { transitionKey, direction, children })
1714
- ] })
1715
- ] });
1716
- }
1717
- var ContentSplitContext = React3__namespace.createContext(null);
1718
- function ContentSplit({
1719
- children,
1720
- aside,
1721
- asideTitle,
1722
- asideDescription,
1723
- asideWidth = "20rem",
1724
- asideOpen,
1725
- onAsideOpenChange,
1726
- collapsible = false,
1727
- defaultCollapsed = false,
1728
- className
1729
- }) {
1730
- const [internalOpen, setInternalOpen] = React3__namespace.useState(false);
1731
- const open = asideOpen ?? internalOpen;
1732
- const setOpen = onAsideOpenChange ?? setInternalOpen;
1733
- const [collapsed, setCollapsed] = React3__namespace.useState(collapsible && defaultCollapsed);
1734
- return /* @__PURE__ */ jsxRuntime.jsxs(ContentSplitContext.Provider, { value: { open, setOpen }, children: [
1735
- /* @__PURE__ */ jsxRuntime.jsxs(
1736
- "div",
1737
- {
1738
- className: chunkH6OULCHF_cjs.cn("lg:grid lg:items-start lg:gap-6", className),
1739
- style: { gridTemplateColumns: `minmax(0, 1fr) ${collapsed ? "auto" : asideWidth}` },
1740
- children: [
1741
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0", children }),
1742
- /* @__PURE__ */ jsxRuntime.jsx("aside", { className: "hidden lg:block lg:sticky lg:top-4", children: collapsed ? /* @__PURE__ */ jsxRuntime.jsx(
1743
- chunkH6OULCHF_cjs.Button,
1744
- {
1745
- variant: "outline",
1746
- size: "sm",
1747
- onClick: () => setCollapsed(false),
1748
- className: "h-9 w-9 p-0",
1749
- "aria-label": typeof asideTitle === "string" ? asideTitle : void 0,
1750
- title: typeof asideTitle === "string" ? asideTitle : void 0,
1751
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelRightOpen, { className: "h-4 w-4" })
1752
- }
1753
- ) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-card border border-border bg-card", children: [
1754
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2 border-b border-border px-4 py-3", children: [
1755
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
1756
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-foreground", children: asideTitle }),
1757
- asideDescription && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-0.5 text-xs text-muted-foreground", children: asideDescription })
1758
- ] }),
1759
- collapsible && /* @__PURE__ */ jsxRuntime.jsx(
1760
- "button",
1761
- {
1762
- type: "button",
1763
- onClick: () => setCollapsed(true),
1764
- className: "rounded p-1 text-muted-foreground transition-colors hover:bg-muted/60 hover:text-foreground",
1765
- "aria-label": "collapse",
1766
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelRightClose, { className: "h-4 w-4" })
1767
- }
1768
- )
1769
- ] }),
1770
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: aside })
1771
- ] }) })
1772
- ]
1773
- }
1774
- ),
1775
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "lg:hidden", children: /* @__PURE__ */ jsxRuntime.jsx(chunkOW73RZOU_cjs.Sheet, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(chunkOW73RZOU_cjs.SheetContent, { width: "max-w-sm", children: [
1776
- /* @__PURE__ */ jsxRuntime.jsxs(chunkOW73RZOU_cjs.SheetHeader, { children: [
1777
- /* @__PURE__ */ jsxRuntime.jsx(chunkOW73RZOU_cjs.SheetTitle, { children: asideTitle }),
1778
- asideDescription && /* @__PURE__ */ jsxRuntime.jsx(chunkOW73RZOU_cjs.SheetDescription, { children: asideDescription })
1779
- ] }),
1780
- /* @__PURE__ */ jsxRuntime.jsx(chunkOW73RZOU_cjs.SheetBody, { children: aside })
1781
- ] }) }) })
1782
- ] });
1783
- }
1784
- function ContentSplitTrigger({ label, iconOnly, className }) {
1785
- const ctx = React3__namespace.useContext(ContentSplitContext);
1786
- if (!ctx) return null;
1787
- return /* @__PURE__ */ jsxRuntime.jsxs(
1788
- chunkH6OULCHF_cjs.Button,
1789
- {
1790
- variant: "outline",
1791
- size: "sm",
1792
- onClick: () => ctx.setOpen(true),
1793
- className: chunkH6OULCHF_cjs.cn("lg:hidden", className),
1794
- "aria-label": typeof label === "string" ? label : void 0,
1795
- children: [
1796
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelRight, { className: chunkH6OULCHF_cjs.cn("h-4 w-4", !iconOnly && "mr-1.5") }),
1797
- !iconOnly && label
1798
- ]
1799
- }
1800
- );
1801
- }
1802
-
1803
- exports.AppShell = AppShell;
1804
- exports.BackStyleProvider = BackStyleProvider;
1805
- exports.ContentSplit = ContentSplit;
1806
- exports.ContentSplitTrigger = ContentSplitTrigger;
1807
- exports.ICON_MAP = ICON_MAP;
1808
- exports.ModuleLayoutProvider = ModuleLayoutProvider;
1809
- exports.ModulePage = ModulePage;
1810
- exports.NavTransitionProvider = NavTransitionProvider;
1811
- exports.PageHeaderActions = PageHeaderActions;
1812
- exports.PageTransition = PageTransition;
1813
- exports.Sidebar = Sidebar;
1814
- exports.SubpageHeader = SubpageHeader;
1815
- exports.Topbar = Topbar;
1816
- exports.useBackStyle = useBackStyle;
1817
- exports.useLayoutStore = useLayoutStore;
1818
- exports.useModuleHeaderActionsSlot = useModuleHeaderActionsSlot;
1819
- exports.useModuleHeaderSlot = useModuleHeaderSlot;
1820
- exports.useModuleLayout = useModuleLayout;
1821
- exports.useNavTransition = useNavTransition;
1822
- //# sourceMappingURL=chunk-7ZQQZD4Q.cjs.map
1823
- //# sourceMappingURL=chunk-7ZQQZD4Q.cjs.map