react-dev-panel 0.1.0 → 0.2.1

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.js CHANGED
@@ -1,375 +1,785 @@
1
1
  export { DEFAULT_GRAPH_ENDPOINT, DEFAULT_OPEN_ENDPOINT, createServerOpenInEditor, serverOpenInEditor } from './chunk-2ZAPVMUL.js';
2
- import { createContext, useContext, useEffect, useMemo, useState, useSyncExternalStore, useCallback, useRef } from 'react';
2
+ import Box6 from '@mui/material/Box';
3
+ import Chip from '@mui/material/Chip';
4
+ import Stack from '@mui/material/Stack';
5
+ import Tooltip2 from '@mui/material/Tooltip';
6
+ import Collapse from '@mui/material/Collapse';
7
+ import TextField from '@mui/material/TextField';
8
+ import Typography3 from '@mui/material/Typography';
9
+ import IconButton from '@mui/material/IconButton';
10
+ import ToggleButton from '@mui/material/ToggleButton';
11
+ import { useTheme, alpha } from '@mui/material/styles';
12
+ import InputAdornment from '@mui/material/InputAdornment';
13
+ import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
14
+ import { createContext, useContext, useMemo, useState, useEffect, useSyncExternalStore, useCallback, useRef } from 'react';
15
+ import { LuBug, LuTrash2, LuX, LuSearch, LuGauge, LuWorkflow, LuWrench, LuChevronRight, LuChevronDown, LuFileCode, LuLink, LuClipboardCopy, LuCopy, LuMousePointerClick, LuLayers, LuFile, LuArrowUp, LuRefreshCw, LuCheck } from 'react-icons/lu';
3
16
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
17
  import { onLCP, onCLS, onINP, onFCP, onTTFB } from 'web-vitals';
18
+ import Switch from '@mui/material/Switch';
19
+ import Divider from '@mui/material/Divider';
20
+ import Button from '@mui/material/Button';
21
+ import Fab from '@mui/material/Fab';
22
+ import Menu from '@mui/material/Menu';
23
+ import MenuItem from '@mui/material/MenuItem';
5
24
 
6
- // src/core/styles.ts
7
- var RDP_STYLE_ID = "react-dev-panel-styles";
8
- var RDP_Z = 2147483e3;
9
- var CSS = `
10
- .rdp-root, .rdp-root * { box-sizing: border-box; }
11
- .rdp-root {
12
- --rdp-bg: #11161d;
13
- --rdp-bg-elev: #1a212b;
14
- --rdp-bg-soft: rgba(148,163,184,0.06);
15
- --rdp-border: rgba(255,255,255,0.09);
16
- --rdp-text: #e6e9ee;
17
- --rdp-text-dim: #9aa4b2;
18
- --rdp-text-faint: #6b7585;
19
- --rdp-accent: #6950E8;
20
- --rdp-accent-contrast: #ffffff;
21
- --rdp-success: #3ddc84;
22
- --rdp-warning: #e0a82e;
23
- --rdp-error: #e5575c;
24
- --rdp-info: #56a6e8;
25
- --rdp-radius: 10px;
26
- --rdp-shadow: 0 8px 28px rgba(0,0,0,0.5);
27
- --rdp-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
28
- --rdp-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
29
- color: var(--rdp-text);
30
- font-family: var(--rdp-sans);
31
- font-size: 13px;
32
- line-height: 1.4;
25
+ // src/core/registry.ts
26
+ var tools = /* @__PURE__ */ new Map();
27
+ function registerTool(def) {
28
+ tools.set(def.id, def);
33
29
  }
34
-
35
- /* Launcher FAB */
36
- .rdp-fab {
37
- position: fixed; width: 52px; height: 52px; border-radius: 50%;
38
- display: grid; place-items: center; cursor: grab; border: none;
39
- color: var(--rdp-accent-contrast);
40
- background: linear-gradient(135deg, var(--rdp-accent), #4a36b8);
41
- box-shadow: 0 4px 12px rgba(105,80,232,0.35), 0 8px 24px rgba(0,0,0,0.5);
42
- z-index: ${RDP_Z};
43
- }
44
- .rdp-fab:active { cursor: grabbing; }
45
- .rdp-fab-badge {
46
- position: absolute; bottom: -3px; right: -3px; min-width: 18px; height: 18px;
47
- padding: 0 5px; border-radius: 999px; background: var(--rdp-error); color: #fff;
48
- font-size: 10px; font-weight: 700; display: grid; place-items: center;
49
- border: 2px solid var(--rdp-bg);
30
+ function getRegisteredTools() {
31
+ return [...tools.values()];
50
32
  }
51
-
52
- /* Floating surfaces */
53
- .rdp-surface {
54
- position: fixed; background: var(--rdp-bg); border: 1px solid var(--rdp-border);
55
- border-radius: var(--rdp-radius); box-shadow: var(--rdp-shadow); overflow: hidden;
56
- display: flex; flex-direction: column; z-index: ${RDP_Z};
57
- }
58
- .rdp-menu { width: 320px; }
59
- .rdp-panel { width: min(460px, calc(100vw - 32px)); max-height: min(78vh, 720px); }
60
-
61
- .rdp-header {
62
- display: flex; align-items: center; gap: 10px; padding: 10px 14px;
63
- border-bottom: 1px solid var(--rdp-border); flex-shrink: 0;
33
+ function resolveTools(ids) {
34
+ if (!ids || ids.length === 0) return getRegisteredTools();
35
+ return ids.map((id) => tools.get(id)).filter((t) => Boolean(t));
64
36
  }
65
- .rdp-menu-head {
66
- background: linear-gradient(135deg, rgba(105,80,232,0.18), rgba(105,80,232,0.04));
37
+ function buildProtocolUrl(editor, loc) {
38
+ const line = loc.line ?? 1;
39
+ const col = loc.column ?? 1;
40
+ switch (editor) {
41
+ case "cursor":
42
+ return `cursor://file/${loc.file}:${line}:${col}`;
43
+ case "webstorm":
44
+ return `webstorm://open?file=${encodeURIComponent(loc.file)}&line=${line}&column=${col}`;
45
+ case "zed":
46
+ return `zed://file/${loc.file}:${line}:${col}`;
47
+ case "vscode":
48
+ case "auto":
49
+ default:
50
+ return `vscode://file/${loc.file}:${line}:${col}`;
51
+ }
67
52
  }
