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