@logickernel/frame 0.1.0

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 (50) hide show
  1. package/README.md +461 -0
  2. package/dist/adapters/nextjs.js +31 -0
  3. package/dist/adapters/nextjs.js.map +1 -0
  4. package/dist/adapters/nextjs.mjs +25 -0
  5. package/dist/adapters/nextjs.mjs.map +1 -0
  6. package/dist/components/AppSidebar.js +467 -0
  7. package/dist/components/AppSidebar.js.map +1 -0
  8. package/dist/components/AppSidebar.mjs +446 -0
  9. package/dist/components/AppSidebar.mjs.map +1 -0
  10. package/dist/components/NavMain.js +133 -0
  11. package/dist/components/NavMain.js.map +1 -0
  12. package/dist/components/NavMain.mjs +112 -0
  13. package/dist/components/NavMain.mjs.map +1 -0
  14. package/dist/components/NavUser.js +88 -0
  15. package/dist/components/NavUser.js.map +1 -0
  16. package/dist/components/NavUser.mjs +86 -0
  17. package/dist/components/NavUser.mjs.map +1 -0
  18. package/dist/components/TeamSwitcher.js +164 -0
  19. package/dist/components/TeamSwitcher.js.map +1 -0
  20. package/dist/components/TeamSwitcher.mjs +162 -0
  21. package/dist/components/TeamSwitcher.mjs.map +1 -0
  22. package/dist/hooks/useNavigation.d.mts +24 -0
  23. package/dist/hooks/useNavigation.d.ts +24 -0
  24. package/dist/hooks/useNavigation.js +59 -0
  25. package/dist/hooks/useNavigation.js.map +1 -0
  26. package/dist/hooks/useNavigation.mjs +57 -0
  27. package/dist/hooks/useNavigation.mjs.map +1 -0
  28. package/dist/index.d.mts +58 -0
  29. package/dist/index.d.ts +58 -0
  30. package/dist/index.js +495 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/index.mjs +465 -0
  33. package/dist/index.mjs.map +1 -0
  34. package/dist/types/index.d.mts +85 -0
  35. package/dist/types/index.d.ts +85 -0
  36. package/dist/types/index.js +4 -0
  37. package/dist/types/index.js.map +1 -0
  38. package/dist/types/index.mjs +3 -0
  39. package/dist/types/index.mjs.map +1 -0
  40. package/dist/types/ui-components.d.js +4 -0
  41. package/dist/types/ui-components.d.js.map +1 -0
  42. package/dist/types/ui-components.d.mjs +3 -0
  43. package/dist/types/ui-components.d.mjs.map +1 -0
  44. package/dist/utils/iconMapper.d.mts +16 -0
  45. package/dist/utils/iconMapper.d.ts +16 -0
  46. package/dist/utils/iconMapper.js +52 -0
  47. package/dist/utils/iconMapper.js.map +1 -0
  48. package/dist/utils/iconMapper.mjs +30 -0
  49. package/dist/utils/iconMapper.mjs.map +1 -0
  50. package/package.json +76 -0
