next-fetch-panel 0.2.0 → 0.4.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 CHANGED
@@ -139,6 +139,55 @@ export default function RootLayout({ children }: { children: React.ReactNode })
139
139
  }
140
140
  ```
141
141
 
142
+ In sheet mode, the panel is resizable — drag the thin handle at the open edge to change its height (bottom/top sheet) or width (left/right sheet). The size is saved to `localStorage` automatically.
143
+
144
+ ---
145
+
146
+ ## Controlling the panel programmatically
147
+
148
+ Use the `useDevNetworkPanel` hook to open, close, or toggle the panel from your own components — without relying on the default floating button.
149
+
150
+ ```tsx
151
+ "use client";
152
+ import { useDevNetworkPanel } from "next-fetch-panel";
153
+
154
+ export function MyToolbar() {
155
+ const { isOpen, toggle } = useDevNetworkPanel();
156
+ return (
157
+ <button onClick={toggle}>
158
+ {isOpen ? "Hide" : "Show"} network panel
159
+ </button>
160
+ );
161
+ }
162
+ ```
163
+
164
+ The hook returns `{ isOpen, open, close, toggle }`. All four values are stable references — safe to use as event handlers without `useCallback`.
165
+
166
+ To hide the default floating button (when you're providing your own trigger), pass `showToggleButton={false}` to `<DevNetworkPanel>`:
167
+
168
+ ```tsx
169
+ <DevNetworkPanel showToggleButton={false} />
170
+ ```
171
+
172
+ ### Toggle button position
173
+
174
+ Use `buttonPosition` to place the default toggle button in any of six positions (default: `"bottom-right"`):
175
+
176
+ ```tsx
177
+ <DevNetworkPanel buttonPosition="bottom-center" />
178
+ ```
179
+
180
+ | Value | Position |
181
+ |-------|----------|
182
+ | `"bottom-right"` | Bottom-right corner *(default)* |
183
+ | `"bottom-center"` | Bottom edge, centered |
184
+ | `"bottom-left"` | Bottom-left corner |
185
+ | `"top-right"` | Top-right corner |
186
+ | `"top-center"` | Top edge, centered |
187
+ | `"top-left"` | Top-left corner |
188
+
189
+ In `fixed` panel mode, the panel container anchors to the same corner/edge as the button.
190
+
142
191
  ---
143
192
 
144
193
  ## Redacting secrets
@@ -204,6 +253,31 @@ No axios configuration change is required — `adapter: 'fetch'` is **not** need
204
253
 
205
254
  ---
206
255
 
256
+ ## Disabling per environment
257
+
258
+ Every entry point accepts an `enabled` option (or prop) that defaults to `true`. Pass `false` to make that layer a complete no-op — no patching, no cookies, no SSE stream, no panel rendered.
259
+
260
+ ```ts
261
+ // instrumentation.ts
262
+ await registerDevPanel({ enabled: process.env.NODE_ENV !== "production" });
263
+
264
+ // middleware.ts / proxy.ts
265
+ export const middleware = withDevPanel(handler, { enabled: process.env.NODE_ENV !== "production" });
266
+
267
+ // app/api/dev-network/route.ts
268
+ export const GET = createDevPanelRoute({ enabled: process.env.NODE_ENV !== "production" });
269
+
270
+ // axios client
271
+ createDevPanelAxiosInterceptors({ enabled: process.env.NODE_ENV !== "production" });
272
+
273
+ // app/layout.tsx
274
+ <DevNetworkPanel enabled={process.env.NODE_ENV !== "production"} />
275
+ ```
276
+
277
+ You can use any condition — `NODE_ENV`, a custom env var, a feature flag, or any boolean. Each entry point is independent, so you can disable just the fetch patch while keeping the panel open for other sessions, or shut everything off at once.
278
+
279
+ ---
280
+
207
281
  ## Security notes
208
282
 
209
283
  | Concern | How it is handled |
@@ -211,15 +285,15 @@ No axios configuration change is required — `adapter: 'fetch'` is **not** need
211
285
  | User A seeing User B's requests | Each browser session gets a unique `__dev_sid` cookie. The SSE stream filters strictly by session ID. |
212
286
  | Panel accessible to anyone | Use the `guard` option on `createDevPanelRoute`. |
213
287
  | Secrets leaking to the browser | Configured patterns are replaced with `[REDACTED]` before entries reach the store. |
214
- | Running in production | Add a `NODE_ENV` gate in `registerDevPanel` or behind a feature flag if needed. |
288
+ | Running in production | Pass `enabled: process.env.NODE_ENV !== "production"` to each entry point. |
215
289
 
216
290
  ---
217
291
 
218
292
  ## Public API
219
293
 
220
294
  ```ts
221
- import { DevNetworkPanel } from "next-fetch-panel";
222
- import type { LogEntry } from "next-fetch-panel";
295
+ import { DevNetworkPanel, useDevNetworkPanel } from "next-fetch-panel";
296
+ import type { LogEntry, ButtonPosition } from "next-fetch-panel";
223
297
 
224
298
  import { registerDevPanel } from "next-fetch-panel/patch";
225
299
  import { withDevPanel } from "next-fetch-panel/middleware";
package/dist/index.d.mts CHANGED
@@ -1,6 +1,17 @@
1
1
  import * as react from 'react';
2
2
 
3
- declare function DevNetworkPanel(): react.ReactPortal | null;
3
+ type ButtonPosition = "bottom-right" | "bottom-center" | "bottom-left" | "top-right" | "top-center" | "top-left";
4
+ declare function useDevNetworkPanel(): {
5
+ isOpen: boolean;
6
+ open: () => void;
7
+ close: () => void;
8
+ toggle: () => void;
9
+ };
10
+ declare function DevNetworkPanel({ enabled, showToggleButton, buttonPosition, }: {
11
+ enabled?: boolean;
12
+ showToggleButton?: boolean;
13
+ buttonPosition?: ButtonPosition;
14
+ }): react.ReactPortal | null;
4
15
 
5
16
  type LogEntry = {
6
17
  id: string;
@@ -27,4 +38,4 @@ declare global {
27
38
  var __devLogStore: DevLogStore | undefined;
28
39
  }
29
40
 
30
- export { DevNetworkPanel, type LogEntry };
41
+ export { type ButtonPosition, DevNetworkPanel, type LogEntry, useDevNetworkPanel };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,17 @@
1
1
  import * as react from 'react';
2
2
 
3
- declare function DevNetworkPanel(): react.ReactPortal | null;
3
+ type ButtonPosition = "bottom-right" | "bottom-center" | "bottom-left" | "top-right" | "top-center" | "top-left";
4
+ declare function useDevNetworkPanel(): {
5
+ isOpen: boolean;
6
+ open: () => void;
7
+ close: () => void;
8
+ toggle: () => void;
9
+ };
10
+ declare function DevNetworkPanel({ enabled, showToggleButton, buttonPosition, }: {
11
+ enabled?: boolean;
12
+ showToggleButton?: boolean;
13
+ buttonPosition?: ButtonPosition;
14
+ }): react.ReactPortal | null;
4
15
 
5
16
  type LogEntry = {
6
17
  id: string;
@@ -27,4 +38,4 @@ declare global {
27
38
  var __devLogStore: DevLogStore | undefined;
28
39
  }
29
40
 
30
- export { DevNetworkPanel, type LogEntry };
41
+ export { type ButtonPosition, DevNetworkPanel, type LogEntry, useDevNetworkPanel };