react-dev-profiler 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -5
- package/dist/index.cjs +130 -78
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +130 -78
- package/dist/index.js.map +1 -1
- package/package.json +2 -3
package/README.md
CHANGED
|
@@ -88,11 +88,12 @@ All observers are created lazily (only when the panel is open) and cleaned up on
|
|
|
88
88
|
|
|
89
89
|
### `<DevProfiler>`
|
|
90
90
|
|
|
91
|
-
| Prop
|
|
92
|
-
|
|
|
93
|
-
| `children`
|
|
94
|
-
| `position`
|
|
95
|
-
| `id`
|
|
91
|
+
| Prop | Type | Default | Description |
|
|
92
|
+
| ------------- | --------------- | --------------- | ------------------------------------------ |
|
|
93
|
+
| `children` | `ReactNode` | — | The subtree to profile |
|
|
94
|
+
| `position` | `PanelPosition` | `'bottom-left'` | Where to anchor the panel |
|
|
95
|
+
| `id` | `string` | auto-generated | Instance label (shown with multi-panels) |
|
|
96
|
+
| `accentColor` | `string` | `'#6366f1'` | Accent color for the toggle button's glow |
|
|
96
97
|
|
|
97
98
|
### `PanelPosition`
|
|
98
99
|
|
package/dist/index.cjs
CHANGED
|
@@ -55,6 +55,25 @@ function percentile(sorted, p) {
|
|
|
55
55
|
return sorted[Math.max(0, idx)];
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
// src/constants.ts
|
|
59
|
+
var COLOR_GREEN = "#4ade80";
|
|
60
|
+
var COLOR_AMBER = "#f59e0b";
|
|
61
|
+
var COLOR_RED = "#ef4444";
|
|
62
|
+
var COLOR_MUTED = "#888";
|
|
63
|
+
var COLOR_DIM = "#444";
|
|
64
|
+
var COLOR_ACCENT = "#6366f1";
|
|
65
|
+
var FPS_60_MS = 16.67;
|
|
66
|
+
var FPS_30_MS = 33;
|
|
67
|
+
var GRAPH_BG = "#111";
|
|
68
|
+
var GRAPH_60FPS_LINE = "#1a3a1a";
|
|
69
|
+
var GRAPH_30FPS_LINE = "#3a1a1a";
|
|
70
|
+
var PANEL_GAP = 8;
|
|
71
|
+
function ftColor(ms) {
|
|
72
|
+
if (ms > FPS_30_MS) return COLOR_RED;
|
|
73
|
+
if (ms > FPS_60_MS) return COLOR_AMBER;
|
|
74
|
+
return COLOR_GREEN;
|
|
75
|
+
}
|
|
76
|
+
|
|
58
77
|
// src/env.ts
|
|
59
78
|
var __DEV__ = typeof process !== "undefined" ? process.env.NODE_ENV !== "production" : true;
|
|
60
79
|
|
|
@@ -101,7 +120,7 @@ var s = {
|
|
|
101
120
|
},
|
|
102
121
|
instanceBadge: {
|
|
103
122
|
background: "#222",
|
|
104
|
-
color:
|
|
123
|
+
color: COLOR_MUTED,
|
|
105
124
|
fontSize: 8,
|
|
106
125
|
padding: "1px 5px",
|
|
107
126
|
borderRadius: 4,
|
|
@@ -116,7 +135,7 @@ var s = {
|
|
|
116
135
|
iconBtn: {
|
|
117
136
|
background: "none",
|
|
118
137
|
border: "none",
|
|
119
|
-
color:
|
|
138
|
+
color: COLOR_DIM,
|
|
120
139
|
cursor: "pointer",
|
|
121
140
|
padding: 4,
|
|
122
141
|
margin: -4,
|
|
@@ -126,12 +145,12 @@ var s = {
|
|
|
126
145
|
transition: "color 0.15s"
|
|
127
146
|
},
|
|
128
147
|
iconBtnActive: {
|
|
129
|
-
color:
|
|
148
|
+
color: COLOR_GREEN
|
|
130
149
|
},
|
|
131
150
|
closeBtn: {
|
|
132
151
|
background: "none",
|
|
133
152
|
border: "none",
|
|
134
|
-
color:
|
|
153
|
+
color: COLOR_DIM,
|
|
135
154
|
cursor: "pointer",
|
|
136
155
|
fontSize: 13,
|
|
137
156
|
padding: 4,
|
|
@@ -144,7 +163,7 @@ var s = {
|
|
|
144
163
|
gap: 5
|
|
145
164
|
},
|
|
146
165
|
section: {
|
|
147
|
-
color:
|
|
166
|
+
color: COLOR_DIM,
|
|
148
167
|
fontSize: 8,
|
|
149
168
|
fontWeight: 600,
|
|
150
169
|
letterSpacing: 1,
|
|
@@ -173,7 +192,7 @@ var s = {
|
|
|
173
192
|
miniRow: {
|
|
174
193
|
display: "flex",
|
|
175
194
|
justifyContent: "space-between",
|
|
176
|
-
color:
|
|
195
|
+
color: COLOR_DIM,
|
|
177
196
|
fontSize: 9,
|
|
178
197
|
marginTop: -2,
|
|
179
198
|
marginBottom: 2
|
|
@@ -226,9 +245,9 @@ var s = {
|
|
|
226
245
|
textAlign: "center"
|
|
227
246
|
}
|
|
228
247
|
};
|
|
229
|
-
var FLASH_OUTLINE =
|
|
248
|
+
var FLASH_OUTLINE = `2px solid ${COLOR_ACCENT}cc`;
|
|
230
249
|
|
|
231
|
-
// src/
|
|
250
|
+
// src/utils.ts
|
|
232
251
|
function getEffectiveRect(el) {
|
|
233
252
|
const rect = el.getBoundingClientRect();
|
|
234
253
|
if (rect.width > 0 || rect.height > 0) return rect;
|
|
@@ -255,6 +274,8 @@ function getObservableChildren(el) {
|
|
|
255
274
|
}
|
|
256
275
|
return result;
|
|
257
276
|
}
|
|
277
|
+
|
|
278
|
+
// src/hooks.ts
|
|
258
279
|
function useAnchorPosition(ref, position = "bottom-left") {
|
|
259
280
|
const [pos, setPos] = (0, import_react.useState)({ top: 0, left: 0 });
|
|
260
281
|
(0, import_react.useEffect)(() => {
|
|
@@ -400,22 +421,24 @@ function useLongTasks(enabled) {
|
|
|
400
421
|
// src/DevStatsPanel.tsx
|
|
401
422
|
var import_react2 = require("react");
|
|
402
423
|
var import_react_dom = require("react-dom");
|
|
424
|
+
|
|
425
|
+
// src/FrameTimeGraph.tsx
|
|
403
426
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
404
427
|
function FrameTimeGraph({ history }) {
|
|
405
|
-
const max = Math.max(
|
|
428
|
+
const max = Math.max(FPS_30_MS, ...history);
|
|
406
429
|
const w = 140;
|
|
407
430
|
const h = 32;
|
|
408
431
|
const barW = Math.max(1, w / HISTORY_SIZE - 0.5);
|
|
409
432
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: s.graphWrap, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: w, height: h, style: { display: "block" }, children: [
|
|
410
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { width: w, height: h, rx: 3, fill:
|
|
433
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { width: w, height: h, rx: 3, fill: GRAPH_BG }),
|
|
411
434
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
412
435
|
"line",
|
|
413
436
|
{
|
|
414
437
|
x1: 0,
|
|
415
|
-
y1: h -
|
|
438
|
+
y1: h - FPS_60_MS / max * h,
|
|
416
439
|
x2: w,
|
|
417
|
-
y2: h -
|
|
418
|
-
stroke:
|
|
440
|
+
y2: h - FPS_60_MS / max * h,
|
|
441
|
+
stroke: GRAPH_60FPS_LINE,
|
|
419
442
|
strokeWidth: 1
|
|
420
443
|
}
|
|
421
444
|
),
|
|
@@ -423,31 +446,36 @@ function FrameTimeGraph({ history }) {
|
|
|
423
446
|
"line",
|
|
424
447
|
{
|
|
425
448
|
x1: 0,
|
|
426
|
-
y1: h -
|
|
449
|
+
y1: h - FPS_30_MS / max * h,
|
|
427
450
|
x2: w,
|
|
428
|
-
y2: h -
|
|
429
|
-
stroke:
|
|
451
|
+
y2: h - FPS_30_MS / max * h,
|
|
452
|
+
stroke: GRAPH_30FPS_LINE,
|
|
430
453
|
strokeWidth: 1
|
|
431
454
|
}
|
|
432
455
|
),
|
|
433
456
|
history.map((ms, i) => {
|
|
434
457
|
const x = i / HISTORY_SIZE * w;
|
|
435
458
|
const barH = Math.min(ms / max * h, h);
|
|
436
|
-
|
|
437
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x, y: h - barH, width: barW, height: barH, fill: color, opacity: 0.8, rx: 0.5 }, i);
|
|
459
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { x, y: h - barH, width: barW, height: barH, fill: ftColor(ms), opacity: 0.8, rx: 0.5 }, i);
|
|
438
460
|
})
|
|
439
461
|
] }) });
|
|
440
462
|
}
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
463
|
+
|
|
464
|
+
// src/StatRow.tsx
|
|
465
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
466
|
+
function StatRow({ label, value, sub, color = COLOR_GREEN }) {
|
|
467
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: s.row, children: [
|
|
468
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: s.rowLabel, children: label }),
|
|
469
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { children: [
|
|
470
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { ...s.rowValue, color }, children: value }),
|
|
471
|
+
sub && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { color: COLOR_DIM, fontSize: 9, marginLeft: 4 }, children: sub })
|
|
447
472
|
] })
|
|
448
473
|
] });
|
|
449
474
|
}
|
|
450
|
-
|
|
475
|
+
|
|
476
|
+
// src/DevStatsPanel.tsx
|
|
477
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
478
|
+
var GAP = PANEL_GAP;
|
|
451
479
|
function getPanelStyle(pos, offset, position) {
|
|
452
480
|
const style = {
|
|
453
481
|
...s.panel,
|
|
@@ -551,71 +579,71 @@ function DevStatsPanel({
|
|
|
551
579
|
setExported(true);
|
|
552
580
|
setTimeout(() => setExported(false), 1200);
|
|
553
581
|
}, [stats]);
|
|
554
|
-
const
|
|
555
|
-
const rpsColor = stats.rendersPerSecond > 30 ?
|
|
556
|
-
const actualColor = stats.profiler.actualDuration > 16 ?
|
|
582
|
+
const frameTColor = ftColor(stats.frameTime);
|
|
583
|
+
const rpsColor = stats.rendersPerSecond > 30 ? COLOR_RED : stats.rendersPerSecond > 10 ? COLOR_AMBER : COLOR_GREEN;
|
|
584
|
+
const actualColor = stats.profiler.actualDuration > 16 ? COLOR_RED : stats.profiler.actualDuration > 8 ? COLOR_AMBER : COLOR_GREEN;
|
|
557
585
|
const fps = stats.frameTime > 0 ? Math.round(1e3 / stats.frameTime) : 0;
|
|
558
586
|
const memoGain = stats.profiler.baseDuration > 0 ? Math.round((1 - stats.profiler.actualDuration / stats.profiler.baseDuration) * 100) : 0;
|
|
559
|
-
const p99Color = stats.frameTimeP99
|
|
587
|
+
const p99Color = ftColor(stats.frameTimeP99);
|
|
560
588
|
const exportStyle = exported ? { ...s.iconBtn, ...s.iconBtnActive } : s.iconBtn;
|
|
561
589
|
return (0, import_react_dom.createPortal)(
|
|
562
|
-
/* @__PURE__ */ (0,
|
|
563
|
-
/* @__PURE__ */ (0,
|
|
564
|
-
/* @__PURE__ */ (0,
|
|
590
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: getPanelStyle(pos, offset, position), ...dragHandlers, children: [
|
|
591
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: s.panelHeader, children: [
|
|
592
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: s.panelTitle, children: [
|
|
565
593
|
"Dev Profiler",
|
|
566
|
-
instanceCount > 1 && instanceId && /* @__PURE__ */ (0,
|
|
594
|
+
instanceCount > 1 && instanceId && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: s.instanceBadge, children: instanceId })
|
|
567
595
|
] }),
|
|
568
|
-
/* @__PURE__ */ (0,
|
|
569
|
-
/* @__PURE__ */ (0,
|
|
596
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: s.headerActions, children: [
|
|
597
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
570
598
|
"button",
|
|
571
599
|
{
|
|
572
600
|
style: exportStyle,
|
|
573
601
|
onClick: handleExport,
|
|
574
602
|
title: exported ? "Exported!" : "Export stats as JSON",
|
|
575
|
-
children: exported ? /* @__PURE__ */ (0,
|
|
603
|
+
children: exported ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("polyline", { points: "3.5 8.5 6.5 11.5 12.5 4.5" }) }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M8 2v8M4 7l4 4 4-4M2 14h12" }) })
|
|
576
604
|
}
|
|
577
605
|
),
|
|
578
|
-
/* @__PURE__ */ (0,
|
|
579
|
-
/* @__PURE__ */ (0,
|
|
606
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { style: s.iconBtn, onClick: handleReset, title: "Reset counters", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime3.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" }) }) }),
|
|
607
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { style: s.closeBtn, onClick: onClose, children: "\u2715" })
|
|
580
608
|
] })
|
|
581
609
|
] }),
|
|
582
|
-
/* @__PURE__ */ (0,
|
|
583
|
-
/* @__PURE__ */ (0,
|
|
584
|
-
/* @__PURE__ */ (0,
|
|
585
|
-
/* @__PURE__ */ (0,
|
|
586
|
-
/* @__PURE__ */ (0,
|
|
587
|
-
/* @__PURE__ */ (0,
|
|
610
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: s.body, children: [
|
|
611
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: s.section, children: "Rendering" }),
|
|
612
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatRow, { label: "Frame time", value: `${stats.frameTime.toFixed(1)}ms`, sub: `${fps} fps`, color: frameTColor }),
|
|
613
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(FrameTimeGraph, { history: stats.frameTimeHistory }),
|
|
614
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: s.miniRow, children: [
|
|
615
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
|
|
588
616
|
"min ",
|
|
589
617
|
stats.frameTimeMin.toFixed(1)
|
|
590
618
|
] }),
|
|
591
|
-
/* @__PURE__ */ (0,
|
|
619
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
|
|
592
620
|
"max ",
|
|
593
621
|
stats.frameTimeMax.toFixed(1)
|
|
594
622
|
] }),
|
|
595
|
-
/* @__PURE__ */ (0,
|
|
623
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: { color: p99Color }, children: [
|
|
596
624
|
"p99 ",
|
|
597
625
|
stats.frameTimeP99.toFixed(1)
|
|
598
626
|
] })
|
|
599
627
|
] }),
|
|
600
|
-
/* @__PURE__ */ (0,
|
|
601
|
-
/* @__PURE__ */ (0,
|
|
602
|
-
/* @__PURE__ */ (0,
|
|
603
|
-
/* @__PURE__ */ (0,
|
|
604
|
-
/* @__PURE__ */ (0,
|
|
605
|
-
/* @__PURE__ */ (0,
|
|
606
|
-
/* @__PURE__ */ (0,
|
|
607
|
-
/* @__PURE__ */ (0,
|
|
608
|
-
/* @__PURE__ */ (0,
|
|
609
|
-
/* @__PURE__ */ (0,
|
|
610
|
-
/* @__PURE__ */ (0,
|
|
611
|
-
/* @__PURE__ */ (0,
|
|
612
|
-
/* @__PURE__ */ (0,
|
|
613
|
-
/* @__PURE__ */ (0,
|
|
614
|
-
/* @__PURE__ */ (0,
|
|
615
|
-
/* @__PURE__ */ (0,
|
|
616
|
-
/* @__PURE__ */ (0,
|
|
628
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatRow, { label: "Renders/s", value: String(stats.rendersPerSecond), color: rpsColor }),
|
|
629
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatRow, { label: "Long tasks", value: String(stats.longTasks), color: stats.longTasks > 0 ? COLOR_AMBER : COLOR_GREEN }),
|
|
630
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: s.separator }),
|
|
631
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: s.section, children: "React Profiler" }),
|
|
632
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatRow, { label: "Phase", value: stats.profiler.phase, color: COLOR_MUTED }),
|
|
633
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatRow, { label: "Render", value: `${stats.profiler.actualDuration.toFixed(2)}ms`, color: actualColor }),
|
|
634
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatRow, { label: "Base (no memo)", value: `${stats.profiler.baseDuration.toFixed(2)}ms`, color: COLOR_MUTED }),
|
|
635
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatRow, { label: "Memo gain", value: `${memoGain}%`, color: memoGain > 50 ? COLOR_GREEN : memoGain > 20 ? COLOR_AMBER : COLOR_RED }),
|
|
636
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatRow, { label: "Commits", value: String(stats.profiler.commitCount) }),
|
|
637
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: s.separator }),
|
|
638
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: s.section, children: "DOM" }),
|
|
639
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatRow, { label: "Nodes", value: stats.domNodes.toLocaleString() }),
|
|
640
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatRow, { label: "Mutations", value: String(stats.domMutations) }),
|
|
641
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatRow, { label: "Size", value: stats.dimensions, color: COLOR_MUTED }),
|
|
642
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: s.separator }),
|
|
643
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: s.section, children: "Memory" }),
|
|
644
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StatRow, { label: "JS Heap", value: stats.memory > 0 ? `${stats.memory} MB` : "N/A" })
|
|
617
645
|
] }),
|
|
618
|
-
/* @__PURE__ */ (0,
|
|
646
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: s.footer, children: "Ctrl+I to toggle" })
|
|
619
647
|
] }),
|
|
620
648
|
document.body
|
|
621
649
|
);
|
|
@@ -624,8 +652,8 @@ function DevStatsPanel({
|
|
|
624
652
|
// src/ToggleButton.tsx
|
|
625
653
|
var import_react3 = require("react");
|
|
626
654
|
var import_react_dom2 = require("react-dom");
|
|
627
|
-
var
|
|
628
|
-
var GAP2 =
|
|
655
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
656
|
+
var GAP2 = PANEL_GAP;
|
|
629
657
|
function getButtonStyle(pos, position) {
|
|
630
658
|
const style = { ...s.toggleBtn };
|
|
631
659
|
if (position.startsWith("bottom")) {
|
|
@@ -644,7 +672,7 @@ function ToggleButton({
|
|
|
644
672
|
targetRef,
|
|
645
673
|
onClick,
|
|
646
674
|
position = "bottom-left",
|
|
647
|
-
accentColor =
|
|
675
|
+
accentColor = COLOR_ACCENT
|
|
648
676
|
}) {
|
|
649
677
|
const pos = useAnchorPosition(targetRef, position);
|
|
650
678
|
const [fps, setFps] = (0, import_react3.useState)(0);
|
|
@@ -666,16 +694,16 @@ function ToggleButton({
|
|
|
666
694
|
return () => cancelAnimationFrame(animId);
|
|
667
695
|
}, []);
|
|
668
696
|
return (0, import_react_dom2.createPortal)(
|
|
669
|
-
/* @__PURE__ */ (0,
|
|
697
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
670
698
|
"button",
|
|
671
699
|
{
|
|
672
700
|
onClick,
|
|
673
701
|
title: "Dev Profiler (Ctrl+I)",
|
|
674
702
|
style: getButtonStyle(pos, position),
|
|
675
703
|
children: [
|
|
676
|
-
/* @__PURE__ */ (0,
|
|
677
|
-
/* @__PURE__ */ (0,
|
|
678
|
-
/* @__PURE__ */ (0,
|
|
704
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { ...s.toggleDot, background: accentColor, boxShadow: `0 0 4px ${accentColor}` } }),
|
|
705
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: s.toggleFps, children: fps }),
|
|
706
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: s.toggleLabel, children: "fps" })
|
|
679
707
|
]
|
|
680
708
|
}
|
|
681
709
|
),
|
|
@@ -684,7 +712,7 @@ function ToggleButton({
|
|
|
684
712
|
}
|
|
685
713
|
|
|
686
714
|
// src/DevProfiler.tsx
|
|
687
|
-
var
|
|
715
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
688
716
|
var TOGGLE_EVENT = "devprofiler:toggle";
|
|
689
717
|
var BOUND_KEY = "__devprofiler_bound";
|
|
690
718
|
if (typeof window !== "undefined" && __DEV__ && !window[BOUND_KEY]) {
|
|
@@ -702,7 +730,7 @@ function DevProfiler({
|
|
|
702
730
|
children,
|
|
703
731
|
position = "bottom-left",
|
|
704
732
|
id,
|
|
705
|
-
accentColor =
|
|
733
|
+
accentColor = COLOR_ACCENT
|
|
706
734
|
}) {
|
|
707
735
|
const wrapperRef = (0, import_react4.useRef)(null);
|
|
708
736
|
const [open, setOpen] = (0, import_react4.useState)(false);
|
|
@@ -739,11 +767,11 @@ function DevProfiler({
|
|
|
739
767
|
window.addEventListener(TOGGLE_EVENT, handler);
|
|
740
768
|
return () => window.removeEventListener(TOGGLE_EVENT, handler);
|
|
741
769
|
}, []);
|
|
742
|
-
if (!__DEV__) return /* @__PURE__ */ (0,
|
|
743
|
-
return /* @__PURE__ */ (0,
|
|
744
|
-
/* @__PURE__ */ (0,
|
|
745
|
-
!open && /* @__PURE__ */ (0,
|
|
746
|
-
open && /* @__PURE__ */ (0,
|
|
770
|
+
if (!__DEV__) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children });
|
|
771
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: wrapperRef, style: { display: "contents" }, children: [
|
|
772
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react4.Profiler, { id: "DevProfiler", onRender, children }),
|
|
773
|
+
!open && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ToggleButton, { targetRef: wrapperRef, onClick: toggle, position, accentColor }),
|
|
774
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
747
775
|
DevStatsPanel,
|
|
748
776
|
{
|
|
749
777
|
targetRef: wrapperRef,
|
|
@@ -770,6 +798,12 @@ function DevProfiler({
|
|
|
770
798
|
* @author Frederic Denis (billywild87) — https://github.com/billywild87
|
|
771
799
|
* @license MIT
|
|
772
800
|
*/
|
|
801
|
+
/**
|
|
802
|
+
* @module react-dev-profiler
|
|
803
|
+
* @description Shared colors and thresholds used across the profiler UI.
|
|
804
|
+
* @author Frederic Denis (billywild87) — https://github.com/billywild87
|
|
805
|
+
* @license MIT
|
|
806
|
+
*/
|
|
773
807
|
/**
|
|
774
808
|
* @module react-dev-profiler
|
|
775
809
|
* @description Environment detection — works with Vite, webpack, Next.js, and any bundler.
|
|
@@ -782,12 +816,30 @@ function DevProfiler({
|
|
|
782
816
|
* @author Frederic Denis (billywild87) — https://github.com/billywild87
|
|
783
817
|
* @license MIT
|
|
784
818
|
*/
|
|
819
|
+
/**
|
|
820
|
+
* @module react-dev-profiler
|
|
821
|
+
* @description Pure utility functions for DOM measurement.
|
|
822
|
+
* @author Frederic Denis (billywild87) — https://github.com/billywild87
|
|
823
|
+
* @license MIT
|
|
824
|
+
*/
|
|
785
825
|
/**
|
|
786
826
|
* @module react-dev-profiler
|
|
787
827
|
* @description Custom hooks that power the profiler's data collection.
|
|
788
828
|
* @author Frederic Denis (billywild87) — https://github.com/billywild87
|
|
789
829
|
* @license MIT
|
|
790
830
|
*/
|
|
831
|
+
/**
|
|
832
|
+
* @module react-dev-profiler
|
|
833
|
+
* @description Rolling bar chart of frame times (last 60 samples).
|
|
834
|
+
* @author Frederic Denis (billywild87) — https://github.com/billywild87
|
|
835
|
+
* @license MIT
|
|
836
|
+
*/
|
|
837
|
+
/**
|
|
838
|
+
* @module react-dev-profiler
|
|
839
|
+
* @description Single label/value row used throughout the profiler panel.
|
|
840
|
+
* @author Frederic Denis (billywild87) — https://github.com/billywild87
|
|
841
|
+
* @license MIT
|
|
842
|
+
*/
|
|
791
843
|
/**
|
|
792
844
|
* @module react-dev-profiler
|
|
793
845
|
* @description The main stats panel — renders all performance metrics in a floating overlay.
|