@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/README.md CHANGED
@@ -72,17 +72,30 @@ Make sure your `tsconfig.json` has the path alias configured:
72
72
 
73
73
  ### Framework Adapter
74
74
 
75
- The library is framework-agnostic and requires a framework adapter to be provided. For Next.js applications, use the provided adapter:
75
+ The library is framework-agnostic and requires a framework adapter to be provided. For Next.js applications, use the provided adapter hook:
76
76
 
77
77
  ```typescript
78
- import { AppSidebar, createNextJSAdapter } from "@logickernel/frame"
79
- import type { User, Organization } from "@logickernel/frame"
78
+ "use client" // Required: adapter hook must be used in a Client Component
80
79
 
81
- // Create the adapter (do this once, can be reused)
82
- const adapter = createNextJSAdapter()
80
+ import { AppLayout, useNextJSAdapter } from "@logickernel/frame"
81
+ import type { User, SidebarData } from "@logickernel/frame"
82
+
83
+ export default function Layout({ children }: { children: React.ReactNode }) {
84
+ // Create the adapter using the hook (must be called in a Client Component)
85
+ const adapter = useNextJSAdapter()
86
+
87
+ return (
88
+ <AppLayout adapter={adapter} user={user} data={sidebarData}>
89
+ {children}
90
+ </AppLayout>
91
+ )
92
+ }
83
93
  ```
84
94
 
85
- For other frameworks, you'll need to implement the `FrameworkAdapter` interface (see Types section).
95
+ **Important:**
96
+ - The `adapter` prop is now **required** (previously optional)
97
+ - `useNextJSAdapter()` must be called in a **Client Component** (add `"use client"` directive)
98
+ - For other frameworks, you'll need to implement the `FrameworkAdapter` interface (see Types section)
86
99
 
87
100
  ### Props Mode vs API Mode
88
101
 
@@ -96,12 +109,12 @@ The component automatically detects which mode to use:
96
109
  Pass a `data` object containing organizations and navigation items. The `{organizationId}` placeholder in URLs is automatically replaced.
97
110
 
98
111
  ```typescript
99
- import { AppSidebar, createNextJSAdapter } from "@logickernel/frame"
112
+ "use client" // Required: adapter hook must be used in a Client Component
113
+
114
+ import { AppLayout, useNextJSAdapter } from "@logickernel/frame"
100
115
  import { Home, Users, GalleryVerticalEnd } from "lucide-react"
101
116
  import type { SidebarData, User } from "@logickernel/frame"
102
117
 
103
- const adapter = createNextJSAdapter()
104
-
105
118
  const user: User = {
106
119
  name: "John Doe",
107
120
  email: "john@example.com",
@@ -121,11 +134,12 @@ const data: SidebarData = {
121
134
  }
122
135
 
123
136
  export default function Layout({ children }: { children: React.ReactNode }) {
137
+ const adapter = useNextJSAdapter()
138
+
124
139
  return (
125
- <>
126
- <AppSidebar user={user} adapter={adapter} data={data} />
127
- <main>{children}</main>
128
- </>
140
+ <AppLayout adapter={adapter} user={user} data={data}>
141
+ {children}
142
+ </AppLayout>
129
143
  )
130
144
  }
131
145
  ```