68
- .rdp-title { font-weight: 700; font-size: 13px; }
69
- .rdp-sub { color: var(--rdp-text-dim); font-size: 12px; }
70
- .rdp-body { flex: 1; overflow-y: auto; padding: 12px; }
71
-
72
- /* Menu rows */
73
- .rdp-row {
74
- display: flex; align-items: flex-start; gap: 12px; padding: 10px 12px;
75
- border-radius: 8px; cursor: pointer; width: 100%; text-align: left; border: none;
76
- background: transparent; color: inherit; font: inherit;
53
+ var defaultOpenInEditor = async (loc, editor = "auto") => {
54
+ const url = buildProtocolUrl(editor, loc);
55
+ if (url && typeof window !== "undefined") {
56
+ try {
57
+ window.location.assign(url);
58
+ return true;
59
+ } catch {
60
+ }
61
+ }
62
+ if (typeof navigator !== "undefined" && navigator.clipboard) {
63
+ await navigator.clipboard.writeText(`${loc.file}${loc.line ? `:${loc.line}` : ""}`).catch(() => void 0);
64
+ }
65
+ return false;
66
+ };
67
+ var DevPanelContext = createContext(null);
68
+ function resolve(config) {
69
+ const enabled = config.enabled ?? (typeof process !== "undefined" ? process.env.NODE_ENV !== "production" : true);
70
+ return {
71
+ enabled,
72
+ editor: config.editor ?? "auto",
73
+ getRoute: config.getRoute ?? (() => typeof location !== "undefined" ? location.pathname : void 0),
74
+ openInEditor: config.openInEditor ?? defaultOpenInEditor,
75
+ graphEndpoint: config.graphEndpoint,
76
+ theme: config.theme ?? {},
77
+ tools: config.tools
78
+ };
77
79
  }
78
- .rdp-row:hover { background: rgba(255,255,255,0.05); }
79
- .rdp-tile {
80
- width: 38px; height: 38px; flex-shrink: 0; border-radius: 9px;
81
- display: grid; place-items: center;
80
+ function DevPanelConfigProvider({
81
+ config,
82
+ children
83
+ }) {
84
+ const value = useMemo(() => resolve(config), [config]);
85
+ return /* @__PURE__ */ jsx(DevPanelContext.Provider, { value, children });
82
86
  }
83
-
84
- /* Primitives */
85
- .rdp-chip {
86
- display: inline-flex; align-items: center; height: 18px; padding: 0 7px;
87
- border-radius: 999px; font-size: 11px; font-weight: 700; line-height: 1;
88
- }
89
- .rdp-btn {
90
- display: inline-flex; align-items: center; gap: 6px; padding: 5px 10px;
91
- border-radius: 8px; border: 1px solid var(--rdp-border); background: transparent;
92
- color: var(--rdp-text); font: inherit; font-size: 12px; cursor: pointer;
93
- }
94
- .rdp-btn:hover { background: rgba(255,255,255,0.05); }
95
- .rdp-btn-primary {
96
- background: var(--rdp-accent); color: var(--rdp-accent-contrast); border-color: transparent;
97
- font-weight: 600; justify-content: center; width: 100%;
98
- }
99
- .rdp-btn-primary:hover { filter: brightness(1.08); }
100
- .rdp-btn-sm { padding: 2px 7px; font-size: 11px; border-radius: 6px; }
101
- .rdp-iconbtn {
102
- display: grid; place-items: center; width: 28px; height: 28px; border-radius: 7px;
103
- border: 1px solid var(--rdp-border); background: transparent; color: var(--rdp-text);
104
- cursor: pointer;
105
- }
106
- .rdp-iconbtn:hover { background: rgba(255,255,255,0.06); }
107
- .rdp-iconbtn-bare { border: none; width: 22px; height: 22px; color: var(--rdp-text-dim); }
108
- .rdp-iconbtn-bare:hover { color: var(--rdp-text); background: rgba(255,255,255,0.06); }
109
-
110
- .rdp-tabs { display: flex; gap: 4px; background: var(--rdp-bg-soft); padding: 3px; border-radius: 9px; }
111
- .rdp-tab {
112
- flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 5px;
113
- padding: 6px 4px; border-radius: 7px; border: none; background: transparent;
114
- color: var(--rdp-text-dim); font: inherit; font-size: 12px; cursor: pointer;
87
+ function useDevPanelConfig() {
88
+ const ctx = useContext(DevPanelContext);
89
+ if (!ctx) throw new Error("useDevPanelConfig must be used within <DevPanel> / DevPanelConfigProvider");
90
+ return ctx;
115
91
  }
116
- .rdp-tab[aria-selected="true"] { background: var(--rdp-bg-elev); color: var(--rdp-text); box-shadow: 0 1px 2px rgba(0,0,0,0.3); }
117
92
 
118
- .rdp-input {
119
- display: flex; align-items: center; gap: 8px; padding: 6px 10px; border-radius: 9px;
120
- border: 1px solid var(--rdp-border); background: var(--rdp-bg-soft);
93
+ // src/tools/dev-logs/store.ts
94
+ var MAX_ENTRIES = 500;
95
+ var STORAGE_KEY = "react-dev-panel:dev-logs";
96
+ var entries = [];
97
+ var seq = 0;
98
+ var installed = false;
99
+ var hydrated = false;
100
+ var emitScheduled = false;
101
+ var persistTimer = null;
102
+ var listeners = /* @__PURE__ */ new Set();
103
+ var EMPTY = [];
104
+ function emit() {
105
+ if (emitScheduled) return;
106
+ emitScheduled = true;
107
+ const flush = () => {
108
+ emitScheduled = false;
109
+ listeners.forEach((listener) => listener());
110
+ };
111
+ if (typeof queueMicrotask === "function") queueMicrotask(flush);
112
+ else void Promise.resolve().then(flush);
121
113
  }
122
- .rdp-input input {
123
- flex: 1; background: transparent; border: none; outline: none; color: var(--rdp-text);
124
- font: inherit; font-size: 13px;
114
+ function persist() {
115
+ if (typeof window === "undefined") return;
116
+ let list = entries;
117
+ for (let attempt = 0; attempt < 6; attempt += 1) {
118
+ try {
119
+ window.sessionStorage.setItem(STORAGE_KEY, JSON.stringify(list));
120
+ return;
121
+ } catch {
122
+ if (!list.length) return;
123
+ list = list.slice(0, Math.floor(list.length / 2));
124
+ }
125
+ }
125
126
  }
126
- .rdp-mono { font-family: var(--rdp-mono); }
127
- .rdp-section-label {
128
- display: block; margin: 8px 0 2px; color: var(--rdp-text-faint); font-weight: 700;
129
- text-transform: uppercase; letter-spacing: 0.5px; font-size: 10px;
127
+ function schedulePersist() {
128
+ if (typeof window === "undefined" || persistTimer) return;
129
+ persistTimer = setTimeout(() => {
130
+ persistTimer = null;
131
+ persist();
132
+ }, 500);
130
133
  }
131
-
132
- /* Inspector overlay bits */
133
- .rdp-overlay { position: fixed; inset: 0; pointer-events: none; z-index: ${RDP_Z - 1}; }
134
- .rdp-hl {
135
- position: fixed; border: 1px solid var(--rdp-accent); border-radius: 3px;
136
- background: rgba(105,80,232,0.14); box-shadow: 0 0 0 1px rgba(105,80,232,0.4);
137
- transition: all 60ms linear; pointer-events: none;
138
- }
139
- .rdp-tooltip {
140
- position: fixed; max-width: 360px; padding: 8px 10px; border-radius: 9px;
141
- background: rgba(15,18,24,0.86); backdrop-filter: blur(8px);
142
- border: 1px solid rgba(255,255,255,0.12); box-shadow: var(--rdp-shadow); color: #fff;
143
- pointer-events: none;
144
- }
145
- .rdp-toast {
146
- position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%);
147
- padding: 7px 14px; border-radius: 9px; background: rgba(15,18,24,0.92);
148
- border: 1px solid rgba(255,255,255,0.12); box-shadow: var(--rdp-shadow);
149
- font-size: 12px; font-weight: 600; z-index: ${RDP_Z};
134
+ function hydrate() {
135
+ if (hydrated || typeof window === "undefined") return;
136
+ hydrated = true;
137
+ try {
138
+ const raw = window.sessionStorage.getItem(STORAGE_KEY);
139
+ if (!raw) return;
140
+ const parsed = JSON.parse(raw);
141
+ if (!Array.isArray(parsed)) return;
142
+ entries = parsed.slice(0, MAX_ENTRIES);
143
+ seq = entries.reduce((max, entry) => {
144
+ const n = Number(String(entry.id).replace("log-", ""));
145
+ return Number.isFinite(n) && n > max ? n : max;
146
+ }, 0);
147
+ emit();
148
+ } catch {
149
+ }
150
150
  }
151
-
152
- .rdp-body::-webkit-scrollbar, .rdp-scroll::-webkit-scrollbar { width: 8px; height: 8px; }
153
- .rdp-body::-webkit-scrollbar-thumb, .rdp-scroll::-webkit-scrollbar-thumb {
154
- background: rgba(255,255,255,0.14); border-radius: 8px;
155
- }
156
- .rdp-kbd {
157
- padding: 1px 5px; border-radius: 5px; border: 1px solid var(--rdp-border);
158
- background: rgba(255,255,255,0.04); font-family: var(--rdp-mono); font-size: 11px;
159
- color: var(--rdp-text-dim);
160
- }
161
- `;
162
- var injected = false;
163
- function injectBaseStyles() {
164
- if (injected || typeof document === "undefined") return;
165
- if (document.getElementById(RDP_STYLE_ID)) {
166
- injected = true;
167
- return;
151
+ function getDevLogs() {
152
+ return entries;
153
+ }
154
+ function getDevLogsServerSnapshot() {
155
+ return EMPTY;
156
+ }
157
+ function subscribeDevLogs(listener) {
158
+ listeners.add(listener);
159
+ return () => listeners.delete(listener);
160
+ }
161
+ function clearDevLogs() {
162
+ entries = [];
163
+ if (persistTimer) {
164
+ clearTimeout(persistTimer);
165
+ persistTimer = null;
168
166
  }
169
- const style = document.createElement("style");
170
- style.id = RDP_STYLE_ID;
171
- style.textContent = CSS;
172
- document.head.appendChild(style);
173
- injected = true;
174
- }
175
- function colorVar(key) {
176
- switch (key) {
177
- case "info":
178
- return "var(--rdp-info)";
179
- case "warning":
180
- return "var(--rdp-warning)";
181
- case "success":
182
- return "var(--rdp-success)";
183
- case "error":
184
- return "var(--rdp-error)";
185
- default:
186
- return "var(--rdp-accent)";
167
+ if (typeof window !== "undefined") {
168
+ try {
169
+ window.sessionStorage.removeItem(STORAGE_KEY);
170
+ } catch {
171
+ }
187
172
  }
173
+ emit();
188
174
  }
189
- function cx(...parts) {
190
- return parts.filter(Boolean).join(" ");
175
+ function errorCount() {
176
+ return entries.reduce((n, e) => e.level === "error" ? n + 1 : n, 0);
191
177
  }
192
-
193
- // src/core/registry.ts
194
- var tools = /* @__PURE__ */ new Map();
195
- function registerTool(def) {
196
- tools.set(def.id, def);
178
+ function addDevLog(entry) {
179
+ seq += 1;
180
+ const next = {
181
+ ...entry,
182
+ id: `log-${seq}`,
183
+ timestamp: Date.now(),
184
+ path: typeof window !== "undefined" ? window.location.pathname : void 0
185
+ };
186
+ entries = [next, ...entries].slice(0, MAX_ENTRIES);
187
+ emit();
188
+ schedulePersist();
197
189
  }
198
- function getRegisteredTools() {
199
- return [...tools.values()];
190
+ function safeString(value) {
191
+ if (typeof value === "string") return value;
192
+ if (value instanceof Error) return value.message;
193
+ try {
194
+ return JSON.stringify(value);
195
+ } catch {
196
+ return String(value);
197
+ }
200
198
  }
201
- function resolveTools(ids) {
202
- if (!ids || ids.length === 0) return getRegisteredTools();
203
- return ids.map((id) => tools.get(id)).filter((t) => Boolean(t));
199
+ function classifyApolloPayload(payload) {
200
+ if (payload && typeof payload === "object") {
201
+ const p = payload;
202
+ if (p.gqlErrors) return "server";
203
+ if (p.networkError || p.networkStatus) return "network";
204
+ }
205
+ return "server";
206
+ }
207
+ function captureConsole(level, args) {
208
+ const firstStr = typeof args[0] === "string" ? args[0] : safeString(args[0]);
209
+ if (firstStr.startsWith("[Apollo error]")) {
210
+ const payload = args[1];
211
+ addDevLog({
212
+ source: classifyApolloPayload(payload),
213
+ level,
214
+ message: firstStr.replace("[Apollo error] ", "").trim() || "Apollo error",
215
+ detail: payload !== void 0 ? safeString(payload) : void 0
216
+ });
217
+ return;
218
+ }
219
+ const errorArg = args.find((a) => a instanceof Error);
220
+ addDevLog({
221
+ source: "client",
222
+ level,
223
+ message: args.map(safeString).join(" ").trim() || `console.${level}`,
224
+ stack: errorArg?.stack
225
+ });
204
226
  }
205
- function Svg({ children, size = 16 }) {
206
- return /* @__PURE__ */ jsx(
207
- "svg",
208
- {
209
- width: size,
210
- height: size,
211
- viewBox: "0 0 24 24",
212
- fill: "none",
213
- stroke: "currentColor",
214
- strokeWidth: 2,
215
- strokeLinecap: "round",
216
- strokeLinejoin: "round",
217
- "aria-hidden": "true",
218
- children
227
+ var NETWORK_IGNORE = ["/_next/", "/__nextjs", "hot-update", "webpack", ".map", "/monitoring"];
228
+ function shouldIgnoreNetwork(url) {
229
+ return NETWORK_IGNORE.some((needle) => url.includes(needle));
230
+ }
231
+ function resolveRequest(input) {
232
+ if (typeof input === "string") return { url: input, method: "GET" };
233
+ if (input instanceof URL) return { url: input.href, method: "GET" };
234
+ return { url: input.url, method: input.method || "GET" };
235
+ }
236
+ function graphqlOperationName(body) {
237
+ if (typeof body !== "string") return void 0;
238
+ try {
239
+ const parsed = JSON.parse(body);
240
+ if (Array.isArray(parsed)) {
241
+ const names = parsed.map((p) => p?.operationName).filter(Boolean);
242
+ return names.length ? names.join(", ") : void 0;
219
243
  }
220
- );
244
+ return parsed?.operationName || void 0;
245
+ } catch {
246
+ return void 0;
247
+ }
221
248
  }
222
- var IconWrench = ({ size }) => /* @__PURE__ */ jsx(Svg, { size, children: /* @__PURE__ */ jsx("path", { d: "M14.7 6.3a4 4 0 0 0-5.4 5.3L3 18v3h3l6.4-6.3a4 4 0 0 0 5.3-5.4l-2.5 2.5-2.1-2.1z" }) });
223
- var IconBug = ({ size }) => /* @__PURE__ */ jsxs(Svg, { size, children: [
224
- /* @__PURE__ */ jsx("rect", { x: "8", y: "6", width: "8", height: "14", rx: "4" }),
225
- /* @__PURE__ */ jsx("path", { d: "M9 6a3 3 0 0 1 6 0M3 13h5M16 13h5M4 18l4-2M20 18l-4-2M4 8l4 2M20 8l-4 2" })
226
- ] });
227
- var IconGauge = ({ size }) => /* @__PURE__ */ jsxs(Svg, { size, children: [
228
- /* @__PURE__ */ jsx("path", { d: "M12 14l3-3" }),
229
- /* @__PURE__ */ jsx("path", { d: "M3.5 18a9 9 0 1 1 17 0" })
230
- ] });
231
- var IconGraph = ({ size }) => /* @__PURE__ */ jsxs(Svg, { size, children: [
232
- /* @__PURE__ */ jsx("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1.5" }),
233
- /* @__PURE__ */ jsx("rect", { x: "14", y: "14", width: "7", height: "7", rx: "1.5" }),
234
- /* @__PURE__ */ jsx("path", { d: "M10 6.5h4a3 3 0 0 1 3 3V14" })
235
- ] });
236
- var IconX = ({ size }) => /* @__PURE__ */ jsx(Svg, { size, children: /* @__PURE__ */ jsx("path", { d: "M6 6l12 12M18 6L6 18" }) });
237
- var IconChevronRight = ({ size }) => /* @__PURE__ */ jsx(Svg, { size, children: /* @__PURE__ */ jsx("path", { d: "M9 6l6 6-6 6" }) });
238
- var IconChevronDown = ({ size }) => /* @__PURE__ */ jsx(Svg, { size, children: /* @__PURE__ */ jsx("path", { d: "M6 9l6 6 6-6" }) });
239
- var IconSearch = ({ size }) => /* @__PURE__ */ jsxs(Svg, { size, children: [
240
- /* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "7" }),
241
- /* @__PURE__ */ jsx("path", { d: "M21 21l-4-4" })
242
- ] });
243
- var IconCopy = ({ size }) => /* @__PURE__ */ jsxs(Svg, { size, children: [
244
- /* @__PURE__ */ jsx("rect", { x: "9", y: "9", width: "11", height: "11", rx: "2" }),
245
- /* @__PURE__ */ jsx("path", { d: "M5 15V5a2 2 0 0 1 2-2h10" })
246
- ] });
247
- var IconFileCode = ({ size }) => /* @__PURE__ */ jsxs(Svg, { size, children: [
248
- /* @__PURE__ */ jsx("path", { d: "M14 3H7a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8z" }),
249
- /* @__PURE__ */ jsx("path", { d: "M14 3v5h5M10 12l-2 2 2 2M14 12l2 2-2 2" })
250
- ] });
251
- var IconRefresh = ({ size }) => /* @__PURE__ */ jsxs(Svg, { size, children: [
252
- /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-3-6.7L21 8" }),
253
- /* @__PURE__ */ jsx("path", { d: "M21 3v5h-5" })
254
- ] });
255
- var IconPointer = ({ size }) => /* @__PURE__ */ jsx(Svg, { size, children: /* @__PURE__ */ jsx("path", { d: "M5 3l16 7-7 2-2 7z" }) });
256
- var IconLayers = ({ size }) => /* @__PURE__ */ jsx(Svg, { size, children: /* @__PURE__ */ jsx("path", { d: "M12 3l9 5-9 5-9-5 9-5zM3 13l9 5 9-5" }) });
257
- var IconArrowUp = ({ size }) => /* @__PURE__ */ jsx(Svg, { size, children: /* @__PURE__ */ jsx("path", { d: "M12 19V5M6 11l6-6 6 6" }) });
258
- var buffer = [];
259
- var nextId = 1;
260
- var listeners = /* @__PURE__ */ new Set();
261
- function emit() {
262
- listeners.forEach((l) => l());
249
+ function detectOpType(query, opName) {
250
+ if (typeof query !== "string") return void 0;
251
+ if (opName) {
252
+ const named = new RegExp(`\\b(query|mutation|subscription)\\s+${opName}\\b`).exec(query);
253
+ if (named) return named[1];
254
+ }
255
+ const keyword = /\b(query|mutation|subscription)\b/.exec(query);
256
+ if (keyword) return keyword[1];
257
+ return /^\s*\{/.test(query) ? "query" : void 0;
263
258
  }
264
- function push(level, message, meta) {
265
- buffer = [...buffer.slice(-499), { id: nextId++, level, time: Date.now(), message, meta }];
266
- emit();
259
+ function graphqlOperationType(body) {
260
+ if (typeof body !== "string") return void 0;
261
+ try {
262
+ const parsed = JSON.parse(body);
263
+ const ops = Array.isArray(parsed) ? parsed : [parsed];
264
+ const types = ops.map((p) => detectOpType(p?.query, p?.operationName)).filter(Boolean);
265
+ const unique = Array.from(new Set(types));
266
+ return unique.length === 1 ? unique[0] : void 0;
267
+ } catch {
268
+ return void 0;
269
+ }
270
+ }
271
+ function collapseSignedQuery(u) {
272
+ return u.searchParams.has("X-Amz-Signature") ? "?[signed]" : u.search;
273
+ }
274
+ function shortUrl(url) {
275
+ try {
276
+ const u = new URL(url, window.location.origin);
277
+ return u.pathname + collapseSignedQuery(u);
278
+ } catch {
279
+ return url;
280
+ }
267
281
  }
268
- function stringify(args) {
269
- return args.map((a) => {
270
- if (typeof a === "string") return a;
282
+ function redactedUrl(url) {
283
+ try {
284
+ const u = new URL(url, window.location.origin);
285
+ return `${u.origin}${u.pathname}${collapseSignedQuery(u)}`;
286
+ } catch {
287
+ return url;
288
+ }
289
+ }
290
+ function networkLevel(status) {
291
+ if (status === 0 || status >= 500) return "error";
292
+ if (status >= 400) return "warn";
293
+ return "info";
294
+ }
295
+ var MAX_REASON_CHARS = 160;
296
+ function errorReason(body) {
297
+ if (!body) return void 0;
298
+ const text = body.trim();
299
+ if (!text) return void 0;
300
+ const xmlCode = /<Code>([^<]+)<\/Code>/i.exec(text)?.[1];
301
+ const xmlMessage = /<Message>([^<]+)<\/Message>/i.exec(text)?.[1];
302
+ if (xmlCode || xmlMessage) return [xmlCode, xmlMessage].filter(Boolean).join(": ").slice(0, MAX_REASON_CHARS);
303
+ if (text[0] === "{" || text[0] === "[") {
271
304
  try {
272
- return JSON.stringify(a);
305
+ const parsed = JSON.parse(text);
306
+ const gql = parsed?.errors?.map((e) => e?.message).filter(Boolean).join("; ");
307
+ const reason = gql || (typeof parsed.message === "string" ? parsed.message : void 0) || (typeof parsed.error === "string" ? parsed.error : void 0);
308
+ if (reason) return reason.slice(0, MAX_REASON_CHARS);
273
309
  } catch {
274
- return String(a);
275
310
  }
276
- }).join(" ").slice(0, 2e3);
311
+ }
312
+ const firstLine = text.split("\n").find((line) => line.trim());
313
+ return firstLine ? firstLine.slice(0, MAX_REASON_CHARS) : void 0;
277
314
  }
278
- var installed = false;
279
- function installCapture() {
280
- if (installed || typeof window === "undefined") return;
281
- installed = true;
282
- ["log", "info", "warn", "error"].forEach((level) => {
283
- const original = console[level].bind(console);
284
- console[level] = (...args) => {
285
- push(level, stringify(args));
286
- original(...args);
287
- };
288
- });
289
- if (typeof window.fetch === "function") {
290
- const orig = window.fetch.bind(window);
291
- window.fetch = async (input, init) => {
292
- const method = (init?.method ?? "GET").toUpperCase();
293
- const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
294
- const start = Date.now();
295
- try {
296
- const res = await orig(input, init);
297
- push(res.ok ? "network" : "error", `${method} ${url}`, `${res.status} \xB7 ${Date.now() - start}ms`);
298
- return res;
299
- } catch (err) {
300
- push("error", `${method} ${url}`, `failed \xB7 ${String(err)}`);
301
- throw err;
302
- }
303
- };
315
+ function graphqlResponseErrors(body) {
316
+ if (!body) return void 0;
317
+ const trimmed = body.trim();
318
+ if (trimmed[0] !== "{" && trimmed[0] !== "[") return void 0;
319
+ try {
320
+ const parsed = JSON.parse(trimmed);
321
+ const result = Array.isArray(parsed) ? parsed[0] : parsed;
322
+ const errors = result?.errors;
323
+ if (!Array.isArray(errors) || errors.length === 0) return void 0;
324
+ const reason = errors.map((e) => {
325
+ const code = e?.extensions?.code;
326
+ return code ? `${code}: ${e?.message ?? ""}`.trim() : e?.message;
327
+ }).filter(Boolean).join("; ").slice(0, MAX_REASON_CHARS) || "GraphQL error";
328
+ const data = result?.data;
329
+ const partial = data != null && typeof data === "object" && Object.values(data).some((v) => v != null);
330
+ return { reason, partial };
331
+ } catch {
332
+ return void 0;
304
333
  }
305
334
  }
306
- function subscribeLogs(listener) {
307
- listeners.add(listener);
308
- return () => listeners.delete(listener);
335
+ var MAX_BODY_CHARS = 5e4;
336
+ function truncateBody(text) {
337
+ if (text.length <= MAX_BODY_CHARS) return text;
338
+ return `${text.slice(0, MAX_BODY_CHARS)}
339
+ \u2026 [truncated ${text.length - MAX_BODY_CHARS} chars]`;
309
340
  }
310
- function getLogs() {
311
- return buffer;
341
+ function prettyMaybeJson(text) {
342
+ const trimmed = text.trim();
343
+ if (trimmed[0] !== "{" && trimmed[0] !== "[") return text;
344
+ try {
345
+ return JSON.stringify(JSON.parse(trimmed), null, 2);
346
+ } catch {
347
+ return text;
348
+ }
312
349
  }
313
- var EMPTY = [];
314
- function getServerLogs() {
315
- return EMPTY;
350
+ function formatGraphqlBody(parsed) {
351
+ const ops = Array.isArray(parsed) ? parsed : [parsed];
352
+ if (!ops.length || !ops.every((op) => op && typeof op === "object" && typeof op.query === "string")) return null;
353
+ return ops.map((op) => {
354
+ const parts = [];
355
+ if (op.operationName) parts.push(`# Operation: ${op.operationName}`);
356
+ if (op.variables && Object.keys(op.variables).length > 0)
357
+ parts.push(`# Variables
358
+ ${JSON.stringify(op.variables, null, 2)}`);
359
+ parts.push(`# Query
360
+ ${op.query.trim()}`);
361
+ return parts.join("\n\n");
362
+ }).join("\n\n\u2014\u2014\u2014\n\n");
363
+ }
364
+ function formatBodyString(text) {
365
+ const trimmed = text.trim();
366
+ if (trimmed[0] === "{" || trimmed[0] === "[") {
367
+ try {
368
+ const parsed = JSON.parse(trimmed);
369
+ return formatGraphqlBody(parsed) ?? JSON.stringify(parsed, null, 2);
370
+ } catch {
371
+ return text;
372
+ }
373
+ }
374
+ return text;
375
+ }
376
+ var SENSITIVE_HEADERS = ["authorization", "cookie", "set-cookie", "x-api-key", "proxy-authorization"];
377
+ function formatHeaders(source) {
378
+ const lines = [];
379
+ source.forEach((value, key) => {
380
+ const redacted = SENSITIVE_HEADERS.includes(key.toLowerCase()) ? "[redacted]" : value;
381
+ lines.push(`${key}: ${redacted}`);
382
+ });
383
+ return lines.length ? lines.join("\n") : void 0;
384
+ }
385
+ function requestHeaders(input, init) {
386
+ const merged = new Headers();
387
+ if (input instanceof Request) input.headers.forEach((value, key) => merged.set(key, value));
388
+ if (init?.headers) new Headers(init.headers).forEach((value, key) => merged.set(key, value));
389
+ return formatHeaders(merged);
390
+ }
391
+ function rawRequestBody(body) {
392
+ if (typeof body !== "string") return void 0;
393
+ return truncateBody(body);
394
+ }
395
+ function readableRequestBody(body) {
396
+ if (body == null) return void 0;
397
+ if (typeof body === "string") return truncateBody(formatBodyString(body));
398
+ if (body instanceof URLSearchParams) return body.toString();
399
+ const name = body.constructor?.name;
400
+ return `[${name || "binary"} body \u2014 not shown]`;
401
+ }
402
+ async function readResponseBody(res) {
403
+ try {
404
+ const ct = res.headers.get("content-type") ?? "";
405
+ if (ct && !/json|text|xml|graphql|javascript|csv|html/i.test(ct)) return `[${ct} response \u2014 not shown]`;
406
+ const text = await res.text();
407
+ if (!text) return void 0;
408
+ return truncateBody(prettyMaybeJson(text));
409
+ } catch {
410
+ return void 0;
411
+ }
316
412
  }
317
- function clearLogs() {
318
- buffer = [];
319
- emit();
413
+ function captureFetch() {
414
+ if (typeof window.fetch !== "function") return;
415
+ const origFetch = window.fetch.bind(window);
416
+ window.fetch = async (input, init) => {
417
+ const { url, method: inferredMethod } = resolveRequest(input);
418
+ const method = (init?.method || inferredMethod || "GET").toUpperCase();
419
+ if (shouldIgnoreNetwork(url)) return origFetch(input, init);
420
+ const opName = graphqlOperationName(init?.body ?? null);
421
+ const opType = graphqlOperationType(init?.body ?? null);
422
+ const reqHeaders = requestHeaders(input, init);
423
+ const requestBody = readableRequestBody(init?.body ?? null);
424
+ const requestBodyRaw = rawRequestBody(init?.body ?? null);
425
+ const start = Date.now();
426
+ const log = (status, statusText, errored, responseBody, responseHeaders) => {
427
+ const ms = Date.now() - start;
428
+ const opLabel = opName ? `${opType ? `${opType} ` : ""}${opName}` : void 0;
429
+ const label = opLabel ? `${shortUrl(url)} \xB7 ${opLabel}` : shortUrl(url);
430
+ const gqlErrors = !errored && status < 400 ? graphqlResponseErrors(responseBody) : void 0;
431
+ const statusLabel = errored ? "FAILED" : String(status);
432
+ const reason = errored ? statusText : status >= 400 ? errorReason(responseBody) : gqlErrors?.reason;
433
+ const level = errored ? "error" : gqlErrors ? gqlErrors.partial ? "warn" : "error" : networkLevel(status);
434
+ addDevLog({
435
+ source: "network",
436
+ level,
437
+ message: `${method} ${statusLabel} ${label} (${ms}ms)${reason ? ` \u2014 ${reason}` : ""}`,
438
+ detail: `${method} ${redactedUrl(url)}
439
+ ${errored ? statusText : `${status} ${statusText}`} \xB7 ${ms}ms${gqlErrors ? ` \xB7 GraphQL ${gqlErrors.partial ? "partial error" : "error"}` : ""}`,
440
+ requestHeaders: reqHeaders,
441
+ requestBody,
442
+ requestBodyRaw,
443
+ responseHeaders,
444
+ responseBody
445
+ });
446
+ };
447
+ try {
448
+ const res = await origFetch(input, init);
449
+ let clone = null;
450
+ try {
451
+ clone = res.clone();
452
+ } catch {
453
+ clone = null;
454
+ }
455
+ const resHeaders = formatHeaders(res.headers);
456
+ if (clone) void readResponseBody(clone).then((body) => log(res.status, res.statusText, false, body, resHeaders));
457
+ else log(res.status, res.statusText, false, void 0, resHeaders);
458
+ return res;
459
+ } catch (err) {
460
+ log(0, err instanceof Error ? err.message : "Network error", true);
461
+ throw err;
462
+ }
463
+ };
320
464
  }
321
- var LEVELS = ["all", "log", "warn", "error", "network"];
322
- var LEVEL_COLOR = {
323
- log: "var(--rdp-text-dim)",
324
- info: "var(--rdp-info)",
325
- warn: "var(--rdp-warning)",
326
- error: "var(--rdp-error)",
327
- network: "var(--rdp-info)"
465
+ function installDevLogCapture() {
466
+ if (installed || typeof window === "undefined") return;
467
+ installed = true;
468
+ hydrate();
469
+ captureFetch();
470
+ window.addEventListener("pagehide", persist);
471
+ const origError = console.error.bind(console);
472
+ const origWarn = console.warn.bind(console);
473
+ const origLog = console.log.bind(console);
474
+ console.error = (...args) => {
475
+ origError(...args);
476
+ try {
477
+ captureConsole("error", args);
478
+ } catch {
479
+ }
480
+ };
481
+ console.warn = (...args) => {
482
+ origWarn(...args);
483
+ try {
484
+ captureConsole("warn", args);
485
+ } catch {
486
+ }
487
+ };
488
+ console.log = (...args) => {
489
+ origLog(...args);
490
+ try {
491
+ captureConsole("info", args);
492
+ } catch {
493
+ }
494
+ };
495
+ window.addEventListener("error", (event) => {
496
+ addDevLog({
497
+ source: "client",
498
+ level: "error",
499
+ message: event.message || "Uncaught error",
500
+ stack: event.error?.stack,
501
+ detail: event.filename ? `${event.filename}:${event.lineno}:${event.colno}` : void 0
502
+ });
503
+ });
504
+ window.addEventListener("unhandledrejection", (event) => {
505
+ const reason = event.reason;
506
+ addDevLog({
507
+ source: "client",
508
+ level: "error",
509
+ message: reason?.message ? `Unhandled rejection: ${reason.message}` : "Unhandled promise rejection",
510
+ stack: reason?.stack,
511
+ detail: safeString(event.reason)
512
+ });
513
+ });
514
+ }
515
+ var SOURCE_COLOR = {
516
+ server: "warning",
517
+ client: "info",
518
+ network: "success"
328
519
  };
329
- function DevLogsPanel({ onClose }) {
330
- const logs = useSyncExternalStore(subscribeLogs, getLogs, getServerLogs);
331
- const [filter, setFilter] = useState("all");
332
- const shown = filter === "all" ? logs : logs.filter((l) => l.level === filter);
333
- return /* @__PURE__ */ jsxs("div", { className: "rdp-surface rdp-panel", style: { bottom: 88, right: 20 }, children: [
334
- /* @__PURE__ */ jsxs("div", { className: "rdp-header", children: [
335
- /* @__PURE__ */ jsx(IconBug, { size: 16 }),
336
- /* @__PURE__ */ jsx("span", { className: "rdp-title", style: { flex: 1 }, children: "Developer Logs" }),
337
- /* @__PURE__ */ jsx("button", { type: "button", className: "rdp-iconbtn-bare", onClick: clearLogs, title: "Clear", style: { width: "auto", padding: "0 8px" }, children: "Clear" }),
338
- /* @__PURE__ */ jsx("button", { type: "button", className: "rdp-iconbtn-bare", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(IconX, { size: 16 }) })
520
+ function formatTime(ts) {
521
+ const d = new Date(ts);
522
+ const pad = (n) => String(n).padStart(2, "0");
523
+ return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
524
+ }
525
+ function buildSections(entry) {
526
+ const sections = [];
527
+ const requestTabs = [];
528
+ if (entry.requestBody) {
529
+ const hasRaw = Boolean(entry.requestBodyRaw && entry.requestBodyRaw !== entry.requestBody);
530
+ requestTabs.push({
531
+ key: "payload",
532
+ label: "Payload",
533
+ value: entry.requestBody,
534
+ variants: hasRaw ? [
535
+ { key: "pretty", label: "Pretty", value: entry.requestBody },
536
+ { key: "raw", label: "Raw", value: entry.requestBodyRaw }
537
+ ] : void 0
538
+ });
539
+ }
540
+ if (entry.requestHeaders) requestTabs.push({ key: "headers", label: "Headers", value: entry.requestHeaders });
541
+ if (requestTabs.length) sections.push({ label: "Request", tabs: requestTabs });
542
+ const responseTabs = [];
543
+ if (entry.responseBody) responseTabs.push({ key: "body", label: "Body", value: entry.responseBody });
544
+ if (entry.responseHeaders) responseTabs.push({ key: "headers", label: "Headers", value: entry.responseHeaders });
545
+ if (responseTabs.length) sections.push({ label: "Response", tabs: responseTabs });
546
+ if (entry.stack) sections.push({ label: "Stack trace", tabs: [{ key: "stack", label: "Stack trace", value: entry.stack }] });
547
+ if (!sections.length && entry.detail) sections.push({ label: "Detail", tabs: [{ key: "detail", label: "Detail", value: entry.detail }] });
548
+ return sections;
549
+ }
550
+ var TOGGLE_SX = {
551
+ "& .MuiToggleButton-root": {
552
+ py: 0,
553
+ px: 0.75,
554
+ height: 20,
555
+ fontSize: "0.6rem",
556
+ fontWeight: 700,
557
+ lineHeight: 1,
558
+ letterSpacing: 0.3,
559
+ textTransform: "uppercase",
560
+ border: "1px solid",
561
+ borderColor: "divider"
562
+ }
563
+ };
564
+ function CopyButton({ value }) {
565
+ const [copied, setCopied] = useState(false);
566
+ const handleCopy = useCallback(
567
+ (e) => {
568
+ e.stopPropagation();
569
+ navigator.clipboard?.writeText(value).then(
570
+ () => {
571
+ setCopied(true);
572
+ window.setTimeout(() => setCopied(false), 1200);
573
+ },
574
+ () => void 0
575
+ );
576
+ },
577
+ [value]
578
+ );
579
+ return /* @__PURE__ */ jsx(Tooltip2, { title: copied ? "Copied" : "Copy", placement: "top", children: /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: handleCopy, sx: { color: copied ? "success.main" : void 0 }, children: copied ? /* @__PURE__ */ jsx(LuCheck, { size: 13 }) : /* @__PURE__ */ jsx(LuCopy, { size: 13 }) }) });
580
+ }
581
+ function SectionBlock({ section }) {
582
+ const theme = useTheme();
583
+ const [activeTabKey, setActiveTabKey] = useState(section.tabs[0]?.key);
584
+ const [variantByTab, setVariantByTab] = useState({});
585
+ const activeTab = section.tabs.find((t) => t.key === activeTabKey) ?? section.tabs[0];
586
+ const activeVariantKey = variantByTab[activeTab.key] ?? activeTab.variants?.[0]?.key;
587
+ const activeVariant = activeTab.variants?.find((v) => v.key === activeVariantKey);
588
+ const displayValue = activeVariant?.value ?? activeTab.value;
589
+ const showTabs = section.tabs.length > 1;
590
+ return /* @__PURE__ */ jsxs(Box6, { children: [
591
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", sx: { px: 1, py: 0.25, gap: 0.5, flexWrap: "wrap" }, children: [
592
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", spacing: 0.75, sx: { minWidth: 0 }, children: [
593
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { color: "text.disabled", fontWeight: 700, textTransform: "uppercase", letterSpacing: 0.4 }, children: section.label }),
594
+ showTabs && /* @__PURE__ */ jsx(ToggleButtonGroup, { size: "small", exclusive: true, value: activeTab.key, onChange: (_, next) => next && setActiveTabKey(next), sx: TOGGLE_SX, children: section.tabs.map((t) => /* @__PURE__ */ jsx(ToggleButton, { value: t.key, children: t.label }, t.key)) })
595
+ ] }),
596
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", spacing: 0.5, children: [
597
+ activeTab.variants && /* @__PURE__ */ jsx(
598
+ ToggleButtonGroup,
599
+ {
600
+ size: "small",
601
+ exclusive: true,
602
+ value: activeVariantKey,
603
+ onChange: (_, next) => next && setVariantByTab((prev) => ({ ...prev, [activeTab.key]: next })),
604
+ sx: TOGGLE_SX,
605
+ children: activeTab.variants.map((v) => /* @__PURE__ */ jsx(ToggleButton, { value: v.key, children: v.label }, v.key))
606
+ }
607
+ ),
608
+ /* @__PURE__ */ jsx(CopyButton, { value: displayValue })
609
+ ] })
339
610
  ] }),
340
- /* @__PURE__ */ jsx("div", { style: { padding: "8px 12px 0", display: "flex", gap: 4, flexWrap: "wrap" }, children: LEVELS.map((lvl) => /* @__PURE__ */ jsx(
341
- "button",
611
+ /* @__PURE__ */ jsx(
612
+ Box6,
342
613
  {
343
- type: "button",
344
- className: cx("rdp-btn", "rdp-btn-sm"),
345
- style: filter === lvl ? { borderColor: "var(--rdp-accent)", color: "var(--rdp-accent)" } : void 0,
346
- onClick: () => setFilter(lvl),
347
- children: lvl
348
- },
349
- lvl
350
- )) }),
351
- /* @__PURE__ */ jsx("div", { className: "rdp-body rdp-mono", style: { fontSize: 12 }, children: shown.length === 0 ? /* @__PURE__ */ jsx("div", { style: { color: "var(--rdp-text-faint)" }, children: "No log entries captured yet." }) : shown.slice().reverse().map((entry) => /* @__PURE__ */ jsxs("div", { style: { padding: "3px 0", borderBottom: "1px solid var(--rdp-border)" }, children: [
352
- /* @__PURE__ */ jsx("span", { style: { color: LEVEL_COLOR[entry.level], fontWeight: 700, marginRight: 6 }, children: entry.level === "network" ? "net" : entry.level }),
353
- /* @__PURE__ */ jsx("span", { style: { wordBreak: "break-word" }, children: entry.message }),
354
- entry.meta && /* @__PURE__ */ jsx("span", { style: { color: "var(--rdp-text-faint)", marginLeft: 6 }, children: entry.meta })
355
- ] }, entry.id)) })
614
+ component: "pre",
615
+ sx: {
616
+ m: 0,
617
+ px: 1,
618
+ pb: 1,
619
+ fontFamily: "monospace",
620
+ fontSize: "0.7rem",
621
+ color: "text.secondary",
622
+ whiteSpace: "pre-wrap",
623
+ wordBreak: "break-word",
624
+ overflowX: "auto",
625
+ maxHeight: 280,
626
+ bgcolor: alpha(theme.palette.grey[500], 0.06)
627
+ },
628
+ children: displayValue
629
+ }
630
+ )
631
+ ] });
632
+ }
633
+ function LogRow({ entry, showPath }) {
634
+ const [open, setOpen] = useState(false);
635
+ const sections = useMemo(() => buildSections(entry), [entry]);
636
+ const expandable = sections.length > 0;
637
+ return /* @__PURE__ */ jsxs(Box6, { sx: { border: "1px solid", borderColor: "divider", borderRadius: 1, overflow: "hidden" }, children: [
638
+ /* @__PURE__ */ jsxs(
639
+ Box6,
640
+ {
641
+ onClick: expandable ? () => setOpen((v) => !v) : void 0,
642
+ sx: {
643
+ display: "flex",
644
+ alignItems: "flex-start",
645
+ gap: 1,
646
+ px: 1,
647
+ py: 0.75,
648
+ cursor: expandable ? "pointer" : "default",
649
+ "&:hover": expandable ? { bgcolor: "action.hover" } : void 0
650
+ },
651
+ children: [
652
+ /* @__PURE__ */ jsx(
653
+ Chip,
654
+ {
655
+ label: entry.source,
656
+ size: "small",
657
+ color: SOURCE_COLOR[entry.source],
658
+ variant: "soft",
659
+ sx: { height: 18, fontSize: "0.6rem", textTransform: "uppercase", fontWeight: 700, mt: 0.25, flexShrink: 0 }
660
+ }
661
+ ),
662
+ /* @__PURE__ */ jsxs(Box6, { sx: { flex: 1, minWidth: 0 }, children: [
663
+ /* @__PURE__ */ jsx(
664
+ Typography3,
665
+ {
666
+ variant: "body2",
667
+ sx: {
668
+ fontFamily: "monospace",
669
+ fontSize: "0.75rem",
670
+ color: entry.level === "error" ? "error.main" : "text.primary",
671
+ wordBreak: "break-word",
672
+ whiteSpace: "pre-wrap"
673
+ },
674
+ children: entry.message
675
+ }
676
+ ),
677
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, sx: { mt: 0.25 }, children: [
678
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { color: "text.disabled", fontFamily: "monospace" }, children: formatTime(entry.timestamp) }),
679
+ showPath && entry.path && /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { color: "text.disabled", fontFamily: "monospace", wordBreak: "break-all" }, children: entry.path })
680
+ ] })
681
+ ] }),
682
+ expandable && /* @__PURE__ */ jsx(Box6, { sx: { flexShrink: 0, color: "text.disabled", transform: open ? "rotate(180deg)" : "none", transition: "transform 0.15s", mt: 0.25 }, children: /* @__PURE__ */ jsx(LuChevronDown, { size: 14 }) })
683
+ ]
684
+ }
685
+ ),
686
+ expandable && /* @__PURE__ */ jsx(Collapse, { in: open, unmountOnExit: true, children: /* @__PURE__ */ jsx(Stack, { spacing: 0.5, sx: { borderTop: "1px solid", borderColor: "divider", py: 0.5 }, children: sections.map((section) => /* @__PURE__ */ jsx(SectionBlock, { section }, section.label)) }) })
356
687
  ] });
