react-dev-profiler 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +138 -108
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +146 -116
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/DevProfiler.tsx
|
|
2
|
-
import { Profiler, useRef as
|
|
2
|
+
import { Profiler, useRef as useRef3, useState as useState4, useEffect as useEffect4, useCallback as useCallback3 } from "react";
|
|
3
3
|
|
|
4
4
|
// src/types.ts
|
|
5
5
|
var HISTORY_SIZE = 60;
|
|
@@ -53,15 +53,15 @@ var s = {
|
|
|
53
53
|
backdropFilter: "blur(12px)",
|
|
54
54
|
userSelect: "none",
|
|
55
55
|
color: "#ccc",
|
|
56
|
-
fontSize: 11
|
|
56
|
+
fontSize: 11,
|
|
57
|
+
cursor: "grab",
|
|
58
|
+
touchAction: "none"
|
|
57
59
|
},
|
|
58
60
|
panelHeader: {
|
|
59
61
|
display: "flex",
|
|
60
62
|
justifyContent: "space-between",
|
|
61
63
|
alignItems: "center",
|
|
62
|
-
marginBottom: 8
|
|
63
|
-
cursor: "grab",
|
|
64
|
-
touchAction: "none"
|
|
64
|
+
marginBottom: 8
|
|
65
65
|
},
|
|
66
66
|
panelTitle: {
|
|
67
67
|
color: "#666",
|
|
@@ -92,7 +92,8 @@ var s = {
|
|
|
92
92
|
border: "none",
|
|
93
93
|
color: "#444",
|
|
94
94
|
cursor: "pointer",
|
|
95
|
-
padding:
|
|
95
|
+
padding: 4,
|
|
96
|
+
margin: -4,
|
|
96
97
|
lineHeight: 1,
|
|
97
98
|
display: "flex",
|
|
98
99
|
alignItems: "center",
|
|
@@ -107,7 +108,8 @@ var s = {
|
|
|
107
108
|
color: "#444",
|
|
108
109
|
cursor: "pointer",
|
|
109
110
|
fontSize: 13,
|
|
110
|
-
padding:
|
|
111
|
+
padding: 4,
|
|
112
|
+
margin: -4,
|
|
111
113
|
lineHeight: 1
|
|
112
114
|
},
|
|
113
115
|
body: {
|
|
@@ -156,23 +158,40 @@ var s = {
|
|
|
156
158
|
toggleBtn: {
|
|
157
159
|
position: "fixed",
|
|
158
160
|
zIndex: 99998,
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
background: "rgba(20, 20, 20, 0.9)",
|
|
161
|
+
height: 26,
|
|
162
|
+
borderRadius: 13,
|
|
163
|
+
border: "1px solid rgba(255, 255, 255, 0.08)",
|
|
164
|
+
background: "rgba(28, 28, 30, 0.92)",
|
|
164
165
|
cursor: "pointer",
|
|
165
166
|
display: "flex",
|
|
166
167
|
alignItems: "center",
|
|
167
|
-
|
|
168
|
-
padding: "0
|
|
169
|
-
backdropFilter: "blur(
|
|
168
|
+
gap: 6,
|
|
169
|
+
padding: "0 10px 0 8px",
|
|
170
|
+
backdropFilter: "blur(20px)",
|
|
171
|
+
WebkitBackdropFilter: "blur(20px)",
|
|
172
|
+
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.4), inset 0 0.5px 0 rgba(255, 255, 255, 0.06)"
|
|
173
|
+
},
|
|
174
|
+
toggleDot: {
|
|
175
|
+
width: 6,
|
|
176
|
+
height: 6,
|
|
177
|
+
borderRadius: "50%",
|
|
178
|
+
flexShrink: 0
|
|
170
179
|
},
|
|
171
180
|
toggleFps: {
|
|
172
181
|
fontFamily: "'SF Mono', 'Fira Code', monospace",
|
|
173
|
-
fontSize:
|
|
174
|
-
fontWeight:
|
|
175
|
-
|
|
182
|
+
fontSize: 11,
|
|
183
|
+
fontWeight: 600,
|
|
184
|
+
color: "rgba(255, 255, 255, 0.85)",
|
|
185
|
+
letterSpacing: -0.3,
|
|
186
|
+
lineHeight: 1
|
|
187
|
+
},
|
|
188
|
+
toggleLabel: {
|
|
189
|
+
fontFamily: "'SF Mono', 'Fira Code', monospace",
|
|
190
|
+
fontSize: 9,
|
|
191
|
+
fontWeight: 500,
|
|
192
|
+
color: "rgba(255, 255, 255, 0.35)",
|
|
193
|
+
letterSpacing: 0,
|
|
194
|
+
textTransform: "lowercase"
|
|
176
195
|
},
|
|
177
196
|
footer: {
|
|
178
197
|
marginTop: 8,
|
|
@@ -184,32 +203,59 @@ var s = {
|
|
|
184
203
|
var FLASH_OUTLINE = "2px solid rgba(99, 102, 241, 0.8)";
|
|
185
204
|
|
|
186
205
|
// src/hooks.ts
|
|
206
|
+
function getEffectiveRect(el) {
|
|
207
|
+
const rect = el.getBoundingClientRect();
|
|
208
|
+
if (rect.width > 0 || rect.height > 0) return rect;
|
|
209
|
+
const children = el.children;
|
|
210
|
+
if (children.length === 0) return rect;
|
|
211
|
+
let top = Infinity, left = Infinity, bottom = -Infinity, right = -Infinity;
|
|
212
|
+
for (let i = 0; i < children.length; i++) {
|
|
213
|
+
const cr = children[i].getBoundingClientRect();
|
|
214
|
+
if (cr.width === 0 && cr.height === 0) continue;
|
|
215
|
+
top = Math.min(top, cr.top);
|
|
216
|
+
left = Math.min(left, cr.left);
|
|
217
|
+
bottom = Math.max(bottom, cr.bottom);
|
|
218
|
+
right = Math.max(right, cr.right);
|
|
219
|
+
}
|
|
220
|
+
if (top === Infinity) return rect;
|
|
221
|
+
return new DOMRect(left, top, right - left, bottom - top);
|
|
222
|
+
}
|
|
223
|
+
function getObservableChildren(el) {
|
|
224
|
+
const result = [];
|
|
225
|
+
for (let i = 0; i < el.children.length; i++) {
|
|
226
|
+
const child = el.children[i];
|
|
227
|
+
const r = child.getBoundingClientRect();
|
|
228
|
+
if (r.width > 0 || r.height > 0) result.push(child);
|
|
229
|
+
}
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
187
232
|
function useAnchorPosition(ref, position = "bottom-left") {
|
|
188
233
|
const [pos, setPos] = useState({ top: 0, left: 0 });
|
|
189
234
|
useEffect(() => {
|
|
190
235
|
if (!ref.current) return;
|
|
236
|
+
const el = ref.current;
|
|
191
237
|
const update = () => {
|
|
192
|
-
|
|
193
|
-
const rect = ref.current.getBoundingClientRect();
|
|
194
|
-
const margin = 8;
|
|
238
|
+
const rect = getEffectiveRect(el);
|
|
195
239
|
switch (position) {
|
|
196
240
|
case "top-left":
|
|
197
|
-
setPos({ top: rect.top
|
|
241
|
+
setPos({ top: rect.top, left: rect.left });
|
|
198
242
|
break;
|
|
199
243
|
case "top-right":
|
|
200
|
-
setPos({ top: rect.top
|
|
244
|
+
setPos({ top: rect.top, left: rect.right });
|
|
201
245
|
break;
|
|
202
246
|
case "bottom-right":
|
|
203
|
-
setPos({ top: rect.bottom
|
|
247
|
+
setPos({ top: rect.bottom, left: rect.right });
|
|
204
248
|
break;
|
|
205
249
|
case "bottom-left":
|
|
206
250
|
default:
|
|
207
|
-
setPos({ top: rect.bottom
|
|
251
|
+
setPos({ top: rect.bottom, left: rect.left });
|
|
208
252
|
break;
|
|
209
253
|
}
|
|
210
254
|
};
|
|
255
|
+
update();
|
|
211
256
|
const observer = new ResizeObserver(update);
|
|
212
|
-
observer.observe(
|
|
257
|
+
observer.observe(el);
|
|
258
|
+
for (const child of getObservableChildren(el)) observer.observe(child);
|
|
213
259
|
observer.observe(document.documentElement);
|
|
214
260
|
return () => observer.disconnect();
|
|
215
261
|
}, [ref, position]);
|
|
@@ -220,9 +266,10 @@ function useDraggable() {
|
|
|
220
266
|
const dragging = useRef(false);
|
|
221
267
|
const start = useRef({ x: 0, y: 0 });
|
|
222
268
|
const onPointerDown = useCallback((e) => {
|
|
269
|
+
if (e.target.closest("button, a, [data-no-drag]")) return;
|
|
223
270
|
dragging.current = true;
|
|
224
271
|
start.current = { x: e.clientX - offset.x, y: e.clientY - offset.y };
|
|
225
|
-
e.
|
|
272
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
226
273
|
}, [offset]);
|
|
227
274
|
const onPointerMove = useCallback((e) => {
|
|
228
275
|
if (!dragging.current) return;
|
|
@@ -242,21 +289,13 @@ function useDomTracker(wrapperRef, enabled) {
|
|
|
242
289
|
const dirty = useRef(true);
|
|
243
290
|
useEffect(() => {
|
|
244
291
|
if (!enabled || !wrapperRef.current) return;
|
|
245
|
-
const observer = new MutationObserver((
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
if (record.type === "attributes" && record.attributeName === "class") continue;
|
|
249
|
-
realMutation = true;
|
|
250
|
-
}
|
|
251
|
-
if (realMutation) {
|
|
252
|
-
mutations.current++;
|
|
253
|
-
dirty.current = true;
|
|
254
|
-
}
|
|
292
|
+
const observer = new MutationObserver(() => {
|
|
293
|
+
mutations.current++;
|
|
294
|
+
dirty.current = true;
|
|
255
295
|
});
|
|
256
296
|
observer.observe(wrapperRef.current, {
|
|
257
297
|
childList: true,
|
|
258
298
|
subtree: true,
|
|
259
|
-
attributes: true,
|
|
260
299
|
attributeFilter: ["style"]
|
|
261
300
|
});
|
|
262
301
|
return () => observer.disconnect();
|
|
@@ -297,18 +336,19 @@ function useRenderFlash(wrapperRef, open) {
|
|
|
297
336
|
const mutationCount = useRef(0);
|
|
298
337
|
useEffect(() => {
|
|
299
338
|
if (!open || !wrapperRef.current) return;
|
|
339
|
+
const wrapper = wrapperRef.current;
|
|
300
340
|
const observer = new MutationObserver(() => {
|
|
301
341
|
mutationCount.current++;
|
|
302
|
-
if (
|
|
303
|
-
const
|
|
304
|
-
|
|
305
|
-
|
|
342
|
+
if (mutationCount.current <= 1) return;
|
|
343
|
+
const target = getObservableChildren(wrapper)[0] ?? wrapper;
|
|
344
|
+
target.style.outline = FLASH_OUTLINE;
|
|
345
|
+
target.style.outlineOffset = "-2px";
|
|
306
346
|
setTimeout(() => {
|
|
307
|
-
|
|
308
|
-
|
|
347
|
+
target.style.outline = "";
|
|
348
|
+
target.style.outlineOffset = "";
|
|
309
349
|
}, 150);
|
|
310
350
|
});
|
|
311
|
-
observer.observe(
|
|
351
|
+
observer.observe(wrapper, { childList: true, subtree: true });
|
|
312
352
|
return () => observer.disconnect();
|
|
313
353
|
}, [wrapperRef, open]);
|
|
314
354
|
}
|
|
@@ -381,20 +421,21 @@ function StatRow({ label, value, sub, color = "#4ade80" }) {
|
|
|
381
421
|
] })
|
|
382
422
|
] });
|
|
383
423
|
}
|
|
424
|
+
var GAP = 8;
|
|
384
425
|
function getPanelStyle(pos, offset, position) {
|
|
385
426
|
const style = {
|
|
386
427
|
...s.panel,
|
|
387
428
|
transform: `translate(${offset.x}px, ${offset.y}px)`
|
|
388
429
|
};
|
|
389
430
|
if (position.startsWith("bottom")) {
|
|
390
|
-
style.bottom = window.innerHeight - pos.top;
|
|
431
|
+
style.bottom = window.innerHeight - pos.top + GAP;
|
|
391
432
|
} else {
|
|
392
|
-
style.top = pos.top;
|
|
433
|
+
style.top = pos.top + GAP;
|
|
393
434
|
}
|
|
394
435
|
if (position.endsWith("right")) {
|
|
395
|
-
style.right = window.innerWidth - pos.left;
|
|
436
|
+
style.right = window.innerWidth - pos.left + GAP;
|
|
396
437
|
} else {
|
|
397
|
-
style.left = pos.left;
|
|
438
|
+
style.left = pos.left + GAP;
|
|
398
439
|
}
|
|
399
440
|
return style;
|
|
400
441
|
}
|
|
@@ -436,7 +477,8 @@ function DevStatsPanel({
|
|
|
436
477
|
allFrameTimes.current.push(avgFrameTime);
|
|
437
478
|
const sorted = [...allFrameTimes.current].sort((a, b) => a - b);
|
|
438
479
|
const el = targetRef.current;
|
|
439
|
-
const
|
|
480
|
+
const r = el ? getEffectiveRect(el) : null;
|
|
481
|
+
const dims = r ? `${Math.round(r.width)} x ${Math.round(r.height)}` : "\u2013";
|
|
440
482
|
const perf = performance;
|
|
441
483
|
const mem = perf.memory ? Math.round(perf.memory.usedJSHeapSize / 1024 / 1024) : 0;
|
|
442
484
|
setStats({
|
|
@@ -471,23 +513,17 @@ function DevStatsPanel({
|
|
|
471
513
|
const handleExport = useCallback2(() => {
|
|
472
514
|
const payload = { timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...stats };
|
|
473
515
|
const json = JSON.stringify(payload, null, 2);
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
ta.select();
|
|
486
|
-
document.execCommand("copy");
|
|
487
|
-
document.body.removeChild(ta);
|
|
488
|
-
setExported(true);
|
|
489
|
-
setTimeout(() => setExported(false), 1200);
|
|
490
|
-
}
|
|
516
|
+
const blob = new Blob([json], { type: "application/json" });
|
|
517
|
+
const url = URL.createObjectURL(blob);
|
|
518
|
+
const a = document.createElement("a");
|
|
519
|
+
a.href = url;
|
|
520
|
+
a.download = `devprofiler-${Date.now()}.json`;
|
|
521
|
+
document.body.appendChild(a);
|
|
522
|
+
a.click();
|
|
523
|
+
document.body.removeChild(a);
|
|
524
|
+
URL.revokeObjectURL(url);
|
|
525
|
+
setExported(true);
|
|
526
|
+
setTimeout(() => setExported(false), 1200);
|
|
491
527
|
}, [stats]);
|
|
492
528
|
const ftColor = stats.frameTime > 33 ? "#ef4444" : stats.frameTime > 16.67 ? "#f59e0b" : "#4ade80";
|
|
493
529
|
const rpsColor = stats.rendersPerSecond > 30 ? "#ef4444" : stats.rendersPerSecond > 10 ? "#f59e0b" : "#4ade80";
|
|
@@ -497,36 +533,26 @@ function DevStatsPanel({
|
|
|
497
533
|
const p99Color = stats.frameTimeP99 > 33 ? "#ef4444" : stats.frameTimeP99 > 16.67 ? "#f59e0b" : "#4ade80";
|
|
498
534
|
const exportStyle = exported ? { ...s.iconBtn, ...s.iconBtnActive } : s.iconBtn;
|
|
499
535
|
return createPortal(
|
|
500
|
-
/* @__PURE__ */ jsxs("div", { style: getPanelStyle(pos, offset, position), children: [
|
|
501
|
-
/* @__PURE__ */ jsxs(
|
|
502
|
-
"
|
|
503
|
-
|
|
504
|
-
style: s.
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
/* @__PURE__ */ jsx("path", { d: "M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25z" })
|
|
521
|
-
] })
|
|
522
|
-
}
|
|
523
|
-
),
|
|
524
|
-
/* @__PURE__ */ jsx("button", { style: s.iconBtn, onClick: handleReset, title: "Reset counters", children: /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M14 1a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-4a1 1 0 0 1 0-2h1.6A6 6 0 0 0 2.07 7.5a1 1 0 1 1-1.97-.36A8 8 0 0 1 13 3.35V2a1 1 0 0 1 1-1zM2 15a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1h4a1 1 0 0 1 0 2H4.4A6 6 0 0 0 13.93 8.5a1 1 0 1 1 1.97.36A8 8 0 0 1 3 12.65V14a1 1 0 0 1-1 1z" }) }) }),
|
|
525
|
-
/* @__PURE__ */ jsx("button", { style: s.closeBtn, onClick: onClose, children: "\u2715" })
|
|
526
|
-
] })
|
|
527
|
-
]
|
|
528
|
-
}
|
|
529
|
-
),
|
|
536
|
+
/* @__PURE__ */ jsxs("div", { style: getPanelStyle(pos, offset, position), ...dragHandlers, children: [
|
|
537
|
+
/* @__PURE__ */ jsxs("div", { style: s.panelHeader, children: [
|
|
538
|
+
/* @__PURE__ */ jsxs("span", { style: s.panelTitle, children: [
|
|
539
|
+
"Dev Profiler",
|
|
540
|
+
instanceCount > 1 && instanceId && /* @__PURE__ */ jsx("span", { style: s.instanceBadge, children: instanceId })
|
|
541
|
+
] }),
|
|
542
|
+
/* @__PURE__ */ jsxs("div", { style: s.headerActions, children: [
|
|
543
|
+
/* @__PURE__ */ jsx(
|
|
544
|
+
"button",
|
|
545
|
+
{
|
|
546
|
+
style: exportStyle,
|
|
547
|
+
onClick: handleExport,
|
|
548
|
+
title: exported ? "Exported!" : "Export stats as JSON",
|
|
549
|
+
children: exported ? /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("polyline", { points: "3.5 8.5 6.5 11.5 12.5 4.5" }) }) : /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M8 2v8M4 7l4 4 4-4M2 14h12" }) })
|
|
550
|
+
}
|
|
551
|
+
),
|
|
552
|
+
/* @__PURE__ */ jsx("button", { style: s.iconBtn, onClick: handleReset, title: "Reset counters", children: /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M14 1a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-4a1 1 0 0 1 0-2h1.6A6 6 0 0 0 2.07 7.5a1 1 0 1 1-1.97-.36A8 8 0 0 1 13 3.35V2a1 1 0 0 1 1-1zM2 15a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1h4a1 1 0 0 1 0 2H4.4A6 6 0 0 0 13.93 8.5a1 1 0 1 1 1.97.36A8 8 0 0 1 3 12.65V14a1 1 0 0 1-1 1z" }) }) }),
|
|
553
|
+
/* @__PURE__ */ jsx("button", { style: s.closeBtn, onClick: onClose, children: "\u2715" })
|
|
554
|
+
] })
|
|
555
|
+
] }),
|
|
530
556
|
/* @__PURE__ */ jsxs("div", { style: s.body, children: [
|
|
531
557
|
/* @__PURE__ */ jsx("span", { style: s.section, children: "Rendering" }),
|
|
532
558
|
/* @__PURE__ */ jsx(StatRow, { label: "Frame time", value: `${stats.frameTime.toFixed(1)}ms`, sub: `${fps} fps`, color: ftColor }),
|
|
@@ -570,38 +596,38 @@ function DevStatsPanel({
|
|
|
570
596
|
}
|
|
571
597
|
|
|
572
598
|
// src/ToggleButton.tsx
|
|
573
|
-
import { useState as useState3, useEffect as useEffect3
|
|
599
|
+
import { useState as useState3, useEffect as useEffect3 } from "react";
|
|
574
600
|
import { createPortal as createPortal2 } from "react-dom";
|
|
575
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
601
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
602
|
+
var GAP2 = 8;
|
|
576
603
|
function getButtonStyle(pos, position) {
|
|
577
604
|
const style = { ...s.toggleBtn };
|
|
578
605
|
if (position.startsWith("bottom")) {
|
|
579
|
-
style.bottom = window.innerHeight - pos.top +
|
|
606
|
+
style.bottom = window.innerHeight - pos.top + GAP2;
|
|
580
607
|
} else {
|
|
581
|
-
style.top = pos.top +
|
|
608
|
+
style.top = pos.top + GAP2;
|
|
582
609
|
}
|
|
583
610
|
if (position.endsWith("right")) {
|
|
584
|
-
style.right = window.innerWidth - pos.left;
|
|
611
|
+
style.right = window.innerWidth - pos.left + GAP2;
|
|
585
612
|
} else {
|
|
586
|
-
style.left = pos.left;
|
|
613
|
+
style.left = pos.left + GAP2;
|
|
587
614
|
}
|
|
588
615
|
return style;
|
|
589
616
|
}
|
|
590
617
|
function ToggleButton({
|
|
591
618
|
targetRef,
|
|
592
619
|
onClick,
|
|
593
|
-
position = "bottom-left"
|
|
620
|
+
position = "bottom-left",
|
|
621
|
+
accentColor = "#6366f1"
|
|
594
622
|
}) {
|
|
595
623
|
const pos = useAnchorPosition(targetRef, position);
|
|
596
624
|
const [fps, setFps] = useState3(0);
|
|
597
|
-
const lastFrame = useRef3(performance.now());
|
|
598
625
|
useEffect3(() => {
|
|
599
626
|
let animId;
|
|
600
627
|
let count = 0;
|
|
601
628
|
let lastSecond = performance.now();
|
|
602
629
|
const tick = () => {
|
|
603
630
|
const now = performance.now();
|
|
604
|
-
lastFrame.current = now;
|
|
605
631
|
count++;
|
|
606
632
|
if (now - lastSecond >= 1e3) {
|
|
607
633
|
setFps(count);
|
|
@@ -613,15 +639,18 @@ function ToggleButton({
|
|
|
613
639
|
animId = requestAnimationFrame(tick);
|
|
614
640
|
return () => cancelAnimationFrame(animId);
|
|
615
641
|
}, []);
|
|
616
|
-
const fpsColor = fps < 30 ? "#ef4444" : fps < 55 ? "#f59e0b" : "#4ade80";
|
|
617
642
|
return createPortal2(
|
|
618
|
-
/* @__PURE__ */
|
|
643
|
+
/* @__PURE__ */ jsxs2(
|
|
619
644
|
"button",
|
|
620
645
|
{
|
|
621
646
|
onClick,
|
|
622
647
|
title: "Dev Profiler (Ctrl+I)",
|
|
623
648
|
style: getButtonStyle(pos, position),
|
|
624
|
-
children:
|
|
649
|
+
children: [
|
|
650
|
+
/* @__PURE__ */ jsx2("span", { style: { ...s.toggleDot, background: accentColor, boxShadow: `0 0 4px ${accentColor}` } }),
|
|
651
|
+
/* @__PURE__ */ jsx2("span", { style: s.toggleFps, children: fps }),
|
|
652
|
+
/* @__PURE__ */ jsx2("span", { style: s.toggleLabel, children: "fps" })
|
|
653
|
+
]
|
|
625
654
|
}
|
|
626
655
|
),
|
|
627
656
|
document.body
|
|
@@ -629,7 +658,7 @@ function ToggleButton({
|
|
|
629
658
|
}
|
|
630
659
|
|
|
631
660
|
// src/DevProfiler.tsx
|
|
632
|
-
import { Fragment, jsx as jsx3, jsxs as
|
|
661
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
633
662
|
var TOGGLE_EVENT = "devprofiler:toggle";
|
|
634
663
|
var BOUND_KEY = "__devprofiler_bound";
|
|
635
664
|
if (typeof window !== "undefined" && __DEV__ && !window[BOUND_KEY]) {
|
|
@@ -646,12 +675,13 @@ var activeInstances = /* @__PURE__ */ new Set();
|
|
|
646
675
|
function DevProfiler({
|
|
647
676
|
children,
|
|
648
677
|
position = "bottom-left",
|
|
649
|
-
id
|
|
678
|
+
id,
|
|
679
|
+
accentColor = "#6366f1"
|
|
650
680
|
}) {
|
|
651
|
-
const wrapperRef =
|
|
681
|
+
const wrapperRef = useRef3(null);
|
|
652
682
|
const [open, setOpen] = useState4(false);
|
|
653
683
|
const toggle = useCallback3(() => setOpen((prev) => !prev), []);
|
|
654
|
-
const instanceId =
|
|
684
|
+
const instanceId = useRef3(id ?? `profiler-${++instanceCounter}`).current;
|
|
655
685
|
useEffect4(() => {
|
|
656
686
|
activeInstances.add(instanceId);
|
|
657
687
|
return () => {
|
|
@@ -662,7 +692,7 @@ function DevProfiler({
|
|
|
662
692
|
const renderRate = useRenderRate();
|
|
663
693
|
const longTasks = useLongTasks(open);
|
|
664
694
|
useRenderFlash(wrapperRef, open);
|
|
665
|
-
const profilerData =
|
|
695
|
+
const profilerData = useRef3({ ...INITIAL_PROFILER });
|
|
666
696
|
const onRender = useCallback3((_id, phase, actualDuration, baseDuration) => {
|
|
667
697
|
profilerData.current = {
|
|
668
698
|
phase,
|
|
@@ -684,9 +714,9 @@ function DevProfiler({
|
|
|
684
714
|
return () => window.removeEventListener(TOGGLE_EVENT, handler);
|
|
685
715
|
}, []);
|
|
686
716
|
if (!__DEV__) return /* @__PURE__ */ jsx3(Fragment, { children });
|
|
687
|
-
return /* @__PURE__ */
|
|
717
|
+
return /* @__PURE__ */ jsxs3("div", { ref: wrapperRef, style: { display: "contents" }, children: [
|
|
688
718
|
/* @__PURE__ */ jsx3(Profiler, { id: "DevProfiler", onRender, children }),
|
|
689
|
-
!open && /* @__PURE__ */ jsx3(ToggleButton, { targetRef: wrapperRef, onClick: toggle, position }),
|
|
719
|
+
!open && /* @__PURE__ */ jsx3(ToggleButton, { targetRef: wrapperRef, onClick: toggle, position, accentColor }),
|
|
690
720
|
open && /* @__PURE__ */ jsx3(
|
|
691
721
|
DevStatsPanel,
|
|
692
722
|
{
|