react-dev-panel 0.2.1 → 0.2.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 +270 -68
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,130 +1,332 @@
|
|
|
1
1
|
# react-dev-panel
|
|
2
2
|
|
|
3
|
-
A
|
|
4
|
-
|
|
3
|
+
A floating, in-app **developer panel for any React project** — drop in one component and get a
|
|
4
|
+
draggable launcher with three tools:
|
|
5
5
|
|
|
6
|
-
- **Developer Logs** — live console + network capture
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
- 🐛 **Developer Logs** — live console + network capture (status, duration, GraphQL op name/type,
|
|
7
|
+
request/response bodies & headers), with source/level filters, search, "this page" scoping, and
|
|
8
|
+
expandable entries.
|
|
9
|
+
- 📊 **Page Performance** — Core Web Vitals (LCP, INP, CLS, FCP, TTFB) with ratings and fix hints.
|
|
10
|
+
- 🧩 **Component Graph Inspector** — hover any element to identify its component, lock it, browse
|
|
11
|
+
the **parent → renders → imports** tree, see **what's mounted on the current page**, and **open
|
|
12
|
+
the source file in your editor**.
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
Built on **MUI** (peer dependency) so it inherits your app's theme. Gating is a prop you control —
|
|
15
|
+
nothing renders in production unless you say so.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Table of contents
|
|
20
|
+
|
|
21
|
+
- [Requirements](#requirements)
|
|
22
|
+
- [Install](#install)
|
|
23
|
+
- [Quick start](#quick-start)
|
|
24
|
+
- [Configuration](#configuration)
|
|
25
|
+
- [Tools](#tools)
|
|
26
|
+
- [Component Graph Inspector setup](#component-graph-inspector-setup)
|
|
27
|
+
- [1. Generate the graph](#1-generate-the-graph)
|
|
28
|
+
- [2. Serve it (pick an adapter)](#2-serve-it-pick-an-adapter)
|
|
29
|
+
- [3. Wire the client](#3-wire-the-client)
|
|
30
|
+
- [Open-in-editor](#open-in-editor)
|
|
31
|
+
- [Gating & security](#gating--security)
|
|
32
|
+
- [Custom tools](#custom-tools)
|
|
33
|
+
- [Theming](#theming)
|
|
34
|
+
- [CLI reference](#cli-reference)
|
|
35
|
+
- [API reference](#api-reference)
|
|
36
|
+
- [Troubleshooting](#troubleshooting)
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Requirements
|
|
41
|
+
|
|
42
|
+
`react-dev-panel` renders inside your app's existing MUI `ThemeProvider`, so these are **peer
|
|
43
|
+
dependencies** you already have in an MUI app:
|
|
44
|
+
|
|
45
|
+
| Peer | Version |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| `react` / `react-dom` | `>=18` |
|
|
48
|
+
| `@mui/material` | `>=7` |
|
|
49
|
+
| `@emotion/react`, `@emotion/styled` | `>=11` |
|
|
50
|
+
| `react-icons` | `>=5` |
|
|
51
|
+
| `typescript` *(optional)* | `>=5` — only the graph-generator CLI uses it |
|
|
52
|
+
|
|
53
|
+
> Not using MUI? This package won't render correctly without an MUI theme in context. (A
|
|
54
|
+
> style-agnostic build is out of scope for now.)
|
|
12
55
|
|
|
13
56
|
## Install
|
|
14
57
|
|
|
15
58
|
```bash
|
|
16
59
|
npm i -D react-dev-panel
|
|
60
|
+
# or: pnpm add -D react-dev-panel / yarn add -D react-dev-panel
|
|
17
61
|
```
|
|
18
62
|
|
|
19
|
-
##
|
|
63
|
+
## Quick start
|
|
20
64
|
|
|
21
|
-
Mount
|
|
65
|
+
Mount `<DevPanel/>` **once**, near your app root, **inside your MUI `ThemeProvider`**. It renders
|
|
66
|
+
nothing in production by default.
|
|
22
67
|
|
|
23
68
|
```tsx
|
|
24
69
|
import { DevPanel } from 'react-dev-panel';
|
|
25
70
|
|
|
26
71
|
export function Providers({ children }) {
|
|
27
72
|
return (
|
|
28
|
-
|
|
73
|
+
<ThemeProvider theme={theme}>
|
|
29
74
|
{children}
|
|
30
|
-
<DevPanel
|
|
31
|
-
|
|
32
|
-
enabled={process.env.NODE_ENV !== 'production' || user?.isInternal}
|
|
33
|
-
// Current route, for tools that display it (optional).
|
|
34
|
-
getRoute={() => location.pathname}
|
|
35
|
-
/>
|
|
36
|
-
</>
|
|
75
|
+
<DevPanel enabled={process.env.NODE_ENV !== 'production'} />
|
|
76
|
+
</ThemeProvider>
|
|
37
77
|
);
|
|
38
78
|
}
|
|
39
79
|
```
|
|
40
80
|
|
|
41
|
-
|
|
81
|
+
A draggable wrench launcher appears in a corner. Open it → **Developer Logs** and **Page
|
|
82
|
+
Performance** work immediately with zero further setup.
|
|
83
|
+
|
|
84
|
+
The **Component Graph Inspector** needs a generated graph + a way to open files — see
|
|
85
|
+
[its setup section](#component-graph-inspector-setup). Until then, its hover/lock still identifies
|
|
86
|
+
components by name (from the React fiber tree); file paths and relationships light up once the
|
|
87
|
+
graph is served.
|
|
42
88
|
|
|
43
|
-
|
|
89
|
+
## Configuration
|
|
90
|
+
|
|
91
|
+
`<DevPanel/>` takes a flat config object:
|
|
44
92
|
|
|
45
93
|
| Prop | Type | Default | Purpose |
|
|
46
|
-
|
|
47
|
-
| `enabled` | `boolean` | `NODE_ENV !== 'production'` | Master gate
|
|
48
|
-
| `getRoute` | `() => string` | `location.pathname` | Current route for
|
|
49
|
-
| `openInEditor` | `(loc, editor?) => void
|
|
50
|
-
| `graphEndpoint` | `string` | — | URL serving the component
|
|
51
|
-
| `editor` | `'auto' \| 'vscode' \| 'cursor' \| 'webstorm' \| 'zed'` | `'auto'` | Preferred editor
|
|
52
|
-
| `theme` | `{ accent
|
|
53
|
-
| `tools` | `string[]` | all | Restrict/reorder tools by id
|
|
94
|
+
| --- | --- | --- | --- |
|
|
95
|
+
| `enabled` | `boolean` | `process.env.NODE_ENV !== 'production'` | Master gate. **You** own the access decision (env, internal-user role, flag). |
|
|
96
|
+
| `getRoute` | `() => string \| undefined` | `location.pathname` | Current route, for the "this page" / route displays. Wire your router (see per-framework notes). |
|
|
97
|
+
| `openInEditor` | `(loc, editor?) => void \| Promise<void \| boolean>` | protocol URL + copy | How source files open. Use `serverOpenInEditor` with an adapter for the best result. |
|
|
98
|
+
| `graphEndpoint` | `string` | — | URL serving the component-graph JSON. Use `DEFAULT_GRAPH_ENDPOINT` with an adapter. |
|
|
99
|
+
| `editor` | `'auto' \| 'vscode' \| 'cursor' \| 'webstorm' \| 'zed'` | `'auto'` | Preferred editor. `auto` lets the server detect the editor running the project. |
|
|
100
|
+
| `theme` | `{ accent?: string; accentContrast?: string }` | — | Minor accent overrides (most styling comes from your MUI theme). |
|
|
101
|
+
| `tools` | `string[]` | all | Restrict/reorder tools by id: `'logs'`, `'perf'`, `'graph'`. |
|
|
54
102
|
|
|
55
|
-
|
|
103
|
+
Example, fully wired (Next.js):
|
|
56
104
|
|
|
57
105
|
```tsx
|
|
58
|
-
|
|
106
|
+
'use client';
|
|
107
|
+
import { usePathname } from 'next/navigation';
|
|
108
|
+
import { DevPanel, serverOpenInEditor, DEFAULT_GRAPH_ENDPOINT } from 'react-dev-panel';
|
|
59
109
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
110
|
+
export function DevPanelMount() {
|
|
111
|
+
const pathname = usePathname();
|
|
112
|
+
return (
|
|
113
|
+
<DevPanel
|
|
114
|
+
enabled={process.env.NODE_ENV !== 'production'}
|
|
115
|
+
getRoute={() => pathname ?? undefined}
|
|
116
|
+
graphEndpoint={DEFAULT_GRAPH_ENDPOINT}
|
|
117
|
+
openInEditor={serverOpenInEditor}
|
|
118
|
+
tools={['graph', 'logs', 'perf']}
|
|
119
|
+
/>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
67
122
|
```
|
|
68
123
|
|
|
69
|
-
##
|
|
124
|
+
## Tools
|
|
70
125
|
|
|
71
|
-
|
|
126
|
+
| Tool | id | Setup | Notes |
|
|
127
|
+
| --- | --- | --- | --- |
|
|
128
|
+
| Developer Logs | `logs` | none | Patches `console` + `fetch`/XHR on first mount. Persists to `sessionStorage` (per tab). |
|
|
129
|
+
| Page Performance | `perf` | none | Uses `web-vitals`. INP needs an interaction before it reports. |
|
|
130
|
+
| Component Graph Inspector | `graph` | graph + endpoint | See below. Degrades gracefully without them. |
|
|
72
131
|
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
npx dev-panel-graph --scan src
|
|
76
|
-
# → .dev-panel/component-graph.json
|
|
77
|
-
```
|
|
78
|
-
2. **Serve it + enable open-in-editor** with an adapter (below).
|
|
79
|
-
3. Open the panel → **Inspect mode** → hover (highlight + tooltip), click to lock, ⌘/Ctrl+click
|
|
80
|
-
to open. Tabs: **Graph** (search + relationship tree), **Page** (what's mounted on this
|
|
81
|
-
route), **File** (source + open).
|
|
132
|
+
## Component Graph Inspector setup
|
|
82
133
|
|
|
83
|
-
|
|
84
|
-
a leaf still lands on your real app component. Open-in-editor uses the editor **running the
|
|
85
|
-
project** (`launch-editor`) — VS Code, Cursor, WebStorm, Zed, … — via the adapter endpoint.
|
|
134
|
+
Three steps: **generate** the graph, **serve** it, **wire** the client.
|
|
86
135
|
|
|
87
|
-
###
|
|
136
|
+
### 1. Generate the graph
|
|
137
|
+
|
|
138
|
+
A CLI scans your source with the TypeScript compiler and writes a JSON graph (components, files,
|
|
139
|
+
lines, and `renders` / `imports` / `route` edges):
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
npx dev-panel-graph --scan src
|
|
143
|
+
# → .dev-panel/component-graph.json
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Re-run it after adding/moving components. Common options:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
npx dev-panel-graph --scan src,packages/ui/src --out .dev-panel/graph.json --root .
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Add it to your scripts so it's easy to refresh:
|
|
153
|
+
|
|
154
|
+
```jsonc
|
|
155
|
+
// package.json
|
|
156
|
+
"scripts": {
|
|
157
|
+
"gen:dev-panel": "dev-panel-graph --scan src"
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Gitignore the output:
|
|
162
|
+
|
|
163
|
+
```gitignore
|
|
164
|
+
.dev-panel/
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### 2. Serve it (pick an adapter)
|
|
168
|
+
|
|
169
|
+
The graph JSON lives outside `public/`, so a tiny dev endpoint serves it (and opens files). Pick
|
|
170
|
+
the adapter for your stack — all three mount the same two endpoints
|
|
171
|
+
(`/dev-panel/graph`, `/dev-panel/open-file`).
|
|
172
|
+
|
|
173
|
+
**Vite** — one line; also regenerates the graph on dev start:
|
|
88
174
|
|
|
89
|
-
**Vite**
|
|
90
175
|
```ts
|
|
176
|
+
// vite.config.ts
|
|
91
177
|
import { devPanel } from 'react-dev-panel/vite';
|
|
92
|
-
|
|
178
|
+
|
|
179
|
+
export default defineConfig({
|
|
180
|
+
plugins: [react(), devPanel({ scan: ['src'] })],
|
|
181
|
+
});
|
|
93
182
|
```
|
|
94
183
|
|
|
95
|
-
**Next.js (App Router)** — gate
|
|
184
|
+
**Next.js (App Router)** — add two route files (gate them yourself; dev/internal only):
|
|
185
|
+
|
|
96
186
|
```ts
|
|
97
187
|
// app/dev-panel/graph/route.ts
|
|
98
|
-
|
|
188
|
+
import { createGraphRoute } from 'react-dev-panel/next';
|
|
189
|
+
export const dynamic = 'force-dynamic';
|
|
190
|
+
export const { GET } = createGraphRoute({
|
|
191
|
+
enabled: () => process.env.NODE_ENV !== 'production',
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
```ts
|
|
99
196
|
// app/dev-panel/open-file/route.ts
|
|
100
|
-
|
|
197
|
+
import { createOpenFileRoute } from 'react-dev-panel/next';
|
|
198
|
+
export const dynamic = 'force-dynamic';
|
|
199
|
+
export const { POST } = createOpenFileRoute({
|
|
200
|
+
enabled: () => process.env.NODE_ENV !== 'production',
|
|
201
|
+
});
|
|
101
202
|
```
|
|
102
203
|
|
|
103
|
-
|
|
204
|
+
> In a monorepo where `cwd` differs from the repo root, pass `root` / `graphFile`:
|
|
205
|
+
> `createGraphRoute({ root: path.resolve(process.cwd(), '../..'), graphFile: 'apps/web/.dev-panel/component-graph.json' })`.
|
|
206
|
+
|
|
207
|
+
**Any Node server (CRA proxy / Express / custom)** — connect-style middleware:
|
|
208
|
+
|
|
104
209
|
```ts
|
|
105
210
|
import { createDevPanelMiddleware } from 'react-dev-panel/server';
|
|
106
211
|
app.use(createDevPanelMiddleware());
|
|
107
212
|
```
|
|
108
213
|
|
|
109
|
-
|
|
214
|
+
### 3. Wire the client
|
|
215
|
+
|
|
216
|
+
Point `<DevPanel/>` at the served endpoint and the server-backed opener:
|
|
217
|
+
|
|
110
218
|
```tsx
|
|
111
219
|
import { DevPanel, serverOpenInEditor, DEFAULT_GRAPH_ENDPOINT } from 'react-dev-panel';
|
|
220
|
+
|
|
112
221
|
<DevPanel enabled={isDev} graphEndpoint={DEFAULT_GRAPH_ENDPOINT} openInEditor={serverOpenInEditor} />
|
|
113
222
|
```
|
|
114
223
|
|
|
115
|
-
|
|
116
|
-
|
|
224
|
+
That's it — open the panel, enable **Inspect mode**, hover, click to lock, and use the **Graph**,
|
|
225
|
+
**Page**, and **File** tabs.
|
|
226
|
+
|
|
227
|
+
> **No adapter / fully client-only?** Omit `graphEndpoint`. Hover still names components and the
|
|
228
|
+
> Page scan still lists them; file paths/relationships require the served graph, and open-in-editor
|
|
229
|
+
> falls back to `editor://` protocol URLs (then copy).
|
|
230
|
+
|
|
231
|
+
## Open-in-editor
|
|
232
|
+
|
|
233
|
+
The detail card has a primary **Open in editor** button plus a `force:` row (**VS Code / Cursor /
|
|
234
|
+
WebStorm**). Resolution order:
|
|
235
|
+
|
|
236
|
+
1. **Server** (`openInEditor={serverOpenInEditor}` + an adapter) → posts to `/dev-panel/open-file`,
|
|
237
|
+
which runs [`launch-editor`](https://www.npmjs.com/package/launch-editor) and opens the editor
|
|
238
|
+
**running the project** (respects `$EDITOR`). Most reliable. The `force:` buttons map to
|
|
239
|
+
`code` / `cursor` / `webstorm` CLIs — those must be on your `PATH`.
|
|
240
|
+
2. **Protocol** (default opener, no server) → `vscode://` / `cursor://` / `webstorm://` / `zed://`.
|
|
241
|
+
3. **Copy** the path to the clipboard if both fail.
|
|
242
|
+
|
|
243
|
+
`⌘/Ctrl + click` on a hovered element opens it directly.
|
|
244
|
+
|
|
245
|
+
## Gating & security
|
|
246
|
+
|
|
247
|
+
- `enabled` is the master switch and **defaults to non-production**. In production it renders
|
|
248
|
+
nothing unless you explicitly pass `enabled` truthy — gate that on an internal-user role/flag.
|
|
249
|
+
- The adapter endpoints accept an `enabled()` callback — **gate them too** (NODE_ENV and/or auth);
|
|
250
|
+
they 404 in production by default.
|
|
251
|
+
- Open-file requests are **confined to the repo root** (path-traversal guarded).
|
|
252
|
+
- The graph JSON is read from disk by the endpoint and is **not** placed under `public/`, so it's
|
|
253
|
+
never a statically served production asset. Keep `.dev-panel/` gitignored.
|
|
254
|
+
- Sensitive request headers (`authorization`, `cookie`, …) are **redacted** before logging, and
|
|
255
|
+
presigned URL signatures are collapsed.
|
|
256
|
+
|
|
257
|
+
## Custom tools
|
|
258
|
+
|
|
259
|
+
Register your own tool before mounting `<DevPanel/>`:
|
|
260
|
+
|
|
261
|
+
```tsx
|
|
262
|
+
import { registerTool } from 'react-dev-panel';
|
|
263
|
+
import { LuFlask } from 'react-icons/lu';
|
|
264
|
+
|
|
265
|
+
registerTool({
|
|
266
|
+
id: 'my-tool',
|
|
267
|
+
title: 'My Tool',
|
|
268
|
+
subtitle: 'Does a useful thing',
|
|
269
|
+
color: 'primary', // primary | info | warning | success | error
|
|
270
|
+
icon: <LuFlask size={19} />,
|
|
271
|
+
Panel: ({ onClose }) => <YourMuiPanel onClose={onClose} />,
|
|
272
|
+
// optional:
|
|
273
|
+
Overlay: MyAlwaysMountedOverlay, // self-gating layer
|
|
274
|
+
useBadge: () => ({ label: '3', tone: 'error' }), // menu-row badge
|
|
275
|
+
init: () => { /* one-time setup on mount */ },
|
|
276
|
+
});
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Restrict/reorder which tools show with the `tools` prop.
|
|
280
|
+
|
|
281
|
+
## Theming
|
|
282
|
+
|
|
283
|
+
The panel uses your app's MUI theme — colors, radius, typography all follow it automatically.
|
|
284
|
+
|
|
285
|
+
- Tweak the launcher accent via `theme={{ accent: '#6950E8' }}`.
|
|
286
|
+
- The detail chips use MUI's `soft` Chip variant. If your theme registers `soft` (e.g. the
|
|
287
|
+
Minimals template) it renders tinted; otherwise it falls back to a plain chip. No action needed.
|
|
288
|
+
|
|
289
|
+
## CLI reference
|
|
290
|
+
|
|
291
|
+
```text
|
|
292
|
+
dev-panel-graph [--root <dir>] [--scan <dir,dir>] [--out <file>]
|
|
293
|
+
|
|
294
|
+
--root repo root (default: cwd) — file paths in the graph are relative to this
|
|
295
|
+
--scan comma-separated dirs to scan (default: src)
|
|
296
|
+
--out output JSON path (default: .dev-panel/component-graph.json)
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
The Vite adapter runs this for you on dev-server start (`generateOnStart`, default `true`).
|
|
300
|
+
|
|
301
|
+
## API reference
|
|
302
|
+
|
|
303
|
+
**`react-dev-panel`**
|
|
304
|
+
- `DevPanel(config)` — the mountable component.
|
|
305
|
+
- `registerTool(def)`, `getRegisteredTools()` — custom tools.
|
|
306
|
+
- `serverOpenInEditor`, `createServerOpenInEditor(endpoint?)` — client opener that POSTs to the
|
|
307
|
+
open-file endpoint.
|
|
308
|
+
- `defaultOpenInEditor` — protocol-URL + copy opener (used when none is provided).
|
|
309
|
+
- `useDevPanelConfig()` — read the resolved config inside a custom tool.
|
|
310
|
+
- `DEFAULT_GRAPH_ENDPOINT`, `DEFAULT_OPEN_ENDPOINT` — `'/dev-panel/graph'`, `'/dev-panel/open-file'`.
|
|
311
|
+
- Types: `DevPanelConfig`, `DevPanelTheme`, `ToolDefinition`, `ToolPanelProps`, `EditorType`,
|
|
312
|
+
`SourceLocation`, `OpenInEditor`, `ComponentGraph`, `ComponentGraphNode`, `ComponentGraphEdge`.
|
|
117
313
|
|
|
118
|
-
|
|
314
|
+
**`react-dev-panel/next`** — `createGraphRoute(opts)`, `createOpenFileRoute(opts)` (+ the endpoint
|
|
315
|
+
constants and `serverOpenInEditor`).
|
|
316
|
+
**`react-dev-panel/vite`** — `devPanel(opts)` (default + named export).
|
|
317
|
+
**`react-dev-panel/server`** — `createDevPanelMiddleware(opts)`.
|
|
119
318
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
319
|
+
## Troubleshooting
|
|
320
|
+
|
|
321
|
+
| Symptom | Fix |
|
|
322
|
+
| --- | --- |
|
|
323
|
+
| Launcher doesn't appear | Check `enabled` is truthy; ensure it's mounted inside your MUI `ThemeProvider`. |
|
|
324
|
+
| Panels look unstyled / wrong colors | It must render inside an MUI `ThemeProvider`. |
|
|
325
|
+
| Graph tab says "not generated" | Run `npx dev-panel-graph`, then click **Retry graph load** (or reload). Confirm the adapter is mounted and `graphEndpoint` matches. |
|
|
326
|
+
| Hover shows `MuiButtonBaseRoot` / a host tag | You hovered a low-level/MUI element. Hover a container, or use **Graph → search** / the **Page** tab to find your app components. The resolver climbs to the nearest component that's in the graph. |
|
|
327
|
+
| "Open in editor" copies instead of opening | With an adapter: ensure the editor CLI (`code`/`cursor`/`webstorm`) is on `PATH`, or set `$EDITOR` before starting dev. Without an adapter, it relies on the OS protocol handler. |
|
|
328
|
+
| Page tab empty after navigation | Click **Rescan** — heavy/async pages mount content after the auto-scan. |
|
|
126
329
|
|
|
127
330
|
## License
|
|
128
331
|
|
|
129
332
|
MIT
|
|
130
|
-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-dev-panel",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "A framework-agnostic, self-contained floating dev panel for React: Developer Logs, Page Performance, and a Component Graph Inspector (hover-to-source, component tree, open-in-editor).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Pavan Kumar Mistry",
|