357
688
  }
689
+ function DevLogsPanel({ onClose }) {
690
+ const logs = useSyncExternalStore(subscribeDevLogs, getDevLogs, getDevLogsServerSnapshot);
691
+ const pathname = useDevPanelConfig().getRoute();
692
+ const [source, setSource] = useState("all");
693
+ const [level, setLevel] = useState("all");
694
+ const [thisPageOnly, setThisPageOnly] = useState(true);
695
+ const [search, setSearch2] = useState("");
696
+ const filtered = useMemo(() => {
697
+ const term = search.trim().toLowerCase();
698
+ return logs.filter((entry) => {
699
+ if (source !== "all" && entry.source !== source) return false;
700
+ if (level !== "all" && entry.level !== level) return false;
701
+ if (thisPageOnly && entry.path && entry.path !== pathname) return false;
702
+ if (term) {
703
+ const haystack = `${entry.message} ${entry.detail ?? ""} ${entry.stack ?? ""}`.toLowerCase();
704
+ if (!haystack.includes(term)) return false;
705
+ }
706
+ return true;
707
+ });
708
+ }, [logs, source, level, thisPageOnly, search, pathname]);
709
+ return /* @__PURE__ */ jsxs(
710
+ Box6,
711
+ {
712
+ "data-rdp-ignore": "",
713
+ sx: {
714
+ position: "fixed",
715
+ bottom: 96,
716
+ right: 24,
717
+ zIndex: (t) => t.zIndex.modal + 1,
718
+ width: "min(460px, calc(100vw - 32px))",
719
+ maxHeight: "min(70vh, 640px)",
720
+ display: "flex",
721
+ flexDirection: "column",
722
+ borderRadius: 2,
723
+ overflow: "hidden",
724
+ border: "1px solid",
725
+ borderColor: "divider",
726
+ bgcolor: "background.paper",
727
+ boxShadow: 12
728
+ },
729
+ children: [
730
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", sx: { px: 1.5, py: 1, borderBottom: "1px solid", borderColor: "divider", flexShrink: 0 }, children: [
731
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", spacing: 1, children: [
732
+ /* @__PURE__ */ jsx(LuBug, { size: 16 }),
733
+ /* @__PURE__ */ jsx(Typography3, { variant: "subtitle2", sx: { fontWeight: 700 }, children: "Developer Logs" }),
734
+ /* @__PURE__ */ jsx(Chip, { label: `${filtered.length}/${logs.length}`, size: "small", variant: "soft", sx: { height: 18, fontSize: "0.65rem" } })
735
+ ] }),
736
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 0.5, children: [
737
+ /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: clearDevLogs, disabled: logs.length === 0, children: /* @__PURE__ */ jsx(LuTrash2, { size: 15 }) }),
738
+ /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: onClose, children: /* @__PURE__ */ jsx(LuX, { size: 16 }) })
739
+ ] })
740
+ ] }),
741
+ /* @__PURE__ */ jsxs(Stack, { spacing: 1, sx: { px: 1.5, py: 1, borderBottom: "1px solid", borderColor: "divider", flexShrink: 0 }, children: [
742
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, alignItems: "center", flexWrap: "wrap", useFlexGap: true, children: [
743
+ /* @__PURE__ */ jsx(ToggleButtonGroup, { size: "small", exclusive: true, value: source, onChange: (_, v) => v && setSource(v), children: ["all", "client", "server", "network"].map((v) => /* @__PURE__ */ jsx(ToggleButton, { value: v, sx: { px: 1, py: 0.25, fontSize: "0.7rem", textTransform: "capitalize" }, children: v }, v)) }),
744
+ /* @__PURE__ */ jsx(ToggleButton, { size: "small", value: "thisPage", selected: thisPageOnly, onChange: () => setThisPageOnly((v) => !v), sx: { px: 1, py: 0.25, fontSize: "0.7rem" }, children: "This page" })
745
+ ] }),
746
+ /* @__PURE__ */ jsx(ToggleButtonGroup, { size: "small", exclusive: true, value: level, onChange: (_, v) => v && setLevel(v), children: ["all", "error", "warn", "info"].map((v) => /* @__PURE__ */ jsx(ToggleButton, { value: v, sx: { px: 1, py: 0.25, fontSize: "0.7rem", textTransform: "capitalize" }, children: v }, v)) }),
747
+ /* @__PURE__ */ jsx(
748
+ TextField,
749
+ {
750
+ size: "small",
751
+ placeholder: "Search...",
752
+ value: search,
753
+ onChange: (e) => setSearch2(e.target.value),
754
+ fullWidth: true,
755
+ slotProps: {
756
+ input: {
757
+ startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx(LuSearch, { size: 15 }) })
758
+ }
759
+ }
760
+ }
761
+ )
762
+ ] }),
763
+ /* @__PURE__ */ jsx(Box6, { sx: { flex: 1, overflowY: "auto", p: 1 }, children: filtered.length === 0 ? /* @__PURE__ */ jsx(Typography3, { variant: "body2", sx: { color: "text.disabled", textAlign: "center", py: 4 }, children: logs.length === 0 ? "No activity captured this session." : "No logs match the current filters." }) : /* @__PURE__ */ jsx(Stack, { spacing: 0.75, children: filtered.map((entry) => /* @__PURE__ */ jsx(LogRow, { entry, showPath: !thisPageOnly }, entry.id)) }) })
764
+ ]
765
+ }
766
+ );
767
+ }
358
768
  function useBadge() {
359
- const logs = useSyncExternalStore(subscribeLogs, getLogs, getServerLogs);
360
- const errors = logs.filter((l) => l.level === "error").length;
769
+ const logs = useSyncExternalStore(subscribeDevLogs, getDevLogs, getDevLogsServerSnapshot);
361
770
  if (logs.length === 0) return null;
771
+ const errors = errorCount();
362
772
  return errors > 0 ? { label: String(errors), tone: "error" } : { label: String(logs.length), tone: "neutral" };
363
773
  }
