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