@logickernel/frame 0.8.0 → 0.8.2

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/dist/index.mjs CHANGED
@@ -1,11 +1,8 @@
1
- import * as React2 from 'react';
2
- import { useState, useEffect } from 'react';
3
- import Link from 'next/link';
4
- import { usePathname, useRouter } from 'next/navigation';
5
- import { signOut } from 'next-auth/react';
6
1
  import * as LucideIcons from 'lucide-react';
7
2
  import { PanelLeft, ChevronRight, Check, Circle, ChevronsUpDown, BadgeCheck, LogOut, GalleryVerticalEnd } from 'lucide-react';
8
3
  import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
4
+ import * as React2 from 'react';
5
+ import { useState, useEffect } from 'react';
9
6
  import { Slot } from '@radix-ui/react-slot';
10
7
  import { cva } from 'class-variance-authority';
11
8
  import { clsx } from 'clsx';
@@ -14,8 +11,11 @@ import * as TooltipPrimitive from '@radix-ui/react-tooltip';
14
11
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
15
12
  import * as AvatarPrimitive from '@radix-ui/react-avatar';
16
13
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
14
+ import Link from 'next/link';
15
+ import { usePathname, useRouter } from 'next/navigation';
16
+ import { signOut } from 'next-auth/react';
17
17
 
18
- // src/components/AppSidebar.tsx
18
+ // src/components/NavMain.tsx
19
19
  var Collapsible = CollapsiblePrimitive.Root;
20
20
  var CollapsibleTrigger2 = CollapsiblePrimitive.CollapsibleTrigger;
21
21
  var CollapsibleContent2 = CollapsiblePrimitive.CollapsibleContent;
@@ -54,7 +54,10 @@ function useSidebar() {
54
54
  return context;
55
55
  }