364
774
  var devLogsTool = {
365
775
  id: "logs",
366
776
  title: "Developer Logs",
367
- subtitle: "Client & network activity",
777
+ subtitle: "Client, server & network activity",
368
778
  color: "info",
369
- icon: /* @__PURE__ */ jsx(IconBug, { size: 19 }),
779
+ icon: /* @__PURE__ */ jsx(LuBug, { size: 19 }),
370
780
  Panel: DevLogsPanel,
371
781
  useBadge,
372
- init: installCapture
782
+ init: installDevLogCapture
373
783
  };
374
784
  function registerDevLogs() {
375
785
  registerTool(devLogsTool);
@@ -389,12 +799,7 @@ function emit2() {
389
799
  function record(m) {
390
800
  metrics = {
391
801
  ...metrics,
392
- [m.name]: {
393
- name: m.name,
394
- value: m.value,
395
- rating: m.rating,
396
- unit: m.name === "CLS" ? "" : "ms"
397
- }
802
+ [m.name]: { name: m.name, value: m.value, rating: m.rating, unit: m.name === "CLS" ? "" : "ms" }
398
803
  };
399
804
  emit2();
400
805
  }
@@ -420,195 +825,171 @@ function serverSnapshot() {
420
825
  return EMPTY2;
421
826
  }
422
827
  var RATING_COLOR = {
423
- good: "var(--rdp-success)",
424
- "needs-improvement": "var(--rdp-warning)",
425
- poor: "var(--rdp-error)"
828
+ good: "success",
829
+ "needs-improvement": "warning",
830
+ poor: "error"
426
831
  };
427
832
  function PagePerformancePanel({ onClose }) {
428
833
  const data = useSyncExternalStore(subscribe, snapshot, serverSnapshot);
429
834
  const order = ["LCP", "INP", "CLS", "FCP", "TTFB"];
430
- return /* @__PURE__ */ jsxs("div", { className: "rdp-surface rdp-panel", style: { bottom: 88, right: 20 }, children: [
431
- /* @__PURE__ */ jsxs("div", { className: "rdp-header", children: [
432
- /* @__PURE__ */ jsx(IconGauge, { size: 16 }),
433
- /* @__PURE__ */ jsx("span", { className: "rdp-title", style: { flex: 1 }, children: "Page Performance" }),
434
- /* @__PURE__ */ jsx("button", { type: "button", className: "rdp-iconbtn-bare", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(IconX, { size: 16 }) })
435
- ] }),
436
- /* @__PURE__ */ jsxs("div", { className: "rdp-body", children: [
437
- order.every((k) => !data[k]) && /* @__PURE__ */ jsx("div", { style: { color: "var(--rdp-text-faint)" }, children: "Collecting Web Vitals\u2026 interact with the page (INP needs an interaction)." }),
438
- order.map((key) => {
439
- const m = data[key];
440
- if (!m) return null;
441
- return /* @__PURE__ */ jsxs("div", { style: { padding: "8px 0", borderBottom: "1px solid var(--rdp-border)" }, children: [
442
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
443
- /* @__PURE__ */ jsx("span", { className: "rdp-chip", style: { background: RATING_COLOR[m.rating], color: "#06210f" }, children: m.name }),
444
- /* @__PURE__ */ jsxs("span", { className: "rdp-mono", style: { fontWeight: 700 }, children: [
445
- m.unit === "ms" ? Math.round(m.value) : m.value.toFixed(3),
446
- m.unit
447
- ] }),
448
- /* @__PURE__ */ jsx("span", { style: { color: RATING_COLOR[m.rating], fontSize: 11, marginLeft: "auto" }, children: m.rating })
835
+ return /* @__PURE__ */ jsxs(
836
+ Box6,
837
+ {
838
+ "data-rdp-ignore": "",
839
+ sx: {
840
+ position: "fixed",
841
+ bottom: 96,
842
+ right: 24,
843
+ zIndex: (t) => t.zIndex.modal + 1,
844
+ width: "min(440px, calc(100vw - 32px))",
845
+ maxHeight: "min(70vh, 640px)",
846
+ display: "flex",
847
+ flexDirection: "column",
848
+ borderRadius: 2,
849
+ overflow: "hidden",
850
+ border: "1px solid",
851
+ borderColor: "divider",
852
+ bgcolor: "background.paper",
853
+ boxShadow: 12
854
+ },
855
+ children: [
856
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", sx: { px: 1.5, py: 1, borderBottom: "1px solid", borderColor: "divider" }, children: [
857
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", spacing: 1, children: [
858
+ /* @__PURE__ */ jsx(LuGauge, { size: 16 }),
859
+ /* @__PURE__ */ jsx(Typography3, { variant: "subtitle2", sx: { fontWeight: 700 }, children: "Page Performance" })
449
860
  ] }),
450
- /* @__PURE__ */ jsx("div", { className: "rdp-sub", style: { marginTop: 2 }, children: HINTS[key] })
451
- ] }, key);
452
- })
453
- ] })
454
- ] });
861
+ /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: onClose, children: /* @__PURE__ */ jsx(LuX, { size: 16 }) })
862
+ ] }),
863
+ /* @__PURE__ */ jsxs(Box6, { sx: { flex: 1, overflowY: "auto", p: 1.5 }, children: [
864
+ order.every((k) => !data[k]) && /* @__PURE__ */ jsx(Typography3, { variant: "body2", sx: { color: "text.disabled" }, children: "Collecting Web Vitals\u2026 interact with the page (INP needs an interaction)." }),
865
+ order.map((key) => {
866
+ const m = data[key];
867
+ if (!m) return null;
868
+ return /* @__PURE__ */ jsxs(Box6, { sx: { py: 1, borderBottom: "1px solid", borderColor: "divider" }, children: [
869
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", spacing: 1, children: [
870
+ /* @__PURE__ */ jsx(
871
+ Chip,
872
+ {
873
+ label: m.name,
874
+ size: "small",
875
+ color: RATING_COLOR[m.rating],
876
+ variant: "soft",
877
+ sx: { height: 20, fontSize: "0.65rem", fontWeight: 700 }
878
+ }
879
+ ),
880
+ /* @__PURE__ */ jsxs(Typography3, { variant: "body2", sx: { fontFamily: "monospace", fontWeight: 700 }, children: [
881
+ m.unit === "ms" ? Math.round(m.value) : m.value.toFixed(3),
882
+ m.unit
883
+ ] }),
884
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { color: `${RATING_COLOR[m.rating]}.main`, ml: "auto" }, children: m.rating })
885
+ ] }),
886
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { color: "text.secondary", display: "block", mt: 0.25 }, children: HINTS[key] })
887
+ ] }, key);
888
+ })
889
+ ] })
890
+ ]
891
+ }
892
+ );
455
893
  }
456
894
  var pagePerformanceTool = {
457
895
  id: "perf",
458
896
  title: "Page Performance",
459
897
  subtitle: "Web Vitals & fix suggestions",
460
898
  color: "warning",
461
- icon: /* @__PURE__ */ jsx(IconGauge, { size: 19 }),
899
+ icon: /* @__PURE__ */ jsx(LuGauge, { size: 19 }),
462
900
  Panel: PagePerformancePanel,
463
901
  init: installPerf
464
902
  };
465
903
  function registerPagePerformance() {
466
904
  registerTool(pagePerformanceTool);
467
905
  }
468
- function buildProtocolUrl(editor, loc) {
469
- const line = loc.line ?? 1;
470
- const col = loc.column ?? 1;
471
- switch (editor) {
472
- case "cursor":
473
- return `cursor://file/${loc.file}:${line}:${col}`;
474
- case "webstorm":
475
- return `webstorm://open?file=${encodeURIComponent(loc.file)}&line=${line}&column=${col}`;
476
- case "zed":
477
- return `zed://file/${loc.file}:${line}:${col}`;
478
- case "vscode":
479
- case "auto":
480
- default:
481
- return `vscode://file/${loc.file}:${line}:${col}`;
482
- }
483
- }
484
- var defaultOpenInEditor = async (loc, editor = "auto") => {
485
- const url = buildProtocolUrl(editor, loc);
486
- if (url && typeof window !== "undefined") {
487
- try {
488
- window.location.assign(url);
489
- return true;
490
- } catch {
491
- }
492
- }
493
- if (typeof navigator !== "undefined" && navigator.clipboard) {
494
- await navigator.clipboard.writeText(`${loc.file}${loc.line ? `:${loc.line}` : ""}`).catch(() => void 0);
495
- }
496
- return false;
497
- };
498
- var DevPanelContext = createContext(null);
499
- function resolve(config) {
500
- const enabled = config.enabled ?? (typeof process !== "undefined" ? process.env.NODE_ENV !== "production" : true);
501
- return {
502
- enabled,
503
- editor: config.editor ?? "auto",
504
- getRoute: config.getRoute ?? (() => typeof location !== "undefined" ? location.pathname : void 0),
505
- openInEditor: config.openInEditor ?? defaultOpenInEditor,
506
- graphEndpoint: config.graphEndpoint,
507
- theme: config.theme ?? {},
508
- tools: config.tools
509
- };
510
- }
511
- function DevPanelConfigProvider({
512
- config,
513
- children
514
- }) {
515
- const value = useMemo(() => resolve(config), [config]);
516
- return /* @__PURE__ */ jsx(DevPanelContext.Provider, { value, children });
517
- }
518
- function useDevPanelConfig() {
519
- const ctx = useContext(DevPanelContext);
520
- if (!ctx) throw new Error("useDevPanelConfig must be used within <DevPanel> / DevPanelConfigProvider");
521
- return ctx;
522
- }
523
906
  function GraphSearch({
524
907
  value,
525
908
  onChange,
526
909
  placeholder = "Search components\u2026"
527
910
  }) {
528
- return /* @__PURE__ */ jsxs("div", { className: "rdp-input", children: [
529
- /* @__PURE__ */ jsx("span", { style: { color: "var(--rdp-text-faint)", display: "grid", placeItems: "center" }, children: /* @__PURE__ */ jsx(IconSearch, { size: 15 }) }),
530
- /* @__PURE__ */ jsx("input", { value, onChange: (e) => onChange(e.target.value), placeholder, "aria-label": "Search components" }),
531
- value && /* @__PURE__ */ jsx("button", { type: "button", className: "rdp-iconbtn-bare", onClick: () => onChange(""), "aria-label": "Clear", children: /* @__PURE__ */ jsx(IconX, { size: 14 }) })
532
- ] });
911
+ return /* @__PURE__ */ jsx(
912
+ TextField,
913
+ {
914
+ size: "small",
915
+ fullWidth: true,
916
+ placeholder,
917
+ value,
918
+ onChange: (e) => onChange(e.target.value),
919
+ slotProps: {
920
+ input: {
921
+ startAdornment: /* @__PURE__ */ jsx(InputAdornment, { position: "start", children: /* @__PURE__ */ jsx(LuSearch, { size: 15 }) })
922
+ }
923
+ }
924
+ }
925
+ );
533
926
  }
927
+ var EDITORS = [
928
+ { key: "vscode", label: "VS Code" },
929
+ { key: "cursor", label: "Cursor" },
930
+ { key: "webstorm", label: "WebStorm" }
931
+ ];
534
932
  function Chips({ names, onSelect }) {
535
- return /* @__PURE__ */ jsx("span", { style: { display: "flex", flexWrap: "wrap", gap: 4 }, children: names.map((n) => /* @__PURE__ */ jsx(
536
- "button",
537
- {
538
- type: "button",
539
- className: "rdp-chip rdp-mono",
540
- style: { border: "1px solid var(--rdp-border)", background: "transparent", color: "var(--rdp-text)", cursor: "pointer" },
541
- onClick: () => onSelect(n),
542
- children: n
543
- },
544
- n
545
- )) });
933
+ return /* @__PURE__ */ jsx(Stack, { direction: "row", spacing: 0.5, useFlexGap: true, sx: { flexWrap: "wrap" }, children: names.map((n) => /* @__PURE__ */ jsx(Chip, { label: n, size: "small", variant: "outlined", onClick: () => onSelect(n), sx: { height: 18, fontSize: "0.62rem", fontFamily: "monospace" } }, n)) });
546
934
  }
547
935
  function Row({ label, children }) {
548
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8, marginTop: 5 }, children: [
549
- /* @__PURE__ */ jsx("span", { style: { minWidth: 52, color: "var(--rdp-text-faint)", fontWeight: 600, flexShrink: 0, fontSize: 11 }, children: label }),
550
- /* @__PURE__ */ jsx("span", { style: { minWidth: 0, flex: 1 }, children })
936
+ return /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, sx: { mt: 0.5 }, children: [
937
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { minWidth: 56, color: "text.disabled", fontWeight: 600, flexShrink: 0 }, children: label }),
938
+ /* @__PURE__ */ jsx(Box6, { sx: { minWidth: 0, flex: 1 }, children })
551
939
  ] });
552
940
  }