@@ -0,0 +1,467 @@
1
+ 'use strict';
2
+
3
+ var LucideIcons = require('lucide-react');
4
+ var collapsible = require('@/components/ui/collapsible');
5
+ var sidebar = require('@/components/ui/sidebar');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var avatar = require('@/components/ui/avatar');
8
+ var dropdownMenu = require('@/components/ui/dropdown-menu');
9
+ var react = require('react');
10
+
11
+ function _interopNamespace(e) {
12
+ if (e && e.__esModule) return e;
13
+ var n = Object.create(null);
14
+ if (e) {
15
+ Object.keys(e).forEach(function (k) {
16
+ if (k !== 'default') {
17
+ var d = Object.getOwnPropertyDescriptor(e, k);
18
+ Object.defineProperty(n, k, d.get ? d : {
19
+ enumerable: true,
20
+ get: function () { return e[k]; }
21
+ });
22
+ }
23
+ });
24
+ }
25
+ n.default = e;
26
+ return Object.freeze(n);
27
+ }
28
+
29
+ var LucideIcons__namespace = /*#__PURE__*/_interopNamespace(LucideIcons);
30
+
31
+ var ICON_MAP = {
32
+ Home: LucideIcons__namespace.Home,
33
+ Users: LucideIcons__namespace.Users,
34
+ GalleryVerticalEnd: LucideIcons__namespace.GalleryVerticalEnd,
35
+ Settings: LucideIcons__namespace.Settings,
36
+ CreditCard: LucideIcons__namespace.CreditCard,
37
+ Building2: LucideIcons__namespace.Building2,
38
+ Check: LucideIcons__namespace.Check,
39
+ ChevronsUpDown: LucideIcons__namespace.ChevronsUpDown,
40
+ ChevronRight: LucideIcons__namespace.ChevronRight,
41
+ BadgeCheck: LucideIcons__namespace.BadgeCheck,
42
+ LogOut: LucideIcons__namespace.LogOut
43
+ // Add more icons as needed
44
+ };
45
+ function getIconComponent(icon) {
46
+ if (!icon) {
47
+ return void 0;
48
+ }
49
+ if (typeof icon !== "string") {
50
+ return icon;
51
+ }
52
+ return ICON_MAP[icon];
53
+ }
54
+ function NavMain({ items, adapter }) {
55
+ const pathname = adapter.usePathname();
56
+ const Link = adapter.Link;
57
+ const groups = [];
58
+ let currentGroup = {
59
+ items: []
60
+ };
61
+ items.forEach((item) => {
62
+ const iconComponent = getIconComponent(item.icon);
63
+ if (!item.url) {
64
+ if (currentGroup.items.length > 0 || currentGroup.label) {
65
+ groups.push(currentGroup);
66
+ }
67
+ currentGroup = {
68
+ label: { title: item.title, icon: iconComponent },
69
+ items: []
70
+ };
71
+ } else {
72
+ currentGroup.items.push({
73
+ title: item.title,
74
+ url: item.url,
75
+ icon: iconComponent,
76
+ isActive: item.isActive,
77
+ items: item.items
78
+ });
79
+ }
80
+ });
81
+ if (currentGroup.items.length > 0 || currentGroup.label) {
82
+ groups.push(currentGroup);
83
+ }
84
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: groups.map((group, groupIndex) => /* @__PURE__ */ jsxRuntime.jsxs(sidebar.SidebarGroup, { children: [
85
+ group.label && /* @__PURE__ */ jsxRuntime.jsxs(sidebar.SidebarGroupLabel, { children: [
86
+ group.label.icon && /* @__PURE__ */ jsxRuntime.jsx(group.label.icon, { className: "mr-2" }),
87
+ group.label.title
88
+ ] }),
89
+ group.items.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarMenu, { children: group.items.map((item) => {
90
+ const isActive = pathname === item.url || item.isActive;
91
+ const hasSubItems = item.items && item.items.length > 0;
92
+ if (hasSubItems) {
93
+ return /* @__PURE__ */ jsxRuntime.jsx(
94
+ collapsible.Collapsible,
95
+ {
96
+ asChild: true,
97
+ defaultOpen: isActive,
98
+ className: "group/collapsible",
99
+ children: /* @__PURE__ */ jsxRuntime.jsxs(sidebar.SidebarMenuItem, { children: [
100
+ /* @__PURE__ */ jsxRuntime.jsx(collapsible.CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
101
+ sidebar.SidebarMenuButton,
102
+ {
103
+ tooltip: item.title,
104
+ isActive,
105
+ children: [
106
+ item.icon && /* @__PURE__ */ jsxRuntime.jsx(item.icon, {}),
107
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: item.title }),
108
+ /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.ChevronRight, { className: "ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" })
109
+ ]
110
+ }
111
+ ) }),
112
+ /* @__PURE__ */ jsxRuntime.jsx(collapsible.CollapsibleContent, { children: /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarMenuSub, { children: item.items?.map((subItem) => /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarMenuSubItem, { children: /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarMenuSubButton, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Link, { href: subItem.url, children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: subItem.title }) }) }) }, subItem.title)) }) })
113
+ ] })
114
+ },
115
+ item.title
116
+ );
117
+ }
118
+ return /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarMenuItem, { children: /* @__PURE__ */ jsxRuntime.jsx(
119
+ sidebar.SidebarMenuButton,
120
+ {
121
+ asChild: true,
122
+ tooltip: item.title,
123
+ isActive,
124
+ children: /* @__PURE__ */ jsxRuntime.jsxs(Link, { href: item.url, children: [
125
+ item.icon && /* @__PURE__ */ jsxRuntime.jsx(item.icon, {}),
126
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: item.title })
127
+ ] })
128
+ }
129
+ ) }, item.title);
130
+ }) })
131
+ ] }, groupIndex)) });
132
+ }
133
+ function getInitials(name, email) {
134
+ if (name) {
135
+ const parts = name.trim().split(/\s+/);
136
+ if (parts.length >= 2) {
137
+ return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
138
+ }
139
+ return name[0].toUpperCase();
140
+ }
141
+ return email[0].toUpperCase();
142
+ }
143
+ function NavUser({ user, adapter }) {
144
+ const { isMobile } = sidebar.useSidebar();
145
+ const router = adapter.useRouter();
146
+ const initials = getInitials(user.name, user.email);
147
+ const displayName = user.name || user.email;
148
+ const handleSignOut = async () => {
149
+ if (adapter.signOut) {
150
+ await adapter.signOut({ redirect: false });
151
+ }
152
+ router.push("/auth/signin");
153
+ if (router.refresh) {
154
+ router.refresh();
155
+ }
156
+ };
157
+ return /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarMenu, { children: /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarMenuItem, { children: /* @__PURE__ */ jsxRuntime.jsxs(dropdownMenu.DropdownMenu, { children: [
158
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
159
+ sidebar.SidebarMenuButton,
160
+ {
161
+ size: "lg",
162
+ className: "data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground",
163
+ children: [
164
+ /* @__PURE__ */ jsxRuntime.jsxs(avatar.Avatar, { className: "h-8 w-8 rounded-lg", children: [
165
+ /* @__PURE__ */ jsxRuntime.jsx(avatar.AvatarImage, { src: user.image || void 0, alt: displayName }),
166
+ /* @__PURE__ */ jsxRuntime.jsx(avatar.AvatarFallback, { className: "rounded-lg", children: initials })
167
+ ] }),
168
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
169
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: displayName }),
170
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs", children: user.email })
171
+ ] }),
172
+ /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.ChevronsUpDown, { className: "ml-auto size-4" })
173
+ ]
174
+ }
175
+ ) }),
176
+ /* @__PURE__ */ jsxRuntime.jsxs(
177
+ dropdownMenu.DropdownMenuContent,
178
+ {
179
+ className: "w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg",
180
+ side: isMobile ? "bottom" : "right",
181
+ align: "end",
182
+ sideOffset: 4,
183
+ children: [
184
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuLabel, { className: "p-0 font-normal", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-1 py-1.5 text-left text-sm", children: [
185
+ /* @__PURE__ */ jsxRuntime.jsxs(avatar.Avatar, { className: "h-8 w-8 rounded-lg", children: [
186
+ /* @__PURE__ */ jsxRuntime.jsx(avatar.AvatarImage, { src: user.image || void 0, alt: displayName }),
187
+ /* @__PURE__ */ jsxRuntime.jsx(avatar.AvatarFallback, { className: "rounded-lg", children: initials })
188
+ ] }),
189
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
190
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: displayName }),
191
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs", children: user.email })
192
+ ] })
193
+ ] }) }),
194
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuSeparator, {}),
195
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuGroup, { children: /* @__PURE__ */ jsxRuntime.jsxs(dropdownMenu.DropdownMenuItem, { children: [
196
+ /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.BadgeCheck, {}),
197
+ "Account"
198
+ ] }) }),
199
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuSeparator, {}),
200
+ /* @__PURE__ */ jsxRuntime.jsxs(dropdownMenu.DropdownMenuItem, { onClick: handleSignOut, children: [
201
+ /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.LogOut, {}),
202
+ "Log out"
203
+ ] })
204
+ ]
205
+ }
206
+ )
207
+ ] }) }) });
208
+ }
209
+ function TeamSwitcher({
210
+ teams,
211
+ organizationId,
212
+ adapter
213
+ }) {
214
+ const { isMobile } = sidebar.useSidebar();
215
+ const pathname = adapter.usePathname();
216
+ const router = adapter.useRouter();
217
+ const pathSegments = pathname.split("/");
218
+ const isAppOrgRoute = pathname.startsWith("/app/") && pathSegments.length > 2 && pathSegments[2] !== "user";
219
+ const pathOrgId = isAppOrgRoute ? pathSegments[2] : null;
220
+ const currentOrgId = organizationId || (pathOrgId && teams.some((team) => team.id === pathOrgId) ? pathOrgId : null);
221
+ const activeTeam = currentOrgId ? teams.find((team) => team.id === currentOrgId) : null;
222
+ const handleTeamChange = (teamId) => {
223
+ router.push(`/app/${teamId}/home`);
224
+ if (router.refresh) {
225
+ router.refresh();
226
+ }
227
+ };
228
+ const teamsWithLogo = teams.map((org) => ({
229
+ id: org.id,
230
+ name: org.name,
231
+ logo: org.logo || LucideIcons.GalleryVerticalEnd,
232
+ plan: org.plan || "Member"
233
+ }));
234
+ if (teamsWithLogo.length === 0) {
235
+ return /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarMenu, { children: /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarMenuItem, { children: /* @__PURE__ */ jsxRuntime.jsxs(sidebar.SidebarMenuButton, { size: "lg", className: "cursor-default", children: [
236
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-muted flex aspect-square size-8 items-center justify-center rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.GalleryVerticalEnd, { className: "size-4 text-muted-foreground" }) }),
237
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
238
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium text-muted-foreground", children: "No organizations" }),
239
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs text-muted-foreground", children: "Join or create one" })
240
+ ] })
241
+ ] }) }) });
242
+ }
243
+ if (!activeTeam) {
244
+ return /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarMenu, { children: /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarMenuItem, { children: /* @__PURE__ */ jsxRuntime.jsxs(dropdownMenu.DropdownMenu, { children: [
245
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
246
+ sidebar.SidebarMenuButton,
247
+ {
248
+ size: "lg",
249
+ className: "data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground",
250
+ children: [
251
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-muted flex aspect-square size-8 items-center justify-center rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.GalleryVerticalEnd, { className: "size-4 text-muted-foreground" }) }),
252
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
253
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: "Organizations" }),
254
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "truncate text-xs text-muted-foreground", children: [
255
+ teamsWithLogo.length,
256
+ " available"
257
+ ] })
258
+ ] }),
259
+ /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.ChevronsUpDown, { className: "ml-auto" })
260
+ ]
261
+ }
262
+ ) }),
263
+ /* @__PURE__ */ jsxRuntime.jsxs(
264
+ dropdownMenu.DropdownMenuContent,
265
+ {
266
+ className: "w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg",
267
+ align: "start",
268
+ side: isMobile ? "bottom" : "right",
269
+ sideOffset: 4,
270
+ children: [
271
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuLabel, { className: "text-muted-foreground text-xs", children: "Select an organization" }),
272
+ teamsWithLogo.map((team) => /* @__PURE__ */ jsxRuntime.jsxs(
273
+ dropdownMenu.DropdownMenuItem,
274
+ {
275
+ onClick: () => handleTeamChange(team.id),
276
+ className: "gap-2 p-2",
277
+ children: [
278
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-6 items-center justify-center rounded-md border", children: /* @__PURE__ */ jsxRuntime.jsx(team.logo, { className: "size-3.5 shrink-0" }) }),
279
+ team.name
280
+ ]
281
+ },
282
+ team.id
283
+ )),
284
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuSeparator, {}),
285
+ /* @__PURE__ */ jsxRuntime.jsxs(
286
+ dropdownMenu.DropdownMenuItem,
287
+ {
288
+ className: "gap-2 p-2",
289
+ onClick: () => router.push("/app/user/organizations"),
290
+ children: [
291
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-6 items-center justify-center rounded-md border bg-transparent", children: /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.GalleryVerticalEnd, { className: "size-4" }) }),
292
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground font-medium", children: "Manage organizations" })
293
+ ]
294
+ }
295
+ )
296
+ ]
297
+ }
298
+ )
299
+ ] }) }) });
300
+ }
301
+ const activeTeamWithLogo = teamsWithLogo.find(
302
+ (team) => team.id === currentOrgId
303
+ );
304
+ if (!activeTeamWithLogo) {
305
+ return null;
306
+ }
307
+ return /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarMenu, { children: /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarMenuItem, { children: /* @__PURE__ */ jsxRuntime.jsxs(dropdownMenu.DropdownMenu, { children: [
308
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
309
+ sidebar.SidebarMenuButton,
310
+ {
311
+ size: "lg",
312
+ className: "data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground",
313
+ children: [
314
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx(activeTeamWithLogo.logo, { className: "size-4" }) }),
315
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid flex-1 text-left text-sm leading-tight", children: [
316
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: activeTeamWithLogo.name }),
317
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs", children: activeTeamWithLogo.plan })
318
+ ] }),
319
+ /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.ChevronsUpDown, { className: "ml-auto" })
320
+ ]
321
+ }
322
+ ) }),
323
+ /* @__PURE__ */ jsxRuntime.jsxs(
324
+ dropdownMenu.DropdownMenuContent,
325
+ {
326
+ className: "w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg",
327
+ align: "start",
328
+ side: isMobile ? "bottom" : "right",
329
+ sideOffset: 4,
330
+ children: [
331
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuLabel, { className: "text-muted-foreground text-xs", children: "Organizations" }),
332
+ teamsWithLogo.map((team) => /* @__PURE__ */ jsxRuntime.jsxs(
333
+ dropdownMenu.DropdownMenuItem,
334
+ {
335
+ onClick: () => handleTeamChange(team.id),
336
+ className: "gap-2 p-2",
337
+ children: [
338
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-6 items-center justify-center rounded-md border", children: /* @__PURE__ */ jsxRuntime.jsx(team.logo, { className: "size-3.5 shrink-0" }) }),
339
+ team.name,
340
+ team.id === currentOrgId && /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Check, { className: "ml-auto h-4 w-4" })
341
+ ]
342
+ },
343
+ team.id
344
+ )),
345
+ /* @__PURE__ */ jsxRuntime.jsx(dropdownMenu.DropdownMenuSeparator, {}),
346
+ /* @__PURE__ */ jsxRuntime.jsxs(
347
+ dropdownMenu.DropdownMenuItem,
348
+ {
349
+ className: "gap-2 p-2",
350
+ onClick: () => router.push("/app/user/organizations"),
351
+ children: [
352
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex size-6 items-center justify-center rounded-md border bg-transparent", children: /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.GalleryVerticalEnd, { className: "size-4" }) }),
353
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground font-medium", children: "Manage organizations" })
354
+ ]
355
+ }
356
+ )
357
+ ]
358
+ }
359
+ )
360
+ ] }) }) });
361
+ }
362
+ function useNavigation({
363
+ organizationId,
364
+ apiBaseUrl = "/api",
365
+ enabled = true
366
+ } = {}) {
367
+ const [items, setItems] = react.useState([]);
368
+ const [organizations, setOrganizations] = react.useState([]);
369
+ const [loading, setLoading] = react.useState(false);
370
+ const [error, setError] = react.useState(null);
371
+ react.useEffect(() => {
372
+ if (!enabled || !organizationId) {
373
+ setItems([]);
374
+ setOrganizations([]);
375
+ return;
376
+ }
377
+ const fetchNavigation = async () => {
378
+ setLoading(true);
379
+ setError(null);
380
+ try {
381
+ const response = await fetch(
382
+ `${apiBaseUrl}/navigation/${organizationId}`,
383
+ {
384
+ credentials: "include"
385
+ // Include cookies for auth
386
+ }
387
+ );
388
+ if (!response.ok) {
389
+ if (response.status === 401) {
390
+ throw new Error("Unauthorized");
391
+ }
392
+ if (response.status === 404) {
393
+ throw new Error("Organization not found");
394
+ }
395
+ throw new Error(`Failed to fetch navigation: ${response.statusText}`);
396
+ }
397
+ const data = await response.json();
398
+ setItems(data.items || []);
399
+ setOrganizations(data.organizations || []);
400
+ } catch (err) {
401
+ const error2 = err instanceof Error ? err : new Error("Unknown error");
402
+ setError(error2);
403
+ setItems([]);
404
+ setOrganizations([]);
405
+ } finally {
406
+ setLoading(false);
407
+ }
408
+ };
409
+ fetchNavigation();
410
+ }, [organizationId, apiBaseUrl, enabled]);
411
+ return { items, organizations, loading, error };
412
+ }
413
+ function AppSidebar({
414
+ user,
415
+ adapter,
416
+ data,
417
+ organizationId,
418
+ apiBaseUrl,
419
+ ...props
420
+ }) {
421
+ const pathname = adapter.usePathname();
422
+ const isPropsMode = data !== void 0;
423
+ const pathSegments = pathname.split("/");
424
+ const isAppOrgRoute = pathname.startsWith("/app/") && pathSegments.length > 2 && pathSegments[2] !== "user";
425
+ const pathOrgId = isAppOrgRoute ? pathSegments[2] : null;
426
+ const {
427
+ items: apiNavigationItems,
428
+ organizations: apiOrganizations,
429
+ loading: navigationLoading
430
+ } = useNavigation({
431
+ organizationId: organizationId || pathOrgId || void 0,
432
+ apiBaseUrl,
433
+ enabled: !isPropsMode
434
+ });
435
+ const organizations = isPropsMode ? data.organizations : apiOrganizations;
436
+ const baseNavigationItems = isPropsMode ? data.navigationItems : apiNavigationItems;
437
+ const currentOrgId = organizationId || (pathOrgId && organizations.some((org) => org.id === pathOrgId) ? pathOrgId : void 0);
438
+ let navigationItems = baseNavigationItems;
439
+ if (isPropsMode && currentOrgId && navigationItems.length > 0) {
440
+ navigationItems = navigationItems.map((item) => ({
441
+ ...item,
442
+ url: item.url?.replace("{organizationId}", currentOrgId),
443
+ items: item.items?.map((subItem) => ({
444
+ ...subItem,
445
+ url: subItem.url.replace("{organizationId}", currentOrgId)
446
+ }))
447
+ }));
448
+ }
449
+ const displayNavigationItems = currentOrgId ? navigationItems : [];
450
+ return /* @__PURE__ */ jsxRuntime.jsxs(sidebar.Sidebar, { collapsible: "icon", ...props, children: [
451
+ /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(
452
+ TeamSwitcher,
453
+ {
454
+ teams: organizations,
455
+ organizationId: currentOrgId || void 0,
456
+ adapter
457
+ }
458
+ ) }),
459
+ /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarContent, { children: navigationLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 text-sm text-muted-foreground", children: "Loading..." }) : /* @__PURE__ */ jsxRuntime.jsx(NavMain, { items: displayNavigationItems, adapter }) }),
460
+ /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarFooter, { children: /* @__PURE__ */ jsxRuntime.jsx(NavUser, { user, adapter }) }),
461
+ /* @__PURE__ */ jsxRuntime.jsx(sidebar.SidebarRail, {})
462
+ ] });
463
+ }
464
+
465
+ exports.AppSidebar = AppSidebar;
466
+ //# sourceMappingURL=AppSidebar.js.map
467
+ //# sourceMappingURL=AppSidebar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/iconMapper.ts","../../src/components/NavMain.tsx","../../src/components/NavUser.tsx","../../src/components/TeamSwitcher.tsx","../../src/hooks/useNavigation.ts","../../src/components/AppSidebar.tsx"],"names":["LucideIcons","SidebarGroup","SidebarGroupLabel","jsx","SidebarMenu","Collapsible","SidebarMenuItem","CollapsibleTrigger","jsxs","SidebarMenuButton","ChevronRight","CollapsibleContent","SidebarMenuSub","SidebarMenuSubItem","SidebarMenuSubButton","useSidebar","DropdownMenu","DropdownMenuTrigger","Avatar","AvatarImage","AvatarFallback","ChevronsUpDown","DropdownMenuContent","DropdownMenuLabel","DropdownMenuSeparator","DropdownMenuGroup","DropdownMenuItem","BadgeCheck","LogOut","GalleryVerticalEnd","Check","useState","useEffect","error","Sidebar","SidebarHeader","SidebarContent","SidebarFooter","SidebarRail"],"mappings":"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","file":"AppSidebar.js","sourcesContent":["/**\n * Icon mapper utility\n * Maps icon name strings to Lucide React icon components\n */\n\nimport * as LucideIcons from \"lucide-react\"\nimport type { LucideIcon } from \"lucide-react\"\n\n/**\n * Map of icon names to Lucide icon components\n * Used to convert icon name strings from API to icon components\n */\nconst ICON_MAP: Record<string, LucideIcon> = {\n Home: LucideIcons.Home,\n Users: LucideIcons.Users,\n GalleryVerticalEnd: LucideIcons.GalleryVerticalEnd,\n Settings: LucideIcons.Settings,\n CreditCard: LucideIcons.CreditCard,\n Building2: LucideIcons.Building2,\n Check: LucideIcons.Check,\n ChevronsUpDown: LucideIcons.ChevronsUpDown,\n ChevronRight: LucideIcons.ChevronRight,\n BadgeCheck: LucideIcons.BadgeCheck,\n LogOut: LucideIcons.LogOut,\n // Add more icons as needed\n}\n\n/**\n * Get icon component from icon name or component\n * \n * @param icon - Icon name (string) or icon component\n * @returns Icon component or undefined\n */\nexport function getIconComponent(\n icon?: string | LucideIcon\n): LucideIcon | undefined {\n if (!icon) {\n return undefined\n }\n\n // If it's already a component, return it\n if (typeof icon !== \"string\") {\n return icon\n }\n\n // Look up icon by name\n return ICON_MAP[icon]\n}\n\n","\"use client\"\n\nimport { ChevronRight, type LucideIcon } from \"lucide-react\"\n\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@/components/ui/collapsible\"\nimport {\n SidebarGroup,\n SidebarGroupLabel,\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n SidebarMenuSub,\n SidebarMenuSubButton,\n SidebarMenuSubItem,\n} from \"@/components/ui/sidebar\"\nimport { getIconComponent } from \"../utils/iconMapper\"\nimport type { FrameworkAdapter, NavigationItem } from \"../types\"\n\ninterface NavMainProps {\n items: NavigationItem[]\n adapter: FrameworkAdapter\n}\n\nexport function NavMain({ items, adapter }: NavMainProps) {\n const pathname = adapter.usePathname()\n const Link = adapter.Link\n\n // Split items into groups based on label items\n const groups: Array<{\n label?: { title: string; icon?: LucideIcon }\n items: Array<{\n title: string\n url: string\n icon?: LucideIcon\n isActive?: boolean\n items?: {\n title: string\n url: string\n }[]\n }>\n }> = []\n let currentGroup: {\n label?: { title: string; icon?: LucideIcon }\n items: Array<{\n title: string\n url: string\n icon?: LucideIcon\n isActive?: boolean\n items?: {\n title: string\n url: string\n }[]\n }>\n } = {\n items: [],\n }\n\n items.forEach((item) => {\n // Convert icon (string or component) to component\n const iconComponent = getIconComponent(item.icon)\n\n if (!item.url) {\n // This is a label - start a new group\n if (currentGroup.items.length > 0 || currentGroup.label) {\n groups.push(currentGroup)\n }\n currentGroup = {\n label: { title: item.title, icon: iconComponent },\n items: [],\n }\n } else {\n // This is a menu item - add to current group\n currentGroup.items.push({\n title: item.title,\n url: item.url,\n icon: iconComponent,\n isActive: item.isActive,\n items: item.items,\n })\n }\n })\n\n // Push the last group\n if (currentGroup.items.length > 0 || currentGroup.label) {\n groups.push(currentGroup)\n }\n\n return (\n <>\n {groups.map((group, groupIndex) => (\n <SidebarGroup key={groupIndex}>\n {group.label && (\n <SidebarGroupLabel>\n {group.label.icon && (\n <group.label.icon className=\"mr-2\" />\n )}\n {group.label.title}\n </SidebarGroupLabel>\n )}\n {group.items.length > 0 && (\n <SidebarMenu>\n {group.items.map((item) => {\n const isActive = pathname === item.url || item.isActive\n const hasSubItems = item.items && item.items.length > 0\n\n if (hasSubItems) {\n return (\n <Collapsible\n key={item.title}\n asChild\n defaultOpen={isActive}\n className=\"group/collapsible\"\n >\n <SidebarMenuItem>\n <CollapsibleTrigger asChild>\n <SidebarMenuButton\n tooltip={item.title}\n isActive={isActive}\n >\n {item.icon && <item.icon />}\n <span>{item.title}</span>\n <ChevronRight className=\"ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90\" />\n </SidebarMenuButton>\n </CollapsibleTrigger>\n <CollapsibleContent>\n <SidebarMenuSub>\n {item.items?.map((subItem) => (\n <SidebarMenuSubItem key={subItem.title}>\n <SidebarMenuSubButton asChild>\n <Link href={subItem.url}>\n <span>{subItem.title}</span>\n </Link>\n </SidebarMenuSubButton>\n </SidebarMenuSubItem>\n ))}\n </SidebarMenuSub>\n </CollapsibleContent>\n </SidebarMenuItem>\n </Collapsible>\n )\n }\n\n return (\n <SidebarMenuItem key={item.title}>\n <SidebarMenuButton\n asChild\n tooltip={item.title}\n isActive={isActive}\n >\n <Link href={item.url}>\n {item.icon && <item.icon />}\n <span>{item.title}</span>\n </Link>\n </SidebarMenuButton>\n </SidebarMenuItem>\n )\n })}\n </SidebarMenu>\n )}\n </SidebarGroup>\n ))}\n </>\n )\n}\n\n","\"use client\"\n\nimport {\n BadgeCheck,\n ChevronsUpDown,\n LogOut,\n} from \"lucide-react\"\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/components/ui/avatar\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/components/ui/sidebar\"\nimport type { FrameworkAdapter, User } from \"../types\"\n\nfunction getInitials(name: string | null, email: string): string {\n if (name) {\n const parts = name.trim().split(/\\s+/)\n if (parts.length >= 2) {\n return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase()\n }\n return name[0].toUpperCase()\n }\n return email[0].toUpperCase()\n}\n\ninterface NavUserProps {\n user: User\n adapter: FrameworkAdapter\n}\n\nexport function NavUser({ user, adapter }: NavUserProps) {\n const { isMobile } = useSidebar()\n const router = adapter.useRouter()\n const initials = getInitials(user.name, user.email)\n const displayName = user.name || user.email\n\n const handleSignOut = async () => {\n if (adapter.signOut) {\n await adapter.signOut({ redirect: false })\n }\n router.push(\"/auth/signin\")\n if (router.refresh) {\n router.refresh()\n }\n }\n\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <SidebarMenuButton\n size=\"lg\"\n className=\"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground\"\n >\n <Avatar className=\"h-8 w-8 rounded-lg\">\n <AvatarImage src={user.image || undefined} alt={displayName} />\n <AvatarFallback className=\"rounded-lg\">{initials}</AvatarFallback>\n </Avatar>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">{displayName}</span>\n <span className=\"truncate text-xs\">{user.email}</span>\n </div>\n <ChevronsUpDown className=\"ml-auto size-4\" />\n </SidebarMenuButton>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg\"\n side={isMobile ? \"bottom\" : \"right\"}\n align=\"end\"\n sideOffset={4}\n >\n <DropdownMenuLabel className=\"p-0 font-normal\">\n <div className=\"flex items-center gap-2 px-1 py-1.5 text-left text-sm\">\n <Avatar className=\"h-8 w-8 rounded-lg\">\n <AvatarImage src={user.image || undefined} alt={displayName} />\n <AvatarFallback className=\"rounded-lg\">{initials}</AvatarFallback>\n </Avatar>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">{displayName}</span>\n <span className=\"truncate text-xs\">{user.email}</span>\n </div>\n </div>\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <BadgeCheck />\n Account\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuItem onClick={handleSignOut}>\n <LogOut />\n Log out\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n\n","\"use client\"\n\nimport { Check, ChevronsUpDown, GalleryVerticalEnd } from \"lucide-react\"\nimport * as React from \"react\"\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\"\nimport {\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n useSidebar,\n} from \"@/components/ui/sidebar\"\nimport type { FrameworkAdapter, Organization } from \"../types\"\n\ninterface TeamSwitcherProps {\n teams: Organization[]\n organizationId?: string\n adapter: FrameworkAdapter\n}\n\nexport function TeamSwitcher({\n teams,\n organizationId,\n adapter,\n}: TeamSwitcherProps) {\n const { isMobile } = useSidebar()\n const pathname = adapter.usePathname()\n const router = adapter.useRouter()\n\n // Only extract org ID from /app/[org_id]/... paths, excluding /app/user/...\n const pathSegments = pathname.split(\"/\")\n const isAppOrgRoute =\n pathname.startsWith(\"/app/\") &&\n pathSegments.length > 2 &&\n pathSegments[2] !== \"user\"\n const pathOrgId = isAppOrgRoute ? pathSegments[2] : null\n\n // Determine current org: only from provided prop or valid path - don't auto-select\n const currentOrgId =\n organizationId ||\n (pathOrgId && teams.some((team) => team.id === pathOrgId)\n ? pathOrgId\n : null)\n\n // Find the active team based on current org ID\n const activeTeam = currentOrgId\n ? teams.find((team) => team.id === currentOrgId)\n : null\n\n const handleTeamChange = (teamId: string) => {\n // Navigate to the organization's home page\n router.push(`/app/${teamId}/home`)\n if (router.refresh) {\n router.refresh()\n }\n }\n\n // Transform organizations to teams format with default logo\n const teamsWithLogo = teams.map((org) => ({\n id: org.id,\n name: org.name,\n logo: org.logo || GalleryVerticalEnd,\n plan: org.plan || \"Member\",\n }))\n\n // No organizations state\n if (teamsWithLogo.length === 0) {\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <SidebarMenuButton size=\"lg\" className=\"cursor-default\">\n <div className=\"bg-muted flex aspect-square size-8 items-center justify-center rounded-lg\">\n <GalleryVerticalEnd className=\"size-4 text-muted-foreground\" />\n </div>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium text-muted-foreground\">\n No organizations\n </span>\n <span className=\"truncate text-xs text-muted-foreground\">\n Join or create one\n </span>\n </div>\n </SidebarMenuButton>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n }\n\n // No org selected state - prompt user to select\n if (!activeTeam) {\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <SidebarMenuButton\n size=\"lg\"\n className=\"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground\"\n >\n <div className=\"bg-muted flex aspect-square size-8 items-center justify-center rounded-lg\">\n <GalleryVerticalEnd className=\"size-4 text-muted-foreground\" />\n </div>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">Organizations</span>\n <span className=\"truncate text-xs text-muted-foreground\">\n {teamsWithLogo.length} available\n </span>\n </div>\n <ChevronsUpDown className=\"ml-auto\" />\n </SidebarMenuButton>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg\"\n align=\"start\"\n side={isMobile ? \"bottom\" : \"right\"}\n sideOffset={4}\n >\n <DropdownMenuLabel className=\"text-muted-foreground text-xs\">\n Select an organization\n </DropdownMenuLabel>\n {teamsWithLogo.map((team) => (\n <DropdownMenuItem\n key={team.id}\n onClick={() => handleTeamChange(team.id)}\n className=\"gap-2 p-2\"\n >\n <div className=\"flex size-6 items-center justify-center rounded-md border\">\n <team.logo className=\"size-3.5 shrink-0\" />\n </div>\n {team.name}\n </DropdownMenuItem>\n ))}\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"gap-2 p-2\"\n onClick={() => router.push(\"/app/user/organizations\")}\n >\n <div className=\"flex size-6 items-center justify-center rounded-md border bg-transparent\">\n <GalleryVerticalEnd className=\"size-4\" />\n </div>\n <div className=\"text-muted-foreground font-medium\">\n Manage organizations\n </div>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n }\n\n // Org selected state - show current org with switcher\n const activeTeamWithLogo = teamsWithLogo.find(\n (team) => team.id === currentOrgId\n )\n\n if (!activeTeamWithLogo) {\n return null\n }\n\n return (\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <SidebarMenuButton\n size=\"lg\"\n className=\"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground\"\n >\n <div className=\"bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-lg\">\n <activeTeamWithLogo.logo className=\"size-4\" />\n </div>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-medium\">\n {activeTeamWithLogo.name}\n </span>\n <span className=\"truncate text-xs\">{activeTeamWithLogo.plan}</span>\n </div>\n <ChevronsUpDown className=\"ml-auto\" />\n </SidebarMenuButton>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n className=\"w-(--radix-dropdown-menu-trigger-width) min-w-56 rounded-lg\"\n align=\"start\"\n side={isMobile ? \"bottom\" : \"right\"}\n sideOffset={4}\n >\n <DropdownMenuLabel className=\"text-muted-foreground text-xs\">\n Organizations\n </DropdownMenuLabel>\n {teamsWithLogo.map((team) => (\n <DropdownMenuItem\n key={team.id}\n onClick={() => handleTeamChange(team.id)}\n className=\"gap-2 p-2\"\n >\n <div className=\"flex size-6 items-center justify-center rounded-md border\">\n <team.logo className=\"size-3.5 shrink-0\" />\n </div>\n {team.name}\n {team.id === currentOrgId && (\n <Check className=\"ml-auto h-4 w-4\" />\n )}\n </DropdownMenuItem>\n ))}\n <DropdownMenuSeparator />\n <DropdownMenuItem\n className=\"gap-2 p-2\"\n onClick={() => router.push(\"/app/user/organizations\")}\n >\n <div className=\"flex size-6 items-center justify-center rounded-md border bg-transparent\">\n <GalleryVerticalEnd className=\"size-4\" />\n </div>\n <div className=\"text-muted-foreground font-medium\">\n Manage organizations\n </div>\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n )\n}\n\n","\"use client\"\n\nimport { useEffect, useState } from \"react\"\nimport type { NavigationItem, Organization } from \"../types\"\n\ninterface UseNavigationOptions {\n organizationId?: string\n apiBaseUrl?: string\n enabled?: boolean\n}\n\ninterface NavigationResponse {\n items: NavigationItem[]\n organizationId: string\n organizations?: Organization[] // Add organizations to response\n}\n\n/**\n * Hook to fetch navigation items and organizations from API\n * Falls back to empty array if API is unavailable or disabled\n * \n * @param options - Configuration options\n * @returns Navigation items, organizations, loading state, and error\n */\nexport function useNavigation({\n organizationId,\n apiBaseUrl = \"/api\",\n enabled = true,\n}: UseNavigationOptions = {}) {\n const [items, setItems] = useState<NavigationItem[]>([])\n const [organizations, setOrganizations] = useState<Organization[]>([])\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<Error | null>(null)\n\n useEffect(() => {\n if (!enabled || !organizationId) {\n setItems([])\n setOrganizations([])\n return\n }\n\n const fetchNavigation = async () => {\n setLoading(true)\n setError(null)\n\n try {\n const response = await fetch(\n `${apiBaseUrl}/navigation/${organizationId}`,\n {\n credentials: \"include\", // Include cookies for auth\n }\n )\n\n if (!response.ok) {\n if (response.status === 401) {\n throw new Error(\"Unauthorized\")\n }\n if (response.status === 404) {\n throw new Error(\"Organization not found\")\n }\n throw new Error(`Failed to fetch navigation: ${response.statusText}`)\n }\n\n const data: NavigationResponse = await response.json()\n setItems(data.items || [])\n setOrganizations(data.organizations || [])\n } catch (err) {\n const error = err instanceof Error ? err : new Error(\"Unknown error\")\n setError(error)\n setItems([]) // Fallback to empty array\n setOrganizations([]) // Fallback to empty array\n } finally {\n setLoading(false)\n }\n }\n\n fetchNavigation()\n }, [organizationId, apiBaseUrl, enabled])\n\n return { items, organizations, loading, error }\n}\n\n","\"use client\"\n\nimport * as React from \"react\"\n\nimport { NavMain } from \"./NavMain\"\nimport { NavUser } from \"./NavUser\"\nimport { TeamSwitcher } from \"./TeamSwitcher\"\nimport { useNavigation } from \"../hooks/useNavigation\"\nimport type {\n FrameworkAdapter,\n SidebarData,\n User,\n} from \"../types\"\nimport {\n Sidebar,\n SidebarContent,\n SidebarFooter,\n SidebarHeader,\n SidebarRail,\n} from \"@/components/ui/sidebar\"\n\n/**\n * Props mode: Pass data (organizations + navigationItems)\n * API mode: Omit data (fetched from API)\n */\ninterface AppSidebarProps extends React.ComponentProps<typeof Sidebar> {\n user: User\n adapter: FrameworkAdapter\n /** Sidebar data containing organizations and navigation items (props mode) */\n data?: SidebarData\n /** Current organization ID (optional, can be extracted from pathname) */\n organizationId?: string\n /** Custom API base URL (API mode only, defaults to \"/api\") */\n apiBaseUrl?: string\n}\n\nexport function AppSidebar({\n user,\n adapter,\n data,\n organizationId,\n apiBaseUrl,\n ...props\n}: AppSidebarProps) {\n const pathname = adapter.usePathname()\n\n // Determine mode: if data is provided, use props mode\n // Otherwise, use API mode\n const isPropsMode = data !== undefined\n\n // Extract org ID from path\n const pathSegments = pathname.split(\"/\")\n const isAppOrgRoute =\n pathname.startsWith(\"/app/\") &&\n pathSegments.length > 2 &&\n pathSegments[2] !== \"user\"\n const pathOrgId = isAppOrgRoute ? pathSegments[2] : null\n\n // Fetch navigation and organizations from API if in API mode\n const {\n items: apiNavigationItems,\n organizations: apiOrganizations,\n loading: navigationLoading,\n } = useNavigation({\n organizationId: organizationId || pathOrgId || undefined,\n apiBaseUrl,\n enabled: !isPropsMode,\n })\n\n // In API mode, use data from API\n // In props mode, use data from props\n const organizations = isPropsMode ? data.organizations : apiOrganizations\n const baseNavigationItems = isPropsMode ? data.navigationItems : apiNavigationItems\n\n // Determine current org: only from provided prop or valid path\n const currentOrgId: string | undefined =\n organizationId ||\n (pathOrgId && organizations.some((org) => org.id === pathOrgId)\n ? pathOrgId\n : undefined)\n\n // Replace {organizationId} placeholder in URLs when using props-based navigation\n let navigationItems = baseNavigationItems\n if (isPropsMode && currentOrgId && navigationItems.length > 0) {\n navigationItems = navigationItems.map((item) => ({\n ...item,\n url: item.url?.replace(\"{organizationId}\", currentOrgId),\n items: item.items?.map((subItem) => ({\n ...subItem,\n url: subItem.url.replace(\"{organizationId}\", currentOrgId),\n })),\n }))\n }\n\n // Only show navigation items when an organization is selected\n const displayNavigationItems = currentOrgId ? navigationItems : []\n\n return (\n <Sidebar collapsible=\"icon\" {...props}>\n <SidebarHeader>\n <TeamSwitcher\n teams={organizations}\n organizationId={currentOrgId || undefined}\n adapter={adapter}\n />\n </SidebarHeader>\n <SidebarContent>\n {navigationLoading ? (\n <div className=\"p-4 text-sm text-muted-foreground\">Loading...</div>\n ) : (\n <NavMain items={displayNavigationItems} adapter={adapter} />\n )}\n </SidebarContent>\n <SidebarFooter>\n <NavUser user={user} adapter={adapter} />\n </SidebarFooter>\n <SidebarRail />\n </Sidebar>\n )\n}\n\n"]}