56
56
  function useIsMobile() {
57
- const [isMobile, setIsMobile] = React2.useState(false);
57
+ const [isMobile, setIsMobile] = React2.useState(() => {
58
+ if (typeof window === "undefined") return false;
59
+ return window.matchMedia("(max-width: 768px)").matches;
60
+ });
58
61
  React2.useEffect(() => {
59
62
  const mql = window.matchMedia("(max-width: 768px)");
60
63
  const onChange = () => setIsMobile(mql.matches);
@@ -76,7 +79,19 @@ var SidebarProvider = React2.forwardRef(
76
79
  }, ref) => {
77
80
  const isMobile = useIsMobile();
78
81
  const [openMobile, setOpenMobile] = React2.useState(false);
79
- const [_open, _setOpen] = React2.useState(defaultOpen);
82
+ const getInitialState = React2.useCallback(() => {
83
+ if (typeof document === "undefined") return defaultOpen;
84
+ const cookies = document.cookie.split(";");
85
+ const sidebarCookie = cookies.find(
86
+ (cookie) => cookie.trim().startsWith(`${SIDEBAR_COOKIE_NAME}=`)
87
+ );
88
+ if (sidebarCookie) {
89
+ const value = sidebarCookie.split("=")[1];
90
+ return value === "true";
91
+ }
92
+ return defaultOpen;
93
+ }, [defaultOpen]);
94
+ const [_open, _setOpen] = React2.useState(getInitialState);
80
95
  const open = openProp ?? _open;
81
96
  const setOpen = React2.useCallback(
82
97
  (value) => {
@@ -91,7 +106,11 @@ var SidebarProvider = React2.forwardRef(
91
106
  [setOpenProp, open]
92
107
  );
93
108
  const toggleSidebar = React2.useCallback(() => {
94
- return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
109
+ if (isMobile) {
110
+ setOpenMobile((open2) => !open2);
111
+ } else {
112
+ setOpen((open2) => !open2);
113
+ }
95
114
  }, [isMobile, setOpen, setOpenMobile]);
96
115
  React2.useEffect(() => {
97
116
  const handleKeyDown = (event) => {
@@ -103,6 +122,15 @@ var SidebarProvider = React2.forwardRef(
103
122
  window.addEventListener("keydown", handleKeyDown);
104
123
  return () => window.removeEventListener("keydown", handleKeyDown);
105
124
  }, [toggleSidebar]);
125
+ React2.useEffect(() => {
126
+ if (isMobile && openMobile) {
127
+ const originalStyle = window.getComputedStyle(document.body).overflow;
128
+ document.body.style.overflow = "hidden";
129
+ return () => {
130
+ document.body.style.overflow = originalStyle;
131
+ };
132
+ }
133
+ }, [isMobile, openMobile]);
106
134
  const state = open ? "expanded" : "collapsed";
107
135
  const contextValue = React2.useMemo(
108
136
  () => ({
@@ -126,7 +154,7 @@ var SidebarProvider = React2.forwardRef(
126
154
  ...style
127
155
  },
128
156
  className: cn(
129
- "group/sidebar-wrapper flex min-h-svh w-full has-[[data-variant=inset]]:bg-sidebar",
157
+ "group/sidebar-wrapper flex min-h-svh w-full bg-background has-[[data-variant=inset]]:bg-sidebar",
130
158
  className
131
159
  ),
132
160
  ref,
@@ -162,35 +190,44 @@ var Sidebar = React2.forwardRef(
162
190
  );
163
191
  }
164
192
  if (isMobile) {
165
- return /* @__PURE__ */ jsx(
166
- "div",
167
- {
168
- className: cn(
169
- "fixed inset-0 z-50 bg-black/80",
170
- openMobile ? "block" : "hidden"
171
- ),
172
- onClick: () => setOpenMobile(false),
173
- children: /* @__PURE__ */ jsx(
174
- "div",
175
- {
176
- "data-sidebar": "sidebar",
177
- "data-mobile": "true",
178
- className: cn(
179
- "fixed inset-y-0 z-50 flex h-svh w-[--sidebar-width] flex-col bg-sidebar p-2 text-sidebar-foreground",
180
- side === "left" ? "left-0 border-r" : "right-0 border-l",
181
- className
182
- ),
183
- style: {
184
- "--sidebar-width": SIDEBAR_WIDTH_MOBILE
185
- },
186
- onClick: (e) => e.stopPropagation(),
187
- ref,
188
- ...props,
189
- children
193
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
194
+ /* @__PURE__ */ jsx(
195
+ "div",
196
+ {
197
+ onClick: () => setOpenMobile(false),
198
+ "aria-hidden": "true",
199
+ style: {
200
+ position: "fixed",
201
+ inset: 0,
202
+ zIndex: 40,
203
+ backgroundColor: "rgba(0, 0, 0, 0.8)",
204
+ opacity: openMobile ? 1 : 0,
205
+ transition: "opacity 200ms",
206
+ pointerEvents: openMobile ? "auto" : "none"
190
207
  }
191
- )
192
- }
193
- );
208
+ }
209
+ ),
210
+ /* @__PURE__ */ jsx(
211
+ "div",
212
+ {
213
+ "data-sidebar": "sidebar",
214
+ "data-mobile": "true",
215
+ className: cn(
216
+ "fixed inset-y-0 z-50 flex h-svh w-[--sidebar-width] flex-col bg-sidebar p-2 text-sidebar-foreground transition-transform duration-200 ease-in-out",
217
+ side === "left" ? "left-0 border-r" : "right-0 border-l",
218
+ openMobile ? "translate-x-0" : side === "left" ? "-translate-x-full" : "translate-x-full",
219
+ className
220
+ ),
221
+ style: {
222
+ "--sidebar-width": SIDEBAR_WIDTH_MOBILE
223
+ },
224
+ onClick: (e) => e.stopPropagation(),
225
+ ref,
226
+ ...props,
227
+ children
228
+ }
229
+ )
230
+ ] });
194
231
  }
195
232
  return /* @__PURE__ */ jsxs(
196
233
  "div",
@@ -287,23 +324,24 @@ var SidebarRail = React2.forwardRef(({ className, ...props }, ref) => {
287
324
  });
288
325
  SidebarRail.displayName = "SidebarRail";
289
326
  var SidebarInset = React2.forwardRef(({ className, style, ...props }, ref) => {
290
- const { state, isMobile } = useSidebar();
291
327
  return /* @__PURE__ */ jsx(
292
- "main",
328
+ "div",
293
329
  {
294
330
  ref,
295
331
  className: cn(
296
332
  "relative flex min-h-svh flex-1 flex-col bg-background",
297
- // Auto-adjust margin based on sidebar state
298
- // Transition duration uses CSS variable for consistency
299
333
  "transition-[margin-left] duration-200 ease-linear",
334
+ // Use peer selectors to respond to sidebar state
300
335
  // On mobile, no margin needed (sidebar is overlay)
301
- // On desktop, margin-left based on sidebar state:
302
- // - Expanded: ml-64 (256px / 16rem)
303
- // - Collapsed: ml-12 (48px / 3rem)
304
- !isMobile && state === "expanded" && "md:ml-64",
305
- !isMobile && state === "collapsed" && "md:ml-12",
306
- // Keep peer-based styles for inset variant
336
+ // For default "sidebar" variant, the spacer div already creates space, so no margin needed
337
+ // Only add margin for floating/inset variants that don't have a spacer
338
+ "md:peer-data-[variant=floating]:ml-[--sidebar-width]",
339
+ "md:peer-data-[variant=floating]:peer-data-[collapsible=offcanvas]:ml-0",
340
+ "md:peer-data-[variant=floating]:peer-data-[collapsible=icon]:ml-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]",
341
+ "md:peer-data-[variant=inset]:ml-[--sidebar-width]",
342
+ "md:peer-data-[variant=inset]:peer-data-[collapsible=offcanvas]:ml-0",
343
+ "md:peer-data-[variant=inset]:peer-data-[collapsible=icon]:ml-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]",
344
+ // Inset variant specific styles
307
345
  "peer-data-[variant=inset]:min-h-[calc(100svh-theme(spacing.4))] md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow",
308
346
  className
309
347
  ),
@@ -661,7 +699,7 @@ function getIconComponent(icon) {
661
699
  }
662
700
  function NavMain({ items, adapter }) {
663
701
  const pathname = adapter.usePathname();
664
- const Link3 = adapter.Link;
702
+ const Link2 = adapter.Link;
665
703
  const groups = [];
666
704
  let currentGroup = {
667
705
  items: []
@@ -717,7 +755,7 @@ function NavMain({ items, adapter }) {
717
755
  ]
718
756
  }
719
757
  ) }),
720
- /* @__PURE__ */ jsx(CollapsibleContent2, { children: /* @__PURE__ */ jsx(SidebarMenuSub, { children: item.items?.map((subItem) => /* @__PURE__ */ jsx(SidebarMenuSubItem, { children: /* @__PURE__ */ jsx(SidebarMenuSubButton, { asChild: true, children: /* @__PURE__ */ jsx(Link3, { href: subItem.url, children: /* @__PURE__ */ jsx("span", { children: subItem.title }) }) }) }, subItem.title)) }) })
758
+ /* @__PURE__ */ jsx(CollapsibleContent2, { 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)) }) })
721
759
  ] })
722
760
  },
723
761
  item.title
@@ -729,7 +767,7 @@ function NavMain({ items, adapter }) {
729
767
  asChild: true,
730
768
  tooltip: item.title,
731
769
  isActive,
732
- children: /* @__PURE__ */ jsxs(Link3, { href: item.url, children: [
770
+ children: /* @__PURE__ */ jsxs(Link2, { href: item.url, children: [
733
771
  item.icon && /* @__PURE__ */ jsx(item.icon, {}),
734
772
  /* @__PURE__ */ jsx("span", { children: item.title })
735
773
  ] })
@@ -1165,28 +1203,24 @@ function useNavigation({
1165
1203
  }, [organizationId, apiBaseUrl, enabled]);
1166
1204
  return { items, organizations, loading, error };
1167
1205
  }
1168
- var NextJSLink = ({ href, children, className }) => /* @__PURE__ */ jsx(Link, { href, className, children });
1169
1206
  function AppSidebar({
1170
1207
  user,
1171
- adapter: externalAdapter,
1208
+ adapter,
1172
1209
  data,
1173
1210
  organizationId,
1174
1211
  apiBaseUrl,
1175
1212
  ...props
1176
1213
  }) {
1177
- const pathname = usePathname();
1178
- const nextRouter = useRouter();
1179
- const router = React2.useMemo(() => ({
1180
- push: (path) => nextRouter.push(path),
1181
- refresh: () => nextRouter.refresh()
1182
- }), [nextRouter]);
1183
- const internalAdapter = React2.useMemo(() => ({
1184
- usePathname: () => pathname,
1185
- useRouter: () => router,
1186
- Link: NextJSLink,
1187
- signOut
1188
- }), [pathname, router]);
1189
- const adapter = externalAdapter ?? internalAdapter;
1214
+ if (!adapter) {
1215
+ throw new Error(
1216
+ "AppSidebar: adapter is required. Please provide a framework adapter. For Next.js, use: const adapter = useNextJSAdapter()"
1217
+ );
1218
+ }
1219
+ if (typeof adapter.usePathname !== "function") {
1220
+ throw new Error(
1221
+ "AppSidebar: Invalid adapter provided. The adapter must have a usePathname function. Make sure you're using the correct adapter for your framework."
1222
+ );
1223
+ }
1190
1224
  const currentPathname = adapter.usePathname();
1191
1225
  const isPropsMode = data !== void 0;
1192
1226
  const pathSegments = currentPathname.split("/");
@@ -1251,26 +1285,48 @@ function AppLayout({
1251
1285
  ),
1252
1286
  /* @__PURE__ */ jsxs(SidebarInset, { children: [
1253
1287
  /* @__PURE__ */ jsx(SidebarTrigger, {}),
1254
- /* @__PURE__ */ jsx("main", { className: "flex flex-1 flex-col gap-4 p-4 md:p-6", children })
1288
+ children
1255
1289
  ] })
1256
1290
  ] });
1257
1291
  }
1258
- function createNextJSAdapter() {
1259
- const NextJSLink2 = ({ href, children, className }) => /* @__PURE__ */ jsx(Link, { href, className, children });
1260
- return {
1261
- usePathname: usePathname,
1262
- useRouter: () => {
1263
- const router = useRouter();
1292
+ function useNextJSAdapter() {
1293
+ const pathname = usePathname();
1294
+ const nextRouter = useRouter();
1295
+ const router = React2.useMemo(
1296
+ () => {
1297
+ if (!nextRouter) {
1298
+ throw new Error(
1299
+ "Next.js router is not available. Make sure you're using useNextJSAdapter in a Client Component ('use client') and that Next.js router is properly initialized."
1300
+ );
1301
+ }
1264
1302
  return {
1265
- push: (path) => router.push(path),
1266
- refresh: () => router.refresh()
1303
+ push: (path) => nextRouter.push(path),
1304
+ refresh: () => nextRouter.refresh()
1267
1305
  };
1268
1306
  },
1269
- Link: NextJSLink2,
1270
- signOut: signOut
1271
- };
1307
+ [nextRouter]
1308
+ );
1309
+ const NextJSLink = React2.useMemo(
1310
+ () => ({ href, children, className }) => /* @__PURE__ */ jsx(Link, { href, className, children }),
1311
+ []
1312
+ );
1313
+ const adapter = React2.useMemo(
1314
+ () => ({
1315
+ usePathname: () => {
1316
+ if (pathname === void 0 || pathname === null) {
1317
+ return "";
1318
+ }
1319
+ return pathname;
1320
+ },
1321
+ useRouter: () => router,
1322
+ Link: NextJSLink,
1323
+ signOut
1324
+ }),
1325
+ [pathname, router, NextJSLink]
1326
+ );
1327
+ return adapter;
1272
1328
  }
1273
1329
 
1274
- export { AppLayout, AppSidebar, NavMain, NavUser, SidebarInset, SidebarProvider, SidebarTrigger, TeamSwitcher, createNextJSAdapter, getIconComponent, useNavigation, useSidebar };
1330
+ export { AppLayout, AppSidebar, NavMain, NavUser, SidebarInset, SidebarProvider, SidebarTrigger, TeamSwitcher, getIconComponent, useNavigation, useNextJSAdapter, useSidebar };
1275
1331
  //# sourceMappingURL=index.mjs.map
1276
1332
  //# sourceMappingURL=index.mjs.map