553
941
  function NodeDetails({
554
942
  selected,
943
+ editor,
555
944
  onOpen,
945
+ onOpenEditor,
556
946
  onCopyInfo,
557
947
  onCopyPath,
558
948
  onSelectName
559
949
  }) {
560
950
  if (!selected) {
561
- return /* @__PURE__ */ jsx("div", { style: { color: "var(--rdp-text-faint)", padding: "6px 2px" }, children: "Nothing selected. Enable inspect mode and click a component, or pick one from the tree." });
951
+ return /* @__PURE__ */ jsx(Typography3, { variant: "body2", sx: { color: "text.disabled", px: 0.5, py: 1 }, children: "Nothing selected. Enable inspect mode and click a component, or pick one from the tree." });
562
952
  }
563
- return /* @__PURE__ */ jsxs(
564
- "div",
565
- {
566
- style: {
567
- padding: 10,
568
- borderRadius: 9,
569
- border: "1px solid var(--rdp-border)",
570
- background: "var(--rdp-bg-soft)"
571
- },
572
- children: [
573
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
574
- /* @__PURE__ */ jsx("span", { className: "rdp-chip", style: { background: "rgba(105,80,232,0.22)", color: "var(--rdp-accent)" }, children: selected.componentName }),
575
- selected.domTag && /* @__PURE__ */ jsx("span", { className: "rdp-mono", style: { color: "var(--rdp-text-faint)", fontSize: 11 }, children: `<${selected.domTag}>` })
576
- ] }),
577
- selected.filePath ? /* @__PURE__ */ jsxs("div", { className: "rdp-mono", style: { marginTop: 6, fontSize: 11.5, color: "var(--rdp-text-dim)", wordBreak: "break-all" }, children: [
578
- selected.filePath,
579
- selected.line ? `:${selected.line}` : "",
580
- selected.line && selected.column ? `:${selected.column}` : ""
581
- ] }) : /* @__PURE__ */ jsx("div", { style: { marginTop: 6, fontSize: 11.5, color: "var(--rdp-warning)" }, children: "No source path \u2014 run the graph generator (npx dev-panel-graph) or mount an adapter." }),
582
- selected.route && /* @__PURE__ */ jsx(Row, { label: "Route", children: /* @__PURE__ */ jsx("span", { className: "rdp-mono", style: { fontSize: 12 }, children: selected.route }) }),
583
- selected.parent && /* @__PURE__ */ jsx(Row, { label: "Parent", children: /* @__PURE__ */ jsx(Chips, { names: [selected.parent], onSelect: onSelectName }) }),
584
- selected.children.length > 0 && /* @__PURE__ */ jsx(Row, { label: "Renders", children: /* @__PURE__ */ jsx(Chips, { names: selected.children, onSelect: onSelectName }) }),
585
- selected.imports.length > 0 && /* @__PURE__ */ jsx(Row, { label: "Imports", children: /* @__PURE__ */ jsx(Chips, { names: selected.imports, onSelect: onSelectName }) }),
586
- selected.props && selected.props.length > 0 && /* @__PURE__ */ jsx(Row, { label: "Props", children: /* @__PURE__ */ jsx("span", { className: "rdp-mono", style: { fontSize: 11, color: "var(--rdp-text-dim)" }, children: selected.props.map((p) => /* @__PURE__ */ jsxs("span", { style: { marginRight: 8, display: "inline-block" }, children: [
587
- /* @__PURE__ */ jsx("span", { style: { color: "var(--rdp-accent)" }, children: p.name }),
588
- "=",
589
- p.value
590
- ] }, p.name)) }) }),
591
- /* @__PURE__ */ jsxs("button", { type: "button", className: cx("rdp-btn", "rdp-btn-primary"), style: { marginTop: 12 }, onClick: onOpen, children: [
592
- /* @__PURE__ */ jsx(IconFileCode, { size: 14 }),
593
- " Open in editor"
594
- ] }),
595
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8, marginTop: 8 }, children: [
596
- /* @__PURE__ */ jsx("button", { type: "button", className: "rdp-iconbtn", onClick: onCopyInfo, title: "Copy component info", children: /* @__PURE__ */ jsx(IconCopy, { size: 15 }) }),
597
- /* @__PURE__ */ jsx(
598
- "button",
599
- {
600
- type: "button",
601
- className: "rdp-iconbtn",
602
- onClick: onCopyPath,
603
- disabled: !selected.filePath && !selected.absFilePath,
604
- title: "Copy file path",
605
- children: /* @__PURE__ */ jsx(IconFileCode, { size: 15 })
606
- }
607
- )
608
- ] })
609
- ]
610
- }
611
- );
953
+ return /* @__PURE__ */ jsxs(Box6, { sx: (t) => ({ p: 1.25, borderRadius: 1.5, border: "1px solid", borderColor: "divider", bgcolor: alpha(t.palette.grey[500], 0.06) }), children: [
954
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", spacing: 0.75, children: [
955
+ /* @__PURE__ */ jsx(Chip, { label: selected.componentName, size: "small", color: "primary", variant: "soft", sx: { height: 20, fontSize: "0.68rem", fontWeight: 700 } }),
956
+ selected.domTag && /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { color: "text.disabled", fontFamily: "monospace" }, children: `<${selected.domTag}>` })
957
+ ] }),
958
+ selected.filePath ? /* @__PURE__ */ jsxs(Typography3, { variant: "caption", sx: { display: "block", mt: 0.75, fontFamily: "monospace", fontSize: "0.68rem", wordBreak: "break-all", color: "text.secondary" }, children: [
959
+ selected.filePath,
960
+ selected.line ? `:${selected.line}` : "",
961
+ selected.line && selected.column ? `:${selected.column}` : ""
962
+ ] }) : /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { display: "block", mt: 0.75, color: "warning.main" }, children: "No source path \u2014 run the graph generator (npx dev-panel-graph) or mount an adapter." }),
963
+ selected.route && /* @__PURE__ */ jsx(Row, { label: "Route", children: /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { fontFamily: "monospace" }, children: selected.route }) }),
964
+ selected.parent && /* @__PURE__ */ jsx(Row, { label: "Parent", children: /* @__PURE__ */ jsx(Chips, { names: [selected.parent], onSelect: onSelectName }) }),
965
+ selected.children.length > 0 && /* @__PURE__ */ jsx(Row, { label: "Renders", children: /* @__PURE__ */ jsx(Chips, { names: selected.children, onSelect: onSelectName }) }),
966
+ selected.imports.length > 0 && /* @__PURE__ */ jsx(Row, { label: "Imports", children: /* @__PURE__ */ jsx(Chips, { names: selected.imports, onSelect: onSelectName }) }),
967
+ selected.props && selected.props.length > 0 && /* @__PURE__ */ jsx(Row, { label: "Props", children: /* @__PURE__ */ jsx(Box6, { sx: { fontFamily: "monospace", fontSize: "0.66rem", color: "text.secondary" }, children: selected.props.map((p) => /* @__PURE__ */ jsxs(Box6, { component: "span", sx: { mr: 1, display: "inline-block" }, children: [
968
+ /* @__PURE__ */ jsx(Box6, { component: "span", sx: { color: "primary.main" }, children: p.name }),
969
+ "=",
970
+ p.value
971
+ ] }, p.name)) }) }),
972
+ /* @__PURE__ */ jsx(Button, { fullWidth: true, variant: "contained", startIcon: /* @__PURE__ */ jsx(LuFileCode, { size: 14 }), onClick: onOpen, sx: { textTransform: "none", fontSize: "0.72rem", py: 0.4, mt: 1.25 }, children: "Open in editor" }),
973
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", spacing: 0.5, useFlexGap: true, sx: { flexWrap: "wrap", mt: 0.75 }, children: [
974
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { color: "text.disabled" }, children: "force:" }),
975
+ EDITORS.map((opt) => /* @__PURE__ */ jsx(
976
+ Button,
977
+ {
978
+ size: "small",
979
+ variant: opt.key === editor ? "contained" : "text",
980
+ startIcon: /* @__PURE__ */ jsx(LuLink, { size: 12 }),
981
+ onClick: () => onOpenEditor(opt.key),
982
+ sx: { textTransform: "none", fontSize: "0.66rem", py: 0.1, minWidth: 0 },
983
+ children: opt.label
984
+ },
985
+ opt.key
986
+ ))
987
+ ] }),
988
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, sx: { mt: 1 }, children: [
989
+ /* @__PURE__ */ jsx(Tooltip2, { title: "Copy component info", placement: "top", children: /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: onCopyInfo, sx: { border: "1px solid", borderColor: "divider", borderRadius: 1 }, children: /* @__PURE__ */ jsx(LuClipboardCopy, { size: 15 }) }) }),
990
+ /* @__PURE__ */ jsx(Tooltip2, { title: "Copy file path", placement: "top", children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: onCopyPath, disabled: !selected.filePath && !selected.absFilePath, sx: { border: "1px solid", borderColor: "divider", borderRadius: 1 }, children: /* @__PURE__ */ jsx(LuCopy, { size: 15 }) }) }) })
991
+ ] })
992
+ ] });
612
993
  }
613
994
 
614
995
  // src/tools/component-graph/graph-utils.ts
@@ -875,27 +1256,23 @@ function formatForCopy(s) {
875
1256
  }
876
1257
  var MAX_DEPTH = 6;
877
1258
  function Label({ children }) {
878
- return /* @__PURE__ */ jsx("span", { className: "rdp-section-label", children });
1259
+ return /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { display: "block", mt: 1, mb: 0.25, color: "text.disabled", fontWeight: 700, textTransform: "uppercase", letterSpacing: 0.4, fontSize: "0.6rem" }, children });
879
1260
  }
880
- function RowActions({
881
- node,
882
- onOpen,
883
- onCopy
884
- }) {
885
- return /* @__PURE__ */ jsxs("span", { style: { display: "inline-flex", gap: 2 }, children: [
886
- /* @__PURE__ */ jsx("button", { type: "button", className: "rdp-iconbtn-bare", title: "Open in editor", onClick: (e) => {
1261
+ function RowActions({ node, onOpen, onCopy }) {
1262
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1263
+ /* @__PURE__ */ jsx(Tooltip2, { title: "Open in editor", placement: "top", children: /* @__PURE__ */ jsx(IconButton, { size: "small", sx: { p: 0.25 }, onClick: (e) => {
887
1264
  e.stopPropagation();
888
1265
  onOpen(node);
889
- }, children: /* @__PURE__ */ jsx(IconFileCode, { size: 13 }) }),
890
- /* @__PURE__ */ jsx("button", { type: "button", className: "rdp-iconbtn-bare", title: "Copy file path", onClick: (e) => {
1266
+ }, children: /* @__PURE__ */ jsx(LuFileCode, { size: 13 }) }) }),
1267
+ /* @__PURE__ */ jsx(Tooltip2, { title: "Copy file path", placement: "top", children: /* @__PURE__ */ jsx(IconButton, { size: "small", sx: { p: 0.25 }, onClick: (e) => {
891
1268
  e.stopPropagation();
892
1269
  onCopy(node);
893
- }, children: /* @__PURE__ */ jsx(IconCopy, { size: 13 }) })
1270
+ }, children: /* @__PURE__ */ jsx(LuCopy, { size: 13 }) }) })
894
1271
  ] });
895
1272
  }
896
1273
  function RowShell({
897
1274
  depth = 0,
898
- active,
1275
+ active = false,
899
1276
  caret,
900
1277
  label,
901
1278
  isRoute,
@@ -903,42 +1280,43 @@ function RowShell({
903
1280
  actions
904
1281
  }) {
905
1282
  return /* @__PURE__ */ jsxs(
906
- "div",
1283
+ Stack,
907
1284
  {
908
- className: "rdp-row",
909
- style: {
910
- padding: "3px 6px",
911
- paddingLeft: 6 + depth * 14,
912
- gap: 4,
913
- alignItems: "center",
914
- background: active ? "rgba(105,80,232,0.16)" : void 0
915
- },
1285
+ direction: "row",
1286
+ alignItems: "center",
1287
+ spacing: 0.5,
1288
+ sx: (t) => ({
1289
+ pl: 0.5 + depth * 1.5,
1290
+ pr: 0.5,
1291
+ py: 0.25,
1292
+ borderRadius: 1,
1293
+ bgcolor: active ? alpha(t.palette.primary.main, 0.16) : "transparent",
1294
+ "&:hover": { bgcolor: active ? alpha(t.palette.primary.main, 0.2) : "action.hover" },
1295
+ "&:hover .rdp-row-actions": { opacity: 1 }
1296
+ }),
916
1297
  children: [
917
- /* @__PURE__ */ jsx("span", { style: { width: 16, display: "grid", placeItems: "center", color: "var(--rdp-text-faint)" }, children: caret }),
1298
+ /* @__PURE__ */ jsx(Box6, { sx: { width: 16, display: "grid", placeItems: "center", color: "text.disabled" }, children: caret }),
918
1299
  /* @__PURE__ */ jsx(
919
- "button",
1300
+ Typography3,
920
1301
  {
921
- type: "button",
922
1302
  onClick: onLabel,
923
- className: "rdp-mono",
924
- style: {
1303
+ variant: "caption",
1304
+ sx: {
925
1305
  flex: 1,
926
1306
  minWidth: 0,
927
- textAlign: "left",
928
- background: "none",
929
- border: "none",
930
1307
  cursor: "pointer",
931
- fontSize: 12,
932
1308
  fontWeight: active ? 700 : 500,
933
- color: isRoute ? "var(--rdp-info)" : active ? "var(--rdp-accent)" : "var(--rdp-text)",
934
- whiteSpace: "nowrap",
1309
+ fontFamily: "monospace",
1310
+ fontSize: "0.72rem",
935
1311
  overflow: "hidden",
936
- textOverflow: "ellipsis"
1312
+ textOverflow: "ellipsis",
1313
+ whiteSpace: "nowrap",
1314
+ color: isRoute ? "info.main" : active ? "primary.main" : "text.primary"
937
1315
  },
938
1316
  children: label
939
1317
  }
940
1318
  ),
941
- actions
1319
+ actions && /* @__PURE__ */ jsx(Stack, { direction: "row", spacing: 0.25, className: "rdp-row-actions", sx: { opacity: 0, transition: "opacity 120ms" }, children: actions })
942
1320
  ]
943
1321
  }
944
1322
  );
@@ -950,14 +1328,14 @@ function Branch({ name, depth, trail, p }) {
950
1328
  const hasKids = kids.length > 0 && depth < MAX_DEPTH && !trail.has(id);
951
1329
  const open = p.expanded.has(id);
952
1330
  const active = p.selected?.nodeId === id || p.selected?.componentName === name;
953
- return /* @__PURE__ */ jsxs("div", { children: [
1331
+ return /* @__PURE__ */ jsxs(Box6, { children: [
954
1332
  /* @__PURE__ */ jsx(
955
1333
  RowShell,
956
1334
  {
957
1335
  depth,
958
1336
  active,
959
1337
  isRoute: node?.type === "route",
960
- caret: hasKids ? /* @__PURE__ */ jsx("span", { style: { cursor: "pointer" }, onClick: () => p.onToggle(id), children: open ? /* @__PURE__ */ jsx(IconChevronDown, { size: 13 }) : /* @__PURE__ */ jsx(IconChevronRight, { size: 13 }) }) : null,
1338
+ caret: hasKids ? /* @__PURE__ */ jsx(Box6, { sx: { cursor: "pointer", display: "grid", placeItems: "center" }, onClick: () => p.onToggle(id), children: open ? /* @__PURE__ */ jsx(LuChevronDown, { size: 13 }) : /* @__PURE__ */ jsx(LuChevronRight, { size: 13 }) }) : null,
961
1339
  label: name,
962
1340
  onLabel: () => node && p.onSelect(node),
963
1341
  actions: node ? /* @__PURE__ */ jsx(RowActions, { node, onOpen: p.onOpen, onCopy: p.onCopy }) : null
@@ -970,7 +1348,7 @@ function ComponentGraphTree(p) {
970
1348
  const { graph, selected, search } = p;
971
1349
  if (graph && search.trim()) {
972
1350
  const results = searchNodes(graph, search);
973
- return /* @__PURE__ */ jsxs("div", { children: [
1351
+ return /* @__PURE__ */ jsxs(Box6, { children: [
974
1352
  /* @__PURE__ */ jsxs(Label, { children: [
975
1353
  results.length,
976
1354
  " match",
@@ -987,7 +1365,7 @@ function ComponentGraphTree(p) {
987
1365
  },
988
1366
  node.id
989
1367
  )),
990
- results.length === 0 && /* @__PURE__ */ jsxs("div", { style: { color: "var(--rdp-text-faint)", paddingLeft: 8 }, children: [
1368
+ results.length === 0 && /* @__PURE__ */ jsxs(Typography3, { variant: "caption", sx: { color: "text.disabled", pl: 1 }, children: [
991
1369
  "No components match \u201C",
992
1370
  search,
993
1371
  "\u201D."
@@ -995,9 +1373,9 @@ function ComponentGraphTree(p) {
995
1373
  ] });
996
1374
  }
997
1375
  if (!selected) {
998
- return /* @__PURE__ */ jsx("div", { style: { color: "var(--rdp-text-faint)", padding: "8px 2px" }, children: "Lock a component (hover + click) or search above to explore the tree." });
1376
+ return /* @__PURE__ */ jsx(Typography3, { variant: "body2", sx: { color: "text.disabled", px: 0.5, py: 1 }, children: "Lock a component (hover + click) or search above to explore the tree." });
999
1377
  }
1000
- return /* @__PURE__ */ jsxs("div", { children: [
1378
+ return /* @__PURE__ */ jsxs(Box6, { children: [
1001
1379
  selected.parents.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
1002
1380
  /* @__PURE__ */ jsx(Label, { children: "Parent chain" }),
1003
1381
  selected.parents.map((parent) => {
@@ -1006,7 +1384,7 @@ function ComponentGraphTree(p) {
1006
1384
  RowShell,
1007
1385
  {
1008
1386
  isRoute: node?.type === "route",
1009
- caret: /* @__PURE__ */ jsx(IconArrowUp, { size: 12 }),
1387
+ caret: /* @__PURE__ */ jsx(LuArrowUp, { size: 12 }),
1010
1388
  label: parent,
1011
1389
  onLabel: () => node && p.onSelect(node),
1012
1390
  actions: node ? /* @__PURE__ */ jsx(RowActions, { node, onOpen: p.onOpen, onCopy: p.onCopy }) : null
@@ -1016,13 +1394,13 @@ function ComponentGraphTree(p) {
1016
1394
  })
1017
1395
  ] }),
1018
1396
  /* @__PURE__ */ jsx(Label, { children: "Selected" }),
1019
- /* @__PURE__ */ jsx(RowShell, { active: true, label: selected.componentName, onLabel: () => void 0 }),
1397
+ /* @__PURE__ */ jsx(RowShell, { active: true, label: selected.componentName, onLabel: () => void 0, actions: /* @__PURE__ */ jsx(Chip, { size: "small", variant: "soft", color: "primary", label: selected.source, sx: { height: 16, fontSize: "0.55rem", fontWeight: 700 } }) }),
1020
1398
  /* @__PURE__ */ jsxs(Label, { children: [
1021
1399
  "Renders (",
1022
1400
  selected.children.length,
1023
1401
  ")"
1024
1402
  ] }),
1025
- selected.children.length === 0 ? /* @__PURE__ */ jsx("div", { style: { color: "var(--rdp-text-faint)", paddingLeft: 20 }, children: "No child components detected." }) : selected.children.map((c) => /* @__PURE__ */ jsx(Branch, { name: c, depth: 0, trail: new Set(selected.nodeId ? [selected.nodeId] : []), p }, `c:${c}`)),
1403
+ selected.children.length === 0 ? /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { color: "text.disabled", pl: 1.5 }, children: "No child components detected." }) : selected.children.map((c) => /* @__PURE__ */ jsx(Branch, { name: c, depth: 0, trail: new Set(selected.nodeId ? [selected.nodeId] : []), p }, `c:${c}`)),
1026
1404
  selected.imports.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
1027
1405
  /* @__PURE__ */ jsxs(Label, { children: [
1028
1406
  "Imports (",
@@ -1069,56 +1447,60 @@ function ComponentGraphPageList({
1069
1447
  };
1070
1448
  }, [scan, route]);
1071
1449
  if (!graph) {
1072
- return /* @__PURE__ */ jsx("div", { style: { color: "var(--rdp-text-faint)", padding: "6px 2px" }, children: "Load the component graph (Graph tab) to map mounted components to source files." });
1450
+ return /* @__PURE__ */ jsx(Typography3, { variant: "body2", sx: { color: "text.disabled", px: 0.5, py: 1 }, children: "Load the component graph (Graph tab) to map mounted components to source files." });
1073
1451
  }
1074
1452
  const q = query.trim().toLowerCase();
1075
1453
  const filtered = q ? items.filter((i) => i.name.toLowerCase().includes(q) || i.node.filePath.toLowerCase().includes(q)) : items;
1076
- return /* @__PURE__ */ jsxs("div", { children: [
1077
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 6 }, children: [
1078
- /* @__PURE__ */ jsxs("span", { className: "rdp-sub", children: [
1079
- /* @__PURE__ */ jsx("span", { className: "rdp-mono", style: { color: "var(--rdp-info)" }, children: route ?? "/" }),
1080
- " \xB7",
1454
+ return /* @__PURE__ */ jsxs(Box6, { children: [
1455
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", sx: { mb: 0.5 }, children: [
1456
+ /* @__PURE__ */ jsxs(Typography3, { variant: "caption", sx: { color: "text.secondary" }, children: [
1457
+ /* @__PURE__ */ jsx(Box6, { component: "span", sx: { fontFamily: "monospace", color: "info.main" }, children: route ?? "/" }),
1081
1458
  " ",
1459
+ "\xB7 ",
1082
1460
  q ? `${filtered.length} / ${items.length}` : items.length,
1083
1461
  " component",
1084
1462
  items.length === 1 ? "" : "s"
1085
1463
  ] }),
1086
- /* @__PURE__ */ jsxs("button", { type: "button", className: "rdp-btn rdp-btn-sm", onClick: scan, children: [
1087
- /* @__PURE__ */ jsx(IconRefresh, { size: 13 }),
1088
- " Rescan"
1089
- ] })
1464
+ /* @__PURE__ */ jsx(Button, { size: "small", startIcon: /* @__PURE__ */ jsx(LuRefreshCw, { size: 13 }), onClick: scan, sx: { textTransform: "none", fontSize: "0.7rem", py: 0.25 }, children: "Rescan" })
1090
1465
  ] }),
1091
- /* @__PURE__ */ jsx("div", { style: { marginBottom: 8 }, children: /* @__PURE__ */ jsx(GraphSearch, { value: query, onChange: setQuery, placeholder: "Filter components on this page\u2026" }) }),
1092
- items.length === 0 ? /* @__PURE__ */ jsx("div", { style: { color: "var(--rdp-text-faint)", paddingLeft: 4 }, children: "No graph components detected in the live tree. Try Rescan, or regenerate the graph." }) : filtered.length === 0 ? /* @__PURE__ */ jsxs("div", { style: { color: "var(--rdp-text-faint)", paddingLeft: 4 }, children: [
1466
+ /* @__PURE__ */ jsx(Box6, { sx: { mb: 1 }, children: /* @__PURE__ */ jsx(GraphSearch, { value: query, onChange: setQuery, placeholder: "Filter components on this page\u2026" }) }),
1467
+ items.length === 0 ? /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { color: "text.disabled", pl: 0.5 }, children: "No graph components detected in the live tree. Try Rescan, or regenerate the graph." }) : filtered.length === 0 ? /* @__PURE__ */ jsxs(Typography3, { variant: "caption", sx: { color: "text.disabled", pl: 0.5 }, children: [
1093
1468
  "No components match \u201C",
1094
1469
  query,
1095
1470
  "\u201D."
1096
1471
  ] }) : filtered.map(({ name, node, count }) => /* @__PURE__ */ jsxs(
1097
- "div",
1472
+ Stack,
1098
1473
  {
1099
- className: "rdp-row",
1100
- style: { padding: "4px 6px", alignItems: "center", background: selectedName === name ? "rgba(105,80,232,0.16)" : void 0 },
1474
+ direction: "row",
1475
+ alignItems: "center",
1476
+ spacing: 0.5,
1101
1477
  onClick: () => onSelect(node),
1478
+ sx: (t) => ({
1479
+ px: 0.5,
1480
+ py: 0.4,
1481
+ borderRadius: 1,
1482
+ cursor: "pointer",
1483
+ bgcolor: selectedName === name ? alpha(t.palette.primary.main, 0.16) : "transparent",
1484
+ "&:hover": { bgcolor: "action.hover" },
1485
+ "&:hover .rdp-row-actions": { opacity: 1 }
1486
+ }),
1102
1487
  children: [
1103
- /* @__PURE__ */ jsxs("span", { style: { flex: 1, minWidth: 0 }, children: [
1104
- /* @__PURE__ */ jsxs("span", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
1105
- /* @__PURE__ */ jsx("span", { className: "rdp-mono", style: { fontWeight: 600, fontSize: 12, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: name }),
1106
- count > 1 && /* @__PURE__ */ jsxs("span", { className: "rdp-chip", style: { background: "var(--rdp-bg-soft)", color: "var(--rdp-text-dim)", height: 15 }, children: [
1107
- "\xD7",
1108
- count
1109
- ] })
1488
+ /* @__PURE__ */ jsxs(Box6, { sx: { flex: 1, minWidth: 0 }, children: [
1489
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", spacing: 0.5, children: [
1490
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { fontFamily: "monospace", fontWeight: 600, fontSize: "0.72rem", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: name }),
1491
+ count > 1 && /* @__PURE__ */ jsx(Chip, { label: `\xD7${count}`, size: "small", variant: "soft", sx: { height: 15, fontSize: "0.55rem", "& .MuiChip-label": { px: 0.5 } } })
1110
1492
  ] }),
1111
- /* @__PURE__ */ jsx("span", { style: { display: "block", color: "var(--rdp-text-faint)", fontSize: 11, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: node.filePath })
1493
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { display: "block", color: "text.disabled", fontSize: "0.62rem", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: node.filePath })
1112
1494
  ] }),
1113
- /* @__PURE__ */ jsxs("span", { style: { display: "inline-flex", gap: 2 }, children: [
1114
- /* @__PURE__ */ jsx("button", { type: "button", className: "rdp-iconbtn-bare", title: "Open in editor", onClick: (e) => {
1495
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 0.25, className: "rdp-row-actions", sx: { opacity: 0, transition: "opacity 120ms" }, children: [
1496
+ /* @__PURE__ */ jsx(Tooltip2, { title: "Open in editor", placement: "top", children: /* @__PURE__ */ jsx(IconButton, { size: "small", sx: { p: 0.25 }, onClick: (e) => {
1115
1497
  e.stopPropagation();
1116
1498
  onOpen(node);
1117
- }, children: /* @__PURE__ */ jsx(IconFileCode, { size: 13 }) }),
1118
- /* @__PURE__ */ jsx("button", { type: "button", className: "rdp-iconbtn-bare", title: "Copy file path", onClick: (e) => {
1499
+ }, children: /* @__PURE__ */ jsx(LuFileCode, { size: 13 }) }) }),
1500
+ /* @__PURE__ */ jsx(Tooltip2, { title: "Copy file path", placement: "top", children: /* @__PURE__ */ jsx(IconButton, { size: "small", sx: { p: 0.25 }, onClick: (e) => {
1119
1501
  e.stopPropagation();
1120
1502
  onCopy(node);
1121
- }, children: /* @__PURE__ */ jsx(IconCopy, { size: 13 }) })
1503
+ }, children: /* @__PURE__ */ jsx(LuCopy, { size: 13 }) }) })
1122
1504
  ] })
1123
1505
  ]
1124
1506
  },
@@ -1220,10 +1602,10 @@ function loadGraph(endpoint, force = false) {
1220
1602
  return graphPromise;
1221
1603
  }
1222
1604
  var TABS = [
1223
- { value: "hover", label: "Hover", icon: /* @__PURE__ */ jsx(IconPointer, { size: 14 }) },
1224
- { value: "graph", label: "Graph", icon: /* @__PURE__ */ jsx(IconGraph, { size: 14 }) },
1225
- { value: "page", label: "Page", icon: /* @__PURE__ */ jsx(IconLayers, { size: 14 }) },
1226
- { value: "file", label: "File", icon: /* @__PURE__ */ jsx(IconFileCode, { size: 14 }) }
1605
+ { value: "hover", label: "Hover", icon: /* @__PURE__ */ jsx(LuMousePointerClick, { size: 14 }) },
1606
+ { value: "graph", label: "Graph", icon: /* @__PURE__ */ jsx(LuWorkflow, { size: 14 }) },
1607
+ { value: "page", label: "Page", icon: /* @__PURE__ */ jsx(LuLayers, { size: 14 }) },
1608
+ { value: "file", label: "File", icon: /* @__PURE__ */ jsx(LuFile, { size: 14 }) }
1227
1609
  ];
1228
1610
  async function copy(text) {
1229
1611
  if (typeof navigator === "undefined" || !navigator.clipboard) return false;
@@ -1234,17 +1616,15 @@ async function copy(text) {
1234
1616
  }
1235
1617
  function ComponentGraphPanel({ onClose }) {
1236
1618
  const state2 = useSyncExternalStore(subscribeGraph, getGraphState, getGraphServerState);
1619
+ const theme = useTheme();
1237
1620
  const config = useDevPanelConfig();
1238
1621
  const route = config.getRoute();
1239
1622
  const { enabled, mode, selected, graph, status, search, expanded } = state2;
1240
1623
  const openLoc = useCallback(
1241
- async (sel) => {
1624
+ async (sel, editor) => {
1242
1625
  const file = sel?.absFilePath ?? sel?.filePath;
1243
- if (!file) {
1244
- showToast({ message: "No source path available", tone: "error" });
1245
- return;
1246
- }
1247
- const ok = await config.openInEditor?.({ file, line: sel?.line, column: sel?.column }, config.editor);
1626
+ if (!file) return showToast({ message: "No source path available", tone: "error" });
1627
+ const ok = await config.openInEditor?.({ file, line: sel?.line, column: sel?.column }, editor ?? config.editor);
1248
1628
  showToast(ok === false ? { message: "Editor unavailable \u2014 path copied", tone: "info" } : { message: "Opening in your editor\u2026", tone: "success" });
1249
1629
  },
1250
1630
  [config]
@@ -1253,14 +1633,11 @@ function ComponentGraphPanel({ onClose }) {
1253
1633
  if (!selected) return;
1254
1634
  void copy(formatForCopy(selected)).then((ok) => showToast({ message: ok ? "Component info copied" : "Copy failed", tone: ok ? "success" : "error" }));
1255
1635
  }, [selected]);
1256
- const copyPath = useCallback(
1257
- (sel) => {
1258
- const path = sel?.filePath ?? sel?.absFilePath;
1259
- if (!path) return showToast({ message: "No path to copy", tone: "info" });
1260
- void copy(`${path}${sel?.line ? `:${sel.line}` : ""}`).then((ok) => showToast({ message: ok ? "File path copied" : "Copy failed", tone: ok ? "success" : "error" }));
1261
- },
1262
- []
1263
- );
1636
+ const copyPath = useCallback((sel) => {
1637
+ const path = sel?.filePath ?? sel?.absFilePath;
1638
+ if (!path) return showToast({ message: "No path to copy", tone: "info" });
1639
+ void copy(`${path}${sel?.line ? `:${sel.line}` : ""}`).then((ok) => showToast({ message: ok ? "File path copied" : "Copy failed", tone: ok ? "success" : "error" }));
1640
+ }, []);
1264
1641
  const selectName = useCallback(
1265
1642
  (name) => {
1266
1643
  const node = graph?.nodes.find((n) => n.name === name || n.id === name);
@@ -1281,126 +1658,120 @@ function ComponentGraphPanel({ onClose }) {
1281
1658
  NodeDetails,
1282
1659
  {
1283
1660
  selected,
1661
+ editor: config.editor,
1284
1662
  onOpen: () => void openLoc(selected),
1663
+ onOpenEditor: (editor) => void openLoc(selected, editor),
1285
1664
  onCopyInfo: copyInfo,
1286
1665
  onCopyPath: () => copyPath(selected),
1287
1666
  onSelectName: selectName
1288
1667
  }
1289
1668
  );
1290
- return /* @__PURE__ */ jsxs("div", { className: "rdp-surface rdp-panel", style: { bottom: 88, right: 20 }, children: [
1291
- /* @__PURE__ */ jsxs("div", { className: "rdp-header", children: [
1292
- /* @__PURE__ */ jsx(IconGraph, { size: 16 }),
1293
- /* @__PURE__ */ jsx("span", { className: "rdp-title", style: { flex: 1 }, children: "Component Graph Inspector" }),
1294
- enabled && /* @__PURE__ */ jsx("span", { className: "rdp-chip", style: { background: "var(--rdp-success)", color: "#06210f" }, children: "ON" }),
1295
- /* @__PURE__ */ jsx("button", { type: "button", className: "rdp-iconbtn-bare", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(IconX, { size: 16 }) })
1296
- ] }),
1297
- /* @__PURE__ */ jsxs("div", { className: "rdp-body", children: [
1298
- /* @__PURE__ */ jsxs(
1299
- "div",
1300
- {
1301
- style: {
1302
- padding: 12,
1303
- borderRadius: 9,
1304
- border: `1px solid ${enabled ? "rgba(61,220,132,0.5)" : "var(--rdp-border)"}`,
1305
- background: enabled ? "rgba(61,220,132,0.08)" : "var(--rdp-bg-elev)",
1306
- display: "flex",
1307
- alignItems: "center",
1308
- justifyContent: "space-between"
1309
- },
1310
- children: [
1311
- /* @__PURE__ */ jsxs("span", { children: [
1312
- /* @__PURE__ */ jsx("span", { className: "rdp-title", style: { display: "block" }, children: "Inspect mode" }),
1313
- /* @__PURE__ */ jsx("span", { className: "rdp-sub", children: enabled ? "Hover the UI, click to lock \xB7 Esc to exit" : "Enable, then hover the UI" })
1314
- ] }),
1315
- /* @__PURE__ */ jsx(
1316
- "button",
1317
- {
1318
- type: "button",
1319
- className: cx("rdp-btn", enabled && "rdp-btn-primary"),
1320
- style: { width: "auto" },
1321
- onClick: () => toggleInspector(config.graphEndpoint),
1322
- children: enabled ? "On" : "Enable"
1323
- }
1324
- )
1325
- ]
1326
- }
1327
- ),
1328
- /* @__PURE__ */ jsx("div", { className: "rdp-tabs", style: { marginTop: 12 }, children: TABS.map((t) => /* @__PURE__ */ jsxs(
1329
- "button",
1330
- {
1331
- type: "button",
1332
- className: "rdp-tab",
1333
- "aria-selected": mode === t.value,
1334
- onClick: () => {
1335
- setMode(t.value);
1336
- if (t.value === "graph" || t.value === "page") void loadGraph(config.graphEndpoint);
1337
- },
1338
- children: [
1339
- t.icon,
1340
- t.label
1341
- ]
1342
- },
1343
- t.value
1344
- )) }),
1345
- /* @__PURE__ */ jsxs("div", { style: { marginTop: 12 }, children: [
1346
- mode === "hover" && /* @__PURE__ */ jsxs("div", { children: [
1347
- /* @__PURE__ */ jsx("span", { className: "rdp-section-label", children: "Last locked component" }),
1348
- details
1669
+ return /* @__PURE__ */ jsxs(
1670
+ Box6,
1671
+ {
1672
+ "data-rdp-ignore": "",
1673
+ sx: {
1674
+ position: "fixed",
1675
+ bottom: 96,
1676
+ right: 24,
1677
+ zIndex: (t) => t.zIndex.modal + 1,
1678
+ width: "min(460px, calc(100vw - 32px))",
1679
+ maxHeight: "min(78vh, 720px)",
1680
+ display: "flex",
1681
+ flexDirection: "column",
1682
+ borderRadius: 2,
1683
+ overflow: "hidden",
1684
+ border: "1px solid",
1685
+ borderColor: "divider",
1686
+ bgcolor: "background.paper",
1687
+ boxShadow: 12
1688
+ },
1689
+ children: [
1690
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", sx: { px: 1.5, py: 1, borderBottom: "1px solid", borderColor: "divider", flexShrink: 0 }, children: [
1691
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", spacing: 1, children: [
1692
+ /* @__PURE__ */ jsx(LuWorkflow, { size: 16 }),
1693
+ /* @__PURE__ */ jsx(Typography3, { variant: "subtitle2", sx: { fontWeight: 700 }, children: "Component Graph Inspector" }),
1694
+ enabled && /* @__PURE__ */ jsx(Chip, { label: "ON", size: "small", color: "success", variant: "soft", sx: { height: 18, fontSize: "0.6rem", fontWeight: 700 } })
1695
+ ] }),
1696
+ /* @__PURE__ */ jsx(IconButton, { size: "small", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx(LuX, { size: 16 }) })
1349
1697
  ] }),
1350
- mode === "graph" && /* @__PURE__ */ jsxs("div", { children: [
1351
- /* @__PURE__ */ jsx("div", { className: "rdp-sub", style: { marginBottom: 6, color: status === "ready" ? "var(--rdp-success)" : "var(--rdp-text-faint)" }, children: statusText }),
1352
- (status === "empty" || status === "error") && /* @__PURE__ */ jsx("button", { type: "button", className: "rdp-btn rdp-btn-sm", style: { marginBottom: 8 }, onClick: () => loadGraph(config.graphEndpoint, true), children: "Retry graph load" }),
1353
- /* @__PURE__ */ jsx(GraphSearch, { value: search, onChange: setSearch }),
1354
- /* @__PURE__ */ jsx("div", { style: { marginTop: 8 }, children: /* @__PURE__ */ jsx(
1355
- ComponentGraphTree,
1698
+ /* @__PURE__ */ jsxs(Box6, { sx: { flex: 1, overflowY: "auto", p: 1.5 }, children: [
1699
+ /* @__PURE__ */ jsx(
1700
+ Box6,
1356
1701
  {
1357
- graph,
1358
- selected,
1359
- search,
1360
- expanded,
1361
- onSelect: selectNode,
1362
- onToggle: toggleExpanded,
1363
- onOpen: openNode,
1364
- onCopy: copyNode
1702
+ sx: {
1703
+ p: 1.25,
1704
+ borderRadius: 1.5,
1705
+ border: "1px solid",
1706
+ borderColor: enabled ? alpha(theme.palette.success.main, 0.5) : "divider",
1707
+ bgcolor: enabled ? alpha(theme.palette.success.main, 0.08) : "background.default"
1708
+ },
1709
+ children: /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", children: [
1710
+ /* @__PURE__ */ jsxs(Box6, { children: [
1711
+ /* @__PURE__ */ jsx(Typography3, { variant: "body2", sx: { fontWeight: 700 }, children: "Inspect mode" }),
1712
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { color: "text.secondary" }, children: enabled ? "Hover the UI, click to lock \xB7 Esc to exit" : "Enable, then hover the UI" })
1713
+ ] }),
1714
+ /* @__PURE__ */ jsx(Switch, { checked: enabled, onChange: () => toggleInspector(config.graphEndpoint) })
1715
+ ] })
1365
1716
  }
1366
- ) }),
1367
- selected && !search.trim() && /* @__PURE__ */ jsx("div", { style: { marginTop: 12 }, children: details })
1368
- ] }),
1369
- mode === "page" && /* @__PURE__ */ jsxs("div", { children: [
1717
+ ),
1370
1718
  /* @__PURE__ */ jsx(
1371
- ComponentGraphPageList,
1719
+ ToggleButtonGroup,
1372
1720
  {
1373
- graph,
1374
- route,
1375
- selectedName: selected?.componentName,
1376
- onSelect: selectNode,
1377
- onOpen: openNode,
1378
- onCopy: copyNode
1721
+ fullWidth: true,
1722
+ exclusive: true,
1723
+ size: "small",
1724
+ value: mode,
1725
+ onChange: (_, next) => {
1726
+ if (!next) return;
1727
+ setMode(next);
1728
+ if (next === "graph" || next === "page") void loadGraph(config.graphEndpoint);
1729
+ },
1730
+ sx: { mt: 1.5 },
1731
+ children: TABS.map((t) => /* @__PURE__ */ jsxs(ToggleButton, { value: t.value, sx: { textTransform: "none", gap: 0.5, py: 0.5 }, children: [
1732
+ t.icon,
1733
+ t.label
1734
+ ] }, t.value))
1379
1735
  }
1380
1736
  ),
1381
- selected && /* @__PURE__ */ jsx("div", { style: { marginTop: 12 }, children: details })
1382
- ] }),
1383
- mode === "file" && details
1384
- ] })
1385
- ] })
1386
- ] });
1737
+ /* @__PURE__ */ jsx(Divider, { sx: { my: 1.5 } }),
1738
+ mode === "hover" && /* @__PURE__ */ jsxs(Box6, { children: [
1739
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { color: "text.disabled", fontWeight: 700, textTransform: "uppercase", letterSpacing: 0.4 }, children: "Last locked component" }),
1740
+ /* @__PURE__ */ jsx(Box6, { sx: { mt: 0.5 }, children: details })
1741
+ ] }),
1742
+ mode === "graph" && /* @__PURE__ */ jsxs(Box6, { children: [
1743
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { display: "block", mb: 0.5, color: status === "ready" ? "success.main" : "text.disabled" }, children: statusText }),
1744
+ (status === "empty" || status === "error") && /* @__PURE__ */ jsx(Chip, { size: "small", variant: "outlined", label: "Retry graph load", onClick: () => loadGraph(config.graphEndpoint, true), sx: { mb: 1, height: 22, fontSize: "0.65rem" } }),
1745
+ /* @__PURE__ */ jsx(GraphSearch, { value: search, onChange: setSearch }),
1746
+ /* @__PURE__ */ jsx(Box6, { sx: { mt: 1 }, children: /* @__PURE__ */ jsx(ComponentGraphTree, { graph, selected, search, expanded, onSelect: selectNode, onToggle: toggleExpanded, onOpen: openNode, onCopy: copyNode }) }),
1747
+ selected && !search.trim() && /* @__PURE__ */ jsx(Box6, { sx: { mt: 1.5 }, children: details })
1748
+ ] }),
1749
+ mode === "page" && /* @__PURE__ */ jsxs(Box6, { children: [
1750
+ /* @__PURE__ */ jsx(ComponentGraphPageList, { graph, route, selectedName: selected?.componentName, onSelect: selectNode, onOpen: openNode, onCopy: copyNode }),
1751
+ selected && /* @__PURE__ */ jsx(Box6, { sx: { mt: 1.5 }, children: details })
1752
+ ] }),
1753
+ mode === "file" && details
1754
+ ] })
1755
+ ]
1756
+ }
1757
+ );
1387
1758
  }
1759
+ var TOOLTIP_W = 360;
1388
1760
  function ComponentGraphOverlay() {
1389
1761
  const state2 = useSyncExternalStore(subscribeGraph, getGraphState, getGraphServerState);
1762
+ const theme = useTheme();
1390
1763
  const config = useDevPanelConfig();
1391
- const [hover, setHover] = useState(null);
1392
1764
  const route = config.getRoute();
1393
1765
  const { enabled } = state2;
1394
- const openSelected = useCallback(
1395
- async (file, line, column, name) => {
1766
+ const [hover, setHover] = useState(null);
1767
+ const open = useCallback(
1768
+ async (file, line, column) => {
1396
1769
  if (!file) {
1397
- showToast({ message: "No source path \u2014 generate the graph or use inspect build", tone: "error" });
1770
+ showToast({ message: "No source path \u2014 generate the graph", tone: "error" });
1398
1771
  return;
1399
1772
  }
1400
1773
  const ok = await config.openInEditor?.({ file, line, column }, config.editor);
1401
- showToast(
1402
- ok === false ? { message: `Editor unavailable \u2014 path copied (${name ?? ""})`, tone: "info" } : { message: "Opening in your editor\u2026", tone: "success" }
1403
- );
1774
+ showToast(ok === false ? { message: "Editor unavailable \u2014 path copied", tone: "info" } : { message: "Opening in your editor\u2026", tone: "success" });
1404
1775
  },
1405
1776
  [config]
1406
1777
  );
@@ -1444,11 +1815,8 @@ function ComponentGraphOverlay() {
1444
1815
  e.stopPropagation();
1445
1816
  setSelected(sel);
1446
1817
  setMode("graph");
1447
- if (e.metaKey || e.ctrlKey) {
1448
- void openSelected(sel.absFilePath ?? sel.filePath, sel.line, sel.column, sel.componentName);
1449
- } else {
1450
- showToast({ message: `Locked ${sel.componentName}`, tone: "success" });
1451
- }
1818
+ if (e.metaKey || e.ctrlKey) void open(sel.absFilePath ?? sel.filePath, sel.line, sel.column);
1819
+ else showToast({ message: `Locked ${sel.componentName}`, tone: "success" });
1452
1820
  };
1453
1821
  document.addEventListener("pointermove", onMove, { passive: true });
1454
1822
  document.addEventListener("keydown", onKey, true);
@@ -1460,47 +1828,92 @@ function ComponentGraphOverlay() {
1460
1828
  document.removeEventListener("click", onClick, true);
1461
1829
  setHover(null);
1462
1830
  };
1463
- }, [enabled, route, openSelected]);
1831
+ }, [enabled, route, open]);
1464
1832
  if (!enabled) return null;
1465
- const flipX = typeof window !== "undefined" && hover && hover.x + 374 > window.innerWidth;
1833
+ const flipX = typeof window !== "undefined" && hover && hover.x + TOOLTIP_W + 14 > window.innerWidth;
1466
1834
  const flipY = typeof window !== "undefined" && hover && hover.y + 140 > window.innerHeight;
1467
- return /* @__PURE__ */ jsxs("div", { className: "rdp-overlay", children: [
1835
+ return /* @__PURE__ */ jsxs(Box6, { "data-rdp-ignore": "", sx: { position: "fixed", inset: 0, pointerEvents: "none", zIndex: (t) => t.zIndex.tooltip + 1 }, children: [
1468
1836
  hover && /* @__PURE__ */ jsx(
1469
- "div",
1837
+ Box6,
1470
1838
  {
1471
- className: "rdp-hl",
1472
- style: { top: hover.rect.top, left: hover.rect.left, width: hover.rect.width, height: hover.rect.height }
1839
+ sx: {
1840
+ position: "fixed",
1841
+ top: hover.rect.top,
1842
+ left: hover.rect.left,
1843
+ width: hover.rect.width,
1844
+ height: hover.rect.height,
1845
+ border: "1px solid",
1846
+ borderColor: "primary.main",
1847
+ bgcolor: alpha(theme.palette.primary.main, 0.12),
1848
+ borderRadius: 0.5,
1849
+ boxShadow: `0 0 0 1px ${alpha(theme.palette.primary.main, 0.4)}`,
1850
+ transition: "all 60ms linear"
1851
+ }
1473
1852
  }
1474
1853
  ),
1475
1854
  hover && /* @__PURE__ */ jsxs(
1476
- "div",
1855
+ Box6,
1477
1856
  {
1478
- className: "rdp-tooltip",
1479
- style: {
1857
+ sx: {
1858
+ position: "fixed",
1480
1859
  top: flipY ? void 0 : hover.y + 14,
1481
1860
  bottom: flipY ? window.innerHeight - hover.y + 14 : void 0,
1482
1861
  left: flipX ? void 0 : hover.x + 14,
1483
- right: flipX ? window.innerWidth - hover.x + 14 : void 0
1862
+ right: flipX ? window.innerWidth - hover.x + 14 : void 0,
1863
+ maxWidth: TOOLTIP_W,
1864
+ px: 1.25,
1865
+ py: 1,
1866
+ borderRadius: 1.5,
1867
+ border: "1px solid",
1868
+ borderColor: alpha(theme.palette.common.white, 0.12),
1869
+ bgcolor: alpha(theme.palette.grey[900], 0.85),
1870
+ backdropFilter: "blur(8px)",
1871
+ boxShadow: "0 8px 28px rgba(0,0,0,0.45)",
1872
+ color: theme.palette.common.white
1484
1873
  },
1485
1874
  children: [
1486
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: hover.filePath ? 4 : 0 }, children: [
1487
- /* @__PURE__ */ jsx("span", { className: "rdp-chip", style: { background: "rgba(105,80,232,0.5)", color: "#fff" }, children: hover.name }),
1488
- /* @__PURE__ */ jsx("span", { className: "rdp-mono", style: { color: "rgba(255,255,255,0.6)", fontSize: 11 }, children: `<${hover.domTag}>` })
1875
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", spacing: 0.75, sx: { mb: hover.filePath ? 0.5 : 0 }, children: [
1876
+ /* @__PURE__ */ jsx(
1877
+ Chip,
1878
+ {
1879
+ label: hover.name,
1880
+ size: "small",
1881
+ sx: { height: 18, fontWeight: 700, fontSize: "0.65rem", color: "#fff", bgcolor: alpha(theme.palette.primary.main, 0.5) }
1882
+ }
1883
+ ),
1884
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { color: alpha(theme.palette.common.white, 0.6), fontFamily: "monospace" }, children: `<${hover.domTag}>` })
1489
1885
  ] }),
1490
- /* @__PURE__ */ jsx("div", { className: "rdp-mono", style: { fontSize: 11.5, color: "rgba(255,255,255,0.85)", wordBreak: "break-all" }, children: hover.filePath ? `${hover.filePath}${hover.line ? `:${hover.line}` : ""}` : "source resolved from graph on lock" }),
1491
- hover.route && /* @__PURE__ */ jsx("div", { style: { fontSize: 11, color: "rgba(255,255,255,0.45)" }, children: hover.route }),
1492
- /* @__PURE__ */ jsx("div", { style: { fontSize: 10.5, marginTop: 4, color: "rgba(255,255,255,0.5)" }, children: "click to lock \xB7 \u2318/Ctrl + click to open \xB7 Esc to exit" })
1886
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { display: "block", fontFamily: "monospace", fontSize: "0.68rem", wordBreak: "break-all", color: hover.filePath ? alpha(theme.palette.common.white, 0.85) : alpha(theme.palette.warning.light, 0.9) }, children: hover.filePath ? `${hover.filePath}${hover.line ? `:${hover.line}` : ""}` : "source resolved from graph on lock" }),
1887
+ hover.route && /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { display: "block", fontSize: "0.62rem", color: alpha(theme.palette.common.white, 0.45) }, children: hover.route }),
1888
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { display: "block", mt: 0.5, fontSize: "0.6rem", color: alpha(theme.palette.common.white, 0.5) }, children: "click to lock \xB7 \u2318/Ctrl + click to open \xB7 Esc to exit" })
1493
1889
  ]
1494
1890
  }
1495
1891
  ),
1496
1892
  state2.toast && /* @__PURE__ */ jsx(
1497
- "div",
1893
+ Box6,
1498
1894
  {
1499
- className: "rdp-toast",
1500
- style: {
1501
- color: state2.toast.tone === "success" ? "var(--rdp-success)" : state2.toast.tone === "error" ? "var(--rdp-error)" : "#fff"
1895
+ sx: {
1896
+ position: "fixed",
1897
+ bottom: 24,
1898
+ left: "50%",
1899
+ transform: "translateX(-50%)",
1900
+ px: 1.5,
1901
+ py: 0.75,
1902
+ borderRadius: 1.5,
1903
+ border: "1px solid",
1904
+ borderColor: alpha(theme.palette.common.white, 0.12),
1905
+ bgcolor: alpha(theme.palette.grey[900], 0.9),
1906
+ backdropFilter: "blur(8px)",
1907
+ boxShadow: "0 8px 28px rgba(0,0,0,0.45)"
1502
1908
  },
1503
- children: state2.toast.message
1909
+ children: /* @__PURE__ */ jsx(
1910
+ Typography3,
1911
+ {
1912
+ variant: "caption",
1913
+ sx: { fontWeight: 600, color: state2.toast.tone === "success" ? "success.light" : state2.toast.tone === "error" ? "error.light" : "common.white" },
1914
+ children: state2.toast.message
1915
+ }
1916
+ )
1504
1917
  }
1505
1918
  )
1506
1919
  ] });
@@ -1510,191 +1923,237 @@ var componentGraphTool = {
1510
1923
  title: "Component Graph Inspector",
1511
1924
  subtitle: "Inspect component tree & open source files",
1512
1925
  color: "primary",
1513
- icon: /* @__PURE__ */ jsx(IconGraph, { size: 19 }),
1926
+ icon: /* @__PURE__ */ jsx(LuWorkflow, { size: 19 }),
1514
1927
  Panel: ComponentGraphPanel,
1515
1928
  Overlay: ComponentGraphOverlay
1516
1929
  };
1517
1930
  function registerComponentGraph() {
1518
1931
  registerTool(componentGraphTool);
1519
1932
  }
1520
- var STORAGE_KEY = "react-dev-panel:corner";
1521
- var GAP = 20;
1522
- var FAB = 52;
1933
+ function ToolTile({ color, size = 38, children }) {
1934
+ return /* @__PURE__ */ jsx(
1935
+ Box6,
1936
+ {
1937
+ sx: (theme) => ({
1938
+ width: size,
1939
+ height: size,
1940
+ flexShrink: 0,
1941
+ borderRadius: 1.5,
1942
+ display: "grid",
1943
+ placeItems: "center",
1944
+ color: theme.palette[color].main,
1945
+ bgcolor: alpha(theme.palette[color].main, 0.14)
1946
+ }),
1947
+ children
1948
+ }
1949
+ );
1950
+ }
1951
+ var STORAGE_KEY2 = "react-dev-panel:corner";
1952
+ var EDGE_GAP = 24;
1953
+ var FAB_SIZE = 56;
1523
1954
  var DRAG_THRESHOLD = 5;
1524
1955
  function isCorner(v) {
1525
1956
  return v === "top-left" || v === "top-right" || v === "bottom-left" || v === "bottom-right";
1526
1957
  }
1527
- function readCorner() {
1958
+ function readStoredCorner() {
1528
1959
  if (typeof window === "undefined") return "bottom-right";
1529
1960
  try {
1530
- const s = window.localStorage.getItem(STORAGE_KEY);
1531
- if (isCorner(s)) return s;
1961
+ const stored = window.localStorage.getItem(STORAGE_KEY2);
1962
+ if (isCorner(stored)) return stored;
1532
1963
  } catch {
1533
1964
  }
1534
1965
  return "bottom-right";
1535
1966
  }
1536
1967
  function useDraggableCorner() {
1537
1968
  const [corner, setCorner] = useState("bottom-right");
1538
- const [drag, setDrag] = useState(null);
1539
- const moved = useRef(false);
1540
- const offset = useRef({ x: 0, y: 0 });
1541
- useEffect(() => setCorner(readCorner()), []);
1542
- const onPointerDown = useCallback((e) => {
1543
- if (e.button !== 0) return;
1544
- const rect = e.currentTarget.getBoundingClientRect();
1545
- offset.current = { x: e.clientX - rect.left, y: e.clientY - rect.top };
1546
- moved.current = false;
1547
- const sx = e.clientX;
1548
- const sy = e.clientY;
1549
- const move = (ev) => {
1550
- if (!moved.current && Math.hypot(ev.clientX - sx, ev.clientY - sy) < DRAG_THRESHOLD) return;
1551
- moved.current = true;
1552
- setDrag({ x: ev.clientX - offset.current.x, y: ev.clientY - offset.current.y });
1969
+ const [dragPos, setDragPos] = useState(null);
1970
+ const movedRef = useRef(false);
1971
+ const offsetRef = useRef({ x: 0, y: 0 });
1972
+ useEffect(() => setCorner(readStoredCorner()), []);
1973
+ const onPointerDown = useCallback((event) => {
1974
+ if (event.button !== 0) return;
1975
+ const rect = event.currentTarget.getBoundingClientRect();
1976
+ offsetRef.current = { x: event.clientX - rect.left, y: event.clientY - rect.top };
1977
+ movedRef.current = false;
1978
+ const startX = event.clientX;
1979
+ const startY = event.clientY;
1980
+ const handleMove = (ev) => {
1981
+ if (!movedRef.current && Math.hypot(ev.clientX - startX, ev.clientY - startY) < DRAG_THRESHOLD) return;
1982
+ movedRef.current = true;
1983
+ setDragPos({ x: ev.clientX - offsetRef.current.x, y: ev.clientY - offsetRef.current.y });
1553
1984
  };
1554
- const up = (ev) => {
1555
- window.removeEventListener("pointermove", move);
1556
- window.removeEventListener("pointerup", up);
1557
- if (moved.current) {
1558
- const cxp = ev.clientX - offset.current.x + FAB / 2;
1559
- const cyp = ev.clientY - offset.current.y + FAB / 2;
1560
- const next = `${cyp < window.innerHeight / 2 ? "top" : "bottom"}-${cxp < window.innerWidth / 2 ? "left" : "right"}`;
1985
+ const handleUp = (ev) => {
1986
+ window.removeEventListener("pointermove", handleMove);
1987
+ window.removeEventListener("pointerup", handleUp);
1988
+ if (movedRef.current) {
1989
+ const cx = ev.clientX - offsetRef.current.x + FAB_SIZE / 2;
1990
+ const cy = ev.clientY - offsetRef.current.y + FAB_SIZE / 2;
1991
+ const next = `${cy < window.innerHeight / 2 ? "top" : "bottom"}-${cx < window.innerWidth / 2 ? "left" : "right"}`;
1561
1992
  setCorner(next);
1562
1993
  try {
1563
- window.localStorage.setItem(STORAGE_KEY, next);
1994
+ window.localStorage.setItem(STORAGE_KEY2, next);
1564
1995
  } catch {
1565
1996
  }
1566
1997
  }
1567
- setDrag(null);
1998
+ setDragPos(null);
1568
1999
  };
1569
- window.addEventListener("pointermove", move);
1570
- window.addEventListener("pointerup", up);
2000
+ window.addEventListener("pointermove", handleMove);
2001
+ window.addEventListener("pointerup", handleUp);
1571
2002
  }, []);
1572
- const onClickCapture = useCallback((e) => {
1573
- if (moved.current) {
1574
- e.stopPropagation();
1575
- e.preventDefault();
1576
- moved.current = false;
2003
+ const onClickCapture = useCallback((event) => {
2004
+ if (movedRef.current) {
2005
+ event.stopPropagation();
2006
+ event.preventDefault();
2007
+ movedRef.current = false;
1577
2008
  }
1578
2009
  }, []);
2010
+ const dragging = dragPos !== null;
1579
2011
  const isTop = corner.startsWith("top");
1580
2012
  const isLeft = corner.endsWith("left");
1581
- const pos = drag ? { top: drag.y, left: drag.x } : {
1582
- top: isTop ? GAP : void 0,
1583
- bottom: isTop ? void 0 : GAP,
1584
- left: isLeft ? GAP : void 0,
1585
- right: isLeft ? void 0 : GAP
2013
+ const positionSx = dragging ? { top: dragPos.y, left: dragPos.x, right: "auto", bottom: "auto" } : {
2014
+ top: isTop ? EDGE_GAP : "auto",
2015
+ bottom: isTop ? "auto" : EDGE_GAP,
2016
+ left: isLeft ? EDGE_GAP : "auto",
2017
+ right: isLeft ? "auto" : EDGE_GAP
1586
2018
  };
1587
- return { pos, isTop, isLeft, onPointerDown, onClickCapture };
2019
+ return { positionSx, onPointerDown, onClickCapture, isTop, isLeft, dragging };
1588
2020
  }
1589
2021
  function ToolBadge({ tool }) {
1590
2022
  const badge = tool.useBadge?.();
1591
2023
  if (!badge) return null;
1592
- const bg = badge.tone === "error" ? "var(--rdp-error)" : badge.tone === "success" ? "var(--rdp-success)" : "var(--rdp-bg-soft)";
1593
- const color = badge.tone === "success" ? "#06210f" : "#fff";
1594
- return /* @__PURE__ */ jsx("span", { className: "rdp-chip", style: { background: bg, color }, children: badge.label });
2024
+ const color = badge.tone === "error" ? "error" : badge.tone === "success" ? "success" : "default";
2025
+ return /* @__PURE__ */ jsx(
2026
+ Chip,
2027
+ {
2028
+ size: "small",
2029
+ variant: "soft",
2030
+ color,
2031
+ label: badge.label,
2032
+ sx: { height: 18, fontWeight: 700, fontSize: "0.65rem", "& .MuiChip-label": { px: 0.75 } }
2033
+ }
2034
+ );
1595
2035
  }
1596
- function Launcher({
1597
- tools: tools2,
1598
- onOpenTool
1599
- }) {
1600
- const { pos, isTop, isLeft, onPointerDown, onClickCapture } = useDraggableCorner();
1601
- const [menuOpen, setMenuOpen] = useState(false);
1602
- const menuPos = {
1603
- top: isTop ? pos.top !== void 0 ? pos.top + FAB + 8 : GAP + FAB + 8 : void 0,
1604
- bottom: isTop ? void 0 : GAP + FAB + 8,
1605
- left: isLeft ? GAP : void 0,
1606
- right: isLeft ? void 0 : GAP
1607
- };
2036
+ function Launcher({ tools: tools2, onOpenTool }) {
2037
+ const { positionSx, onPointerDown, onClickCapture, isTop, isLeft, dragging } = useDraggableCorner();
2038
+ const [menuAnchor, setMenuAnchor] = useState(null);
1608
2039
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1609
2040
  /* @__PURE__ */ jsx(
1610
- "button",
2041
+ Box6,
1611
2042
  {
1612
- type: "button",
1613
- className: "rdp-fab",
1614
- style: pos,
1615
- onPointerDown,
1616
- onClickCapture,
1617
- onClick: () => setMenuOpen((v) => !v),
1618
- "aria-label": "Open Developer Tools",
1619
- "aria-haspopup": "menu",
1620
- children: /* @__PURE__ */ jsx(IconWrench, { size: 22 })
2043
+ "data-rdp-ignore": "",
2044
+ sx: (theme) => ({ position: "fixed", zIndex: theme.zIndex.modal + 2, ...positionSx }),
2045
+ children: /* @__PURE__ */ jsx(Tooltip2, { title: dragging ? "" : "Developer Tools \u2014 drag to a corner", placement: isLeft ? "right" : "left", arrow: true, children: /* @__PURE__ */ jsx(
2046
+ Fab,
2047
+ {
2048
+ onClick: (e) => setMenuAnchor(e.currentTarget),
2049
+ onClickCapture,
2050
+ onPointerDown,
2051
+ "aria-label": "Open Developer Tools",
2052
+ "aria-haspopup": "menu",
2053
+ sx: (theme) => ({
2054
+ width: FAB_SIZE,
2055
+ height: FAB_SIZE,
2056
+ touchAction: "none",
2057
+ cursor: dragging ? "grabbing" : "grab",
2058
+ color: theme.palette.primary.contrastText,
2059
+ background: `linear-gradient(135deg, ${theme.palette.primary.main}, ${theme.palette.primary.dark})`,
2060
+ boxShadow: `0 4px 12px ${alpha(theme.palette.primary.main, 0.24)}, 0 8px 24px rgba(0,0,0,0.5)`,
2061
+ "&:hover": {
2062
+ background: `linear-gradient(135deg, ${theme.palette.primary.dark}, ${theme.palette.primary.dark})`
2063
+ }
2064
+ }),
2065
+ children: /* @__PURE__ */ jsx(LuWrench, { size: 22 })
2066
+ }
2067
+ ) })
1621
2068
  }
1622
2069
  ),
1623
- menuOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
1624
- /* @__PURE__ */ jsx(
1625
- "div",
1626
- {
1627
- style: { position: "fixed", inset: 0, zIndex: 1 },
1628
- onClick: () => setMenuOpen(false),
1629
- "aria-hidden": true
1630
- }
1631
- ),
1632
- /* @__PURE__ */ jsxs("div", { className: "rdp-surface rdp-menu", style: menuPos, role: "menu", children: [
1633
- /* @__PURE__ */ jsxs("div", { className: "rdp-header rdp-menu-head", children: [
1634
- /* @__PURE__ */ jsx("span", { className: "rdp-tile", style: { color: "var(--rdp-accent)", background: "rgba(105,80,232,0.16)" }, children: /* @__PURE__ */ jsx(IconWrench, { size: 17 }) }),
1635
- /* @__PURE__ */ jsxs("div", { children: [
1636
- /* @__PURE__ */ jsx("div", { className: "rdp-title", children: "Developer Tools" }),
1637
- /* @__PURE__ */ jsx("div", { className: "rdp-sub", children: "Internal utilities" })
1638
- ] })
1639
- ] }),
1640
- /* @__PURE__ */ jsx("div", { style: { padding: 8 }, children: tools2.map((tool) => /* @__PURE__ */ jsxs(
1641
- "button",
1642
- {
1643
- type: "button",
1644
- className: "rdp-row",
1645
- role: "menuitem",
1646
- onClick: () => {
1647
- onOpenTool(tool.id);
1648
- setMenuOpen(false);
1649
- },
1650
- children: [
1651
- /* @__PURE__ */ jsx(
1652
- "span",
1653
- {
1654
- className: "rdp-tile",
1655
- style: { color: colorVar(tool.color), background: "rgba(148,163,184,0.1)" },
1656
- children: tool.icon
1657
- }
1658
- ),
1659
- /* @__PURE__ */ jsxs("span", { style: { flex: 1, minWidth: 0 }, children: [
1660
- /* @__PURE__ */ jsx("span", { className: "rdp-title", style: { display: "block" }, children: tool.title }),
1661
- /* @__PURE__ */ jsx("span", { className: "rdp-sub", style: { display: "block" }, children: tool.subtitle })
1662
- ] }),
1663
- /* @__PURE__ */ jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 6, color: "var(--rdp-text-faint)" }, children: [
1664
- /* @__PURE__ */ jsx(ToolBadge, { tool }),
1665
- /* @__PURE__ */ jsx(IconChevronRight, { size: 16 })
1666
- ] })
1667
- ]
2070
+ /* @__PURE__ */ jsxs(
2071
+ Menu,
2072
+ {
2073
+ anchorEl: menuAnchor,
2074
+ open: Boolean(menuAnchor),
2075
+ onClose: () => setMenuAnchor(null),
2076
+ sx: (theme) => ({ zIndex: theme.zIndex.modal + 2 }),
2077
+ anchorOrigin: { vertical: isTop ? "bottom" : "top", horizontal: isLeft ? "left" : "right" },
2078
+ transformOrigin: { vertical: isTop ? "top" : "bottom", horizontal: isLeft ? "left" : "right" },
2079
+ slotProps: {
2080
+ paper: {
2081
+ sx: {
2082
+ width: 320,
2083
+ mt: isTop ? 1.5 : 0,
2084
+ mb: isTop ? 0 : 1.5,
2085
+ borderRadius: 2.5,
2086
+ overflow: "hidden",
2087
+ border: "1px solid",
2088
+ borderColor: "divider",
2089
+ boxShadow: 16
2090
+ }
1668
2091
  },
1669
- tool.id
1670
- )) })
1671
- ] })
1672
- ] })
2092
+ list: { sx: { py: 0 } }
2093
+ },
2094
+ children: [
2095
+ /* @__PURE__ */ jsxs(
2096
+ Box6,
2097
+ {
2098
+ sx: {
2099
+ display: "flex",
2100
+ alignItems: "center",
2101
+ gap: 1.25,
2102
+ px: 2,
2103
+ py: 1.5,
2104
+ background: (theme) => `linear-gradient(135deg, ${alpha(theme.palette.primary.main, 0.16)}, ${alpha(theme.palette.primary.main, 0.04)})`
2105
+ },
2106
+ children: [
2107
+ /* @__PURE__ */ jsx(ToolTile, { color: "primary", size: 34, children: /* @__PURE__ */ jsx(LuWrench, { size: 17 }) }),
2108
+ /* @__PURE__ */ jsxs(Box6, { sx: { minWidth: 0 }, children: [
2109
+ /* @__PURE__ */ jsx(Typography3, { variant: "subtitle2", sx: { fontWeight: 700, lineHeight: 1.2 }, children: "Developer Tools" }),
2110
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { color: "text.secondary" }, children: "Internal utilities" })
2111
+ ] })
2112
+ ]
2113
+ }
2114
+ ),
2115
+ /* @__PURE__ */ jsx(Divider, {}),
2116
+ /* @__PURE__ */ jsx(Box6, { sx: { p: 1 }, children: tools2.map((tool, i) => /* @__PURE__ */ jsxs(
2117
+ MenuItem,
2118
+ {
2119
+ onClick: () => {
2120
+ onOpenTool(tool.id);
2121
+ setMenuAnchor(null);
2122
+ },
2123
+ disableGutters: true,
2124
+ sx: { alignItems: "flex-start", gap: 1.25, px: 1.25, py: 1.25, mt: i === 0 ? 0 : 0.5, borderRadius: 1.5, whiteSpace: "normal" },
2125
+ children: [
2126
+ /* @__PURE__ */ jsx(ToolTile, { color: tool.color ?? "primary", children: tool.icon }),
2127
+ /* @__PURE__ */ jsxs(Box6, { sx: { flex: 1, minWidth: 0 }, children: [
2128
+ /* @__PURE__ */ jsx(Typography3, { variant: "subtitle2", sx: { fontWeight: 600, lineHeight: 1.3 }, children: tool.title }),
2129
+ /* @__PURE__ */ jsx(Typography3, { variant: "caption", sx: { color: "text.secondary", display: "block" }, children: tool.subtitle })
2130
+ ] }),
2131
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 0.5, alignItems: "center", sx: { mt: 0.25 }, children: [
2132
+ /* @__PURE__ */ jsx(ToolBadge, { tool }),
2133
+ /* @__PURE__ */ jsx(Box6, { sx: { display: "grid", placeItems: "center", color: "text.disabled" }, children: /* @__PURE__ */ jsx(LuChevronRight, { size: 16 }) })
2134
+ ] })
2135
+ ]
2136
+ },
2137
+ tool.id
2138
+ )) })
2139
+ ]
2140
+ }
2141
+ )
1673
2142
  ] });
1674
2143
  }
1675
2144
  function DevPanel(config) {
1676
2145
  const enabled = config.enabled ?? (typeof process !== "undefined" ? process.env.NODE_ENV !== "production" : true);
1677
- useEffect(() => {
1678
- if (enabled) injectBaseStyles();
1679
- }, [enabled]);
1680
2146
  if (!enabled) return null;
1681
- return /* @__PURE__ */ jsx(DevPanelConfigProvider, { config, children: /* @__PURE__ */ jsx(DevPanelInner, { ids: config.tools, theme: config.theme }) });
2147
+ return /* @__PURE__ */ jsx(DevPanelConfigProvider, { config, children: /* @__PURE__ */ jsx(DevPanelInner, { ids: config.tools }) });
1682
2148
  }
1683
- function DevPanelInner({
1684
- ids,
1685
- theme
1686
- }) {
2149
+ function DevPanelInner({ ids }) {
1687
2150
  const tools2 = useMemo(() => resolveTools(ids), [ids]);
1688
2151
  const [openId, setOpenId] = useState(null);
1689
2152
  useEffect(() => {
1690
2153
  tools2.forEach((t) => t.init?.());
1691
2154
  }, [tools2]);
1692
- const rootStyle = {};
1693
- if (theme?.accent) rootStyle["--rdp-accent"] = theme.accent;
1694
- if (theme?.accentContrast)
1695
- rootStyle["--rdp-accent-contrast"] = theme.accentContrast;
1696
2155
  const ActivePanel = tools2.find((t) => t.id === openId)?.Panel ?? null;
1697
- return /* @__PURE__ */ jsxs("div", { className: "rdp-root", style: rootStyle, "data-rdp-ignore": "", children: [
2156
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1698
2157
  /* @__PURE__ */ jsx(Launcher, { tools: tools2, onOpenTool: setOpenId }),
1699
2158
  ActivePanel && /* @__PURE__ */ jsx(ActivePanel, { onClose: () => setOpenId(null) }),
1700
2159
  tools2.map((t) => t.Overlay ? /* @__PURE__ */ jsx(t.Overlay, {}, t.id) : null)
@@ -1706,6 +2165,6 @@ registerDevLogs();
1706
2165
  registerPagePerformance();
1707
2166
  registerComponentGraph();
1708
2167
 
1709
- export { DevPanel, defaultOpenInEditor, getRegisteredTools, injectBaseStyles, registerTool, useDevPanelConfig };
2168
+ export { DevPanel, defaultOpenInEditor, getRegisteredTools, registerTool, useDevPanelConfig };
1710
2169
  //# sourceMappingURL=index.js.map
1711
2170
  //# sourceMappingURL=index.js.map