@@ -135,31 +149,24 @@ export default function Layout({ children }: { children: React.ReactNode }) {
135
149
  **Important:** Always import sidebar components (`SidebarProvider`, `SidebarTrigger`, `SidebarInset`, etc.) from `@logickernel/frame`, not from your local `@/components/ui/sidebar`. This ensures all components share the same React Context.
136
150
 
137
151
  ```typescript
152
+ "use client" // Required: adapter hook must be used in a Client Component
153
+
138
154
  import {
139
- AppSidebar,
140
- SidebarProvider,
141
- SidebarTrigger,
142
- SidebarInset,
143
- createNextJSAdapter,
155
+ AppLayout,
156
+ useNextJSAdapter,
144
157
  } from "@logickernel/frame"
145
158
  import type { User, SidebarData } from "@logickernel/frame"
146
159
 
147
- const adapter = createNextJSAdapter()
148
160
  const user: User = { name: "John Doe", email: "john@example.com", image: null }
149
161
  const data: SidebarData = { /* ... */ }
150
162
 
151
163
  export default function Layout({ children }: { children: React.ReactNode }) {
164
+ const adapter = useNextJSAdapter()
165
+
152
166
  return (
153
- <SidebarProvider>
154
- <AppSidebar user={user} adapter={adapter} data={data} />
155
- <SidebarInset>
156
- <header className="flex h-16 shrink-0 items-center gap-2 border-b px-4">
157
- <SidebarTrigger />
158
- <h1>My App</h1>
159
- </header>
160
- <main className="flex flex-1 flex-col gap-4 p-4">{children}</main>
161
- </SidebarInset>
162
- </SidebarProvider>
167
+ <AppLayout adapter={adapter} user={user} data={data}>
168
+ {children}
169
+ </AppLayout>
163
170
  )
164
171
  }
165
172
  ```
@@ -177,11 +184,12 @@ export default function Layout({ children }: { children: React.ReactNode }) {
177
184
  Omit `data` — the component fetches organizations and navigation from the API.
178
185
 
179
186
  ```typescript
180
- import { AppSidebar, createNextJSAdapter } from "@logickernel/frame"
187
+ "use client" // Required: adapter hook must be used in a Client Component
181
188
 
182
- const adapter = createNextJSAdapter()
189
+ import { AppLayout, useNextJSAdapter } from "@logickernel/frame"
183
190
 
184
191
  export default function Layout({ children }: { children: React.ReactNode }) {
192
+ const adapter = useNextJSAdapter()
185
193
  return (
186
194
  <>
187
195
  <AppSidebar
package/dist/index.d.mts CHANGED
@@ -88,8 +88,8 @@ interface FrameworkAdapter {
88
88
  */
89
89
  interface AppSidebarProps$1 {
90
90
  user: User;
91
- /** Optional adapter - if not provided, Next.js defaults will be used */
92
- adapter?: FrameworkAdapter;
91
+ /** Framework adapter - required for framework-agnostic operation */
92
+ adapter: FrameworkAdapter;
93
93
  /** Sidebar data containing organizations and navigation items (props mode) */
94
94
  data?: SidebarData;
95
95
  /** Current organization ID (optional, can be extracted from pathname) */
@@ -103,8 +103,8 @@ interface AppSidebarProps$1 {
103
103
  interface AppLayoutProps {
104
104
  /** User data for sidebar */
105
105
  user: User;
106
- /** Optional adapter - if not provided, Next.js defaults will be used */
107
- adapter?: FrameworkAdapter;
106
+ /** Framework adapter - required for framework-agnostic operation */
107
+ adapter: FrameworkAdapter;
108
108
  /** Sidebar data containing organizations and navigation items (props mode) */
109
109
  data?: SidebarData;
110
110
  /** Current organization ID (optional, can be extracted from pathname) */
@@ -145,8 +145,8 @@ declare const SidebarInset: React$1.ForwardRefExoticComponent<Omit<React$1.Detai
145
145
  */
146
146
  interface AppSidebarProps extends React$1.ComponentProps<typeof Sidebar> {
147
147
  user: User;
148
- /** Optional adapter - if not provided, Next.js defaults will be used */
149
- adapter?: FrameworkAdapter;
148
+ /** Framework adapter - required for framework-agnostic operation */
149
+ adapter: FrameworkAdapter;
150
150
  /** Sidebar data containing organizations and navigation items (props mode) */
151
151
  data?: SidebarData;
152
152
  /** Current organization ID (optional, can be extracted from pathname) */
@@ -154,7 +154,7 @@ interface AppSidebarProps extends React$1.ComponentProps<typeof Sidebar> {
154
154
  /** Custom API base URL (API mode only, defaults to "/api") */
155
155
  apiBaseUrl?: string;
156
156
  }
157
- declare function AppSidebar({ user, adapter: externalAdapter, data, organizationId, apiBaseUrl, ...props }: AppSidebarProps): react_jsx_runtime.JSX.Element;
157
+ declare function AppSidebar({ user, adapter, data, organizationId, apiBaseUrl, ...props }: AppSidebarProps): react_jsx_runtime.JSX.Element;
158
158
 
159
159
  /**
160
160
  * High-level layout component that handles the entire sidebar + content layout structure.
@@ -168,20 +168,36 @@ declare function AppSidebar({ user, adapter: externalAdapter, data, organization
168
168
  *
169
169
  * @example
170
170
  * ```tsx
171
- * // API mode (no data prop)
172
- * <AppLayout
173
- * user={user}
174
- * >
175
- * {children}
176
- * </AppLayout>
171
+ * // In Next.js
172
+ * import { useNextJSAdapter } from "@logickernel/frame"
173
+ *
174
+ * function Layout({ children }) {
175
+ * const adapter = useNextJSAdapter()
176
+ * return (
177
+ * <AppLayout adapter={adapter} user={user} data={sidebarData}>
178
+ * {children}
179
+ * </AppLayout>
180
+ * )
181
+ * }
177
182
  *
178
- * // Props mode (with data prop)
179
- * <AppLayout
180
- * user={user}
181
- * data={{ organizations: [...], navigationItems: [...] }}
182
- * >
183
- * {children}
184
- * </AppLayout>
183
+ * // In React Router
184
+ * import { useLocation, useNavigate } from "react-router-dom"
185
+ *
186
+ * function Layout({ children }) {
187
+ * const location = useLocation()
188
+ * const navigate = useNavigate()
189
+ * const adapter = useMemo(() => ({
190
+ * usePathname: () => location.pathname,
191
+ * useRouter: () => ({ push: navigate }),
192
+ * Link: ({ href, children }) => <Link to={href}>{children}</Link>,
193
+ * }), [location.pathname, navigate])
194
+ *
195
+ * return (
196
+ * <AppLayout adapter={adapter} user={user} data={sidebarData}>
197
+ * {children}
198
+ * </AppLayout>
199
+ * )
200
+ * }
185
201
  * ```
186
202
  */
187
203
  declare function AppLayout({ user, adapter, data, organizationId, apiBaseUrl, children, }: AppLayoutProps): react_jsx_runtime.JSX.Element;
@@ -238,16 +254,24 @@ declare function useNavigation({ organizationId, apiBaseUrl, enabled, }?: UseNav
238
254
  declare function getIconComponent(icon?: string | LucideIcon): LucideIcon | undefined;
239
255
 
240
256
  /**
241
- * Next.js adapter for @logickernel/frame
242
- * Provides Next.js-specific implementations of FrameworkAdapter
243
- */
244
-
245
- /**
246
- * Creates a Next.js adapter for the framework
257
+ * Creates a Next.js adapter hook for the framework
247
258
  * Use this when using @logickernel/frame in a Next.js application
248
259
  *
249
260
  * Note: This requires Next.js and next-auth to be installed
261
+ * This hook MUST be called in a Client Component ("use client")
262
+ *
263
+ * @example
264
+ * ```tsx
265
+ * "use client"
266
+ *
267
+ * import { AppLayout, useNextJSAdapter } from "@logickernel/frame"
268
+ *
269
+ * function MyLayout({ children }) {
270
+ * const adapter = useNextJSAdapter()
271
+ * return <AppLayout adapter={adapter} user={user}>{children}</AppLayout>
272
+ * }
273
+ * ```
250
274
  */
251
- declare function createNextJSAdapter(): FrameworkAdapter;
275
+ declare function useNextJSAdapter(): FrameworkAdapter;
252
276
 
253
- export { AppLayout, type AppLayoutProps, AppSidebar, type AppSidebarProps$1 as AppSidebarProps, type FrameworkAdapter, type LinkProps, NavMain, NavUser, type NavigationConfig, type NavigationItem, type Organization, type Router, type SidebarData, SidebarInset, SidebarProvider, SidebarTrigger, TeamSwitcher, type User, createNextJSAdapter, getIconComponent, useNavigation, useSidebar };
277
+ export { AppLayout, type AppLayoutProps, AppSidebar, type AppSidebarProps$1 as AppSidebarProps, type FrameworkAdapter, type LinkProps, NavMain, NavUser, type NavigationConfig, type NavigationItem, type Organization, type Router, type SidebarData, SidebarInset, SidebarProvider, SidebarTrigger, TeamSwitcher, type User, getIconComponent, useNavigation, useNextJSAdapter, useSidebar };
package/dist/index.d.ts CHANGED
@@ -88,8 +88,8 @@ interface FrameworkAdapter {
88
88
  */
89
89
  interface AppSidebarProps$1 {
90
90
  user: User;
91
- /** Optional adapter - if not provided, Next.js defaults will be used */
92
- adapter?: FrameworkAdapter;
91
+ /** Framework adapter - required for framework-agnostic operation */
92
+ adapter: FrameworkAdapter;
93
93
  /** Sidebar data containing organizations and navigation items (props mode) */
94
94
  data?: SidebarData;
95
95
  /** Current organization ID (optional, can be extracted from pathname) */
@@ -103,8 +103,8 @@ interface AppSidebarProps$1 {
103
103
  interface AppLayoutProps {
104
104
  /** User data for sidebar */
105
105
  user: User;
106
- /** Optional adapter - if not provided, Next.js defaults will be used */
107
- adapter?: FrameworkAdapter;
106
+ /** Framework adapter - required for framework-agnostic operation */
107
+ adapter: FrameworkAdapter;
108
108
  /** Sidebar data containing organizations and navigation items (props mode) */
109
109
  data?: SidebarData;
110
110
  /** Current organization ID (optional, can be extracted from pathname) */
@@ -145,8 +145,8 @@ declare const SidebarInset: React$1.ForwardRefExoticComponent<Omit<React$1.Detai
145
145
  */
146
146
  interface AppSidebarProps extends React$1.ComponentProps<typeof Sidebar> {
147
147
  user: User;
148
- /** Optional adapter - if not provided, Next.js defaults will be used */
149
- adapter?: FrameworkAdapter;
148
+ /** Framework adapter - required for framework-agnostic operation */
149
+ adapter: FrameworkAdapter;
150
150
  /** Sidebar data containing organizations and navigation items (props mode) */
151
151
  data?: SidebarData;
152
152
  /** Current organization ID (optional, can be extracted from pathname) */
@@ -154,7 +154,7 @@ interface AppSidebarProps extends React$1.ComponentProps<typeof Sidebar> {
154
154
  /** Custom API base URL (API mode only, defaults to "/api") */
155
155
  apiBaseUrl?: string;
156
156
  }
157
- declare function AppSidebar({ user, adapter: externalAdapter, data, organizationId, apiBaseUrl, ...props }: AppSidebarProps): react_jsx_runtime.JSX.Element;
157
+ declare function AppSidebar({ user, adapter, data, organizationId, apiBaseUrl, ...props }: AppSidebarProps): react_jsx_runtime.JSX.Element;
158
158
 
159
159
  /**
160
160
  * High-level layout component that handles the entire sidebar + content layout structure.
@@ -168,20 +168,36 @@ declare function AppSidebar({ user, adapter: externalAdapter, data, organization
168
168
  *
169
169
  * @example
170
170
  * ```tsx
171
- * // API mode (no data prop)
172
- * <AppLayout
173
- * user={user}
174
- * >
175
- * {children}
176
- * </AppLayout>
171
+ * // In Next.js
172
+ * import { useNextJSAdapter } from "@logickernel/frame"
173
+ *
174
+ * function Layout({ children }) {
175
+ * const adapter = useNextJSAdapter()
176
+ * return (
177
+ * <AppLayout adapter={adapter} user={user} data={sidebarData}>
178
+ * {children}
179
+ * </AppLayout>
180
+ * )
181
+ * }
177
182
  *
178
- * // Props mode (with data prop)
179
- * <AppLayout
180
- * user={user}
181
- * data={{ organizations: [...], navigationItems: [...] }}
182
- * >
183
- * {children}
184
- * </AppLayout>
183
+ * // In React Router
184
+ * import { useLocation, useNavigate } from "react-router-dom"
185
+ *
186
+ * function Layout({ children }) {
187
+ * const location = useLocation()
188
+ * const navigate = useNavigate()
189
+ * const adapter = useMemo(() => ({
190
+ * usePathname: () => location.pathname,
191
+ * useRouter: () => ({ push: navigate }),
192
+ * Link: ({ href, children }) => <Link to={href}>{children}</Link>,
193
+ * }), [location.pathname, navigate])
194
+ *
195
+ * return (
196
+ * <AppLayout adapter={adapter} user={user} data={sidebarData}>
197
+ * {children}
198
+ * </AppLayout>
199
+ * )
200
+ * }
185
201
  * ```
186
202
  */
187
203
  declare function AppLayout({ user, adapter, data, organizationId, apiBaseUrl, children, }: AppLayoutProps): react_jsx_runtime.JSX.Element;
@@ -238,16 +254,24 @@ declare function useNavigation({ organizationId, apiBaseUrl, enabled, }?: UseNav
238
254
  declare function getIconComponent(icon?: string | LucideIcon): LucideIcon | undefined;
239
255
 
240
256
  /**
241
- * Next.js adapter for @logickernel/frame
242
- * Provides Next.js-specific implementations of FrameworkAdapter
243
- */
244
-
245
- /**
246
- * Creates a Next.js adapter for the framework
257
+ * Creates a Next.js adapter hook for the framework
247
258
  * Use this when using @logickernel/frame in a Next.js application
248
259
  *
249
260
  * Note: This requires Next.js and next-auth to be installed
261
+ * This hook MUST be called in a Client Component ("use client")
262
+ *
263
+ * @example
264
+ * ```tsx
265
+ * "use client"
266
+ *
267
+ * import { AppLayout, useNextJSAdapter } from "@logickernel/frame"
268
+ *
269
+ * function MyLayout({ children }) {
270
+ * const adapter = useNextJSAdapter()
271
+ * return <AppLayout adapter={adapter} user={user}>{children}</AppLayout>
272
+ * }
273
+ * ```
250
274
  */
251
- declare function createNextJSAdapter(): FrameworkAdapter;
275
+ declare function useNextJSAdapter(): FrameworkAdapter;
252
276
 
253
- export { AppLayout, type AppLayoutProps, AppSidebar, type AppSidebarProps$1 as AppSidebarProps, type FrameworkAdapter, type LinkProps, NavMain, NavUser, type NavigationConfig, type NavigationItem, type Organization, type Router, type SidebarData, SidebarInset, SidebarProvider, SidebarTrigger, TeamSwitcher, type User, createNextJSAdapter, getIconComponent, useNavigation, useSidebar };
277
+ export { AppLayout, type AppLayoutProps, AppSidebar, type AppSidebarProps$1 as AppSidebarProps, type FrameworkAdapter, type LinkProps, NavMain, NavUser, type NavigationConfig, type NavigationItem, type Organization, type Router, type SidebarData, SidebarInset, SidebarProvider, SidebarTrigger, TeamSwitcher, type User, getIconComponent, useNavigation, useNextJSAdapter, useSidebar };