react-dev-profiler 1.0.2 → 1.1.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.cjs CHANGED
@@ -20,7 +20,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
- DevProfiler: () => DevProfiler
23
+ DevProfiler: () => DevProfiler,
24
+ default: () => DevProfiler
24
25
  });
25
26
  module.exports = __toCommonJS(index_exports);
26
27
 
@@ -79,15 +80,15 @@ var s = {
79
80
  backdropFilter: "blur(12px)",
80
81
  userSelect: "none",
81
82
  color: "#ccc",
82
- fontSize: 11
83
+ fontSize: 11,
84
+ cursor: "grab",
85
+ touchAction: "none"
83
86
  },
84
87
  panelHeader: {
85
88
  display: "flex",
86
89
  justifyContent: "space-between",
87
90
  alignItems: "center",
88
- marginBottom: 8,
89
- cursor: "grab",
90
- touchAction: "none"
91
+ marginBottom: 8
91
92
  },
92
93
  panelTitle: {
93
94
  color: "#666",
@@ -118,7 +119,8 @@ var s = {
118
119
  border: "none",
119
120
  color: "#444",
120
121
  cursor: "pointer",
121
- padding: 0,
122
+ padding: 4,
123
+ margin: -4,
122
124
  lineHeight: 1,
123
125
  display: "flex",
124
126
  alignItems: "center",
@@ -133,7 +135,8 @@ var s = {
133
135
  color: "#444",
134
136
  cursor: "pointer",
135
137
  fontSize: 13,
136
- padding: 0,
138
+ padding: 4,
139
+ margin: -4,
137
140
  lineHeight: 1
138
141
  },
139
142
  body: {
@@ -182,23 +185,40 @@ var s = {
182
185
  toggleBtn: {
183
186
  position: "fixed",
184
187
  zIndex: 99998,
185
- minWidth: 28,
186
- height: 24,
187
- borderRadius: 7,
188
- border: "1px solid #2a2a2a",
189
- background: "rgba(20, 20, 20, 0.9)",
188
+ height: 26,
189
+ borderRadius: 13,
190
+ border: "1px solid rgba(255, 255, 255, 0.08)",
191
+ background: "rgba(28, 28, 30, 0.92)",
190
192
  cursor: "pointer",
191
193
  display: "flex",
192
194
  alignItems: "center",
193
- justifyContent: "center",
194
- padding: "0 6px",
195
- backdropFilter: "blur(8px)"
195
+ gap: 6,
196
+ padding: "0 10px 0 8px",
197
+ backdropFilter: "blur(20px)",
198
+ WebkitBackdropFilter: "blur(20px)",
199
+ boxShadow: "0 1px 3px rgba(0, 0, 0, 0.4), inset 0 0.5px 0 rgba(255, 255, 255, 0.06)"
200
+ },
201
+ toggleDot: {
202
+ width: 6,
203
+ height: 6,
204
+ borderRadius: "50%",
205
+ flexShrink: 0
196
206
  },
197
207
  toggleFps: {
198
208
  fontFamily: "'SF Mono', 'Fira Code', monospace",
199
- fontSize: 10,
200
- fontWeight: 700,
201
- letterSpacing: -0.5
209
+ fontSize: 11,
210
+ fontWeight: 600,
211
+ color: "rgba(255, 255, 255, 0.85)",
212
+ letterSpacing: -0.3,
213
+ lineHeight: 1
214
+ },
215
+ toggleLabel: {
216
+ fontFamily: "'SF Mono', 'Fira Code', monospace",
217
+ fontSize: 9,
218
+ fontWeight: 500,
219
+ color: "rgba(255, 255, 255, 0.35)",
220
+ letterSpacing: 0,
221
+ textTransform: "lowercase"
202
222
  },
203
223
  footer: {
204
224
  marginTop: 8,
@@ -210,32 +230,59 @@ var s = {
210
230
  var FLASH_OUTLINE = "2px solid rgba(99, 102, 241, 0.8)";
211
231
 
212
232
  // src/hooks.ts
233
+ function getEffectiveRect(el) {
234
+ const rect = el.getBoundingClientRect();
235
+ if (rect.width > 0 || rect.height > 0) return rect;
236
+ const children = el.children;
237
+ if (children.length === 0) return rect;
238
+ let top = Infinity, left = Infinity, bottom = -Infinity, right = -Infinity;
239
+ for (let i = 0; i < children.length; i++) {
240
+ const cr = children[i].getBoundingClientRect();
241
+ if (cr.width === 0 && cr.height === 0) continue;
242
+ top = Math.min(top, cr.top);
243
+ left = Math.min(left, cr.left);
244
+ bottom = Math.max(bottom, cr.bottom);
245
+ right = Math.max(right, cr.right);
246
+ }
247
+ if (top === Infinity) return rect;
248
+ return new DOMRect(left, top, right - left, bottom - top);
249
+ }
250
+ function getObservableChildren(el) {
251
+ const result = [];
252
+ for (let i = 0; i < el.children.length; i++) {
253
+ const child = el.children[i];
254
+ const r = child.getBoundingClientRect();
255
+ if (r.width > 0 || r.height > 0) result.push(child);
256
+ }
257
+ return result;
258
+ }
213
259
  function useAnchorPosition(ref, position = "bottom-left") {
214
260
  const [pos, setPos] = (0, import_react.useState)({ top: 0, left: 0 });
215
261
  (0, import_react.useEffect)(() => {
216
262
  if (!ref.current) return;
263
+ const el = ref.current;
217
264
  const update = () => {
218
- if (!ref.current) return;
219
- const rect = ref.current.getBoundingClientRect();
220
- const margin = 8;
265
+ const rect = getEffectiveRect(el);
221
266
  switch (position) {
222
267
  case "top-left":
223
- setPos({ top: rect.top + margin, left: rect.left + margin });
268
+ setPos({ top: rect.top, left: rect.left });
224
269
  break;
225
270
  case "top-right":
226
- setPos({ top: rect.top + margin, left: rect.right - margin });
271
+ setPos({ top: rect.top, left: rect.right });
227
272
  break;
228
273
  case "bottom-right":
229
- setPos({ top: rect.bottom - margin, left: rect.right - margin });
274
+ setPos({ top: rect.bottom, left: rect.right });
230
275
  break;
231
276
  case "bottom-left":
232
277
  default:
233
- setPos({ top: rect.bottom - margin, left: rect.left + margin });
278
+ setPos({ top: rect.bottom, left: rect.left });
234
279
  break;
235
280
  }
236
281
  };
282
+ update();
237
283
  const observer = new ResizeObserver(update);
238
- observer.observe(ref.current);
284
+ observer.observe(el);
285
+ for (const child of getObservableChildren(el)) observer.observe(child);
239
286
  observer.observe(document.documentElement);
240
287
  return () => observer.disconnect();
241
288
  }, [ref, position]);
@@ -246,9 +293,10 @@ function useDraggable() {
246
293
  const dragging = (0, import_react.useRef)(false);
247
294
  const start = (0, import_react.useRef)({ x: 0, y: 0 });
248
295
  const onPointerDown = (0, import_react.useCallback)((e) => {
296
+ if (e.target.closest("button, a, [data-no-drag]")) return;
249
297
  dragging.current = true;
250
298
  start.current = { x: e.clientX - offset.x, y: e.clientY - offset.y };
251
- e.target.setPointerCapture(e.pointerId);
299
+ e.currentTarget.setPointerCapture(e.pointerId);
252
300
  }, [offset]);
253
301
  const onPointerMove = (0, import_react.useCallback)((e) => {
254
302
  if (!dragging.current) return;
@@ -268,21 +316,13 @@ function useDomTracker(wrapperRef, enabled) {
268
316
  const dirty = (0, import_react.useRef)(true);
269
317
  (0, import_react.useEffect)(() => {
270
318
  if (!enabled || !wrapperRef.current) return;
271
- const observer = new MutationObserver((records) => {
272
- let realMutation = false;
273
- for (const record of records) {
274
- if (record.type === "attributes" && record.attributeName === "class") continue;
275
- realMutation = true;
276
- }
277
- if (realMutation) {
278
- mutations.current++;
279
- dirty.current = true;
280
- }
319
+ const observer = new MutationObserver(() => {
320
+ mutations.current++;
321
+ dirty.current = true;
281
322
  });
282
323
  observer.observe(wrapperRef.current, {
283
324
  childList: true,
284
325
  subtree: true,
285
- attributes: true,
286
326
  attributeFilter: ["style"]
287
327
  });
288
328
  return () => observer.disconnect();
@@ -323,18 +363,19 @@ function useRenderFlash(wrapperRef, open) {
323
363
  const mutationCount = (0, import_react.useRef)(0);
324
364
  (0, import_react.useEffect)(() => {
325
365
  if (!open || !wrapperRef.current) return;
366
+ const wrapper = wrapperRef.current;
326
367
  const observer = new MutationObserver(() => {
327
368
  mutationCount.current++;
328
- if (!wrapperRef.current || mutationCount.current <= 1) return;
329
- const el = wrapperRef.current;
330
- el.style.outline = FLASH_OUTLINE;
331
- el.style.outlineOffset = "-2px";
369
+ if (mutationCount.current <= 1) return;
370
+ const target = getObservableChildren(wrapper)[0] ?? wrapper;
371
+ target.style.outline = FLASH_OUTLINE;
372
+ target.style.outlineOffset = "-2px";
332
373
  setTimeout(() => {
333
- el.style.outline = "";
334
- el.style.outlineOffset = "";
374
+ target.style.outline = "";
375
+ target.style.outlineOffset = "";
335
376
  }, 150);
336
377
  });
337
- observer.observe(wrapperRef.current, { childList: true, subtree: true });
378
+ observer.observe(wrapper, { childList: true, subtree: true });
338
379
  return () => observer.disconnect();
339
380
  }, [wrapperRef, open]);
340
381
  }
@@ -407,20 +448,21 @@ function StatRow({ label, value, sub, color = "#4ade80" }) {
407
448
  ] })
408
449
  ] });
409
450
  }
451
+ var GAP = 8;
410
452
  function getPanelStyle(pos, offset, position) {
411
453
  const style = {
412
454
  ...s.panel,
413
455
  transform: `translate(${offset.x}px, ${offset.y}px)`
414
456
  };
415
457
  if (position.startsWith("bottom")) {
416
- style.bottom = window.innerHeight - pos.top;
458
+ style.bottom = window.innerHeight - pos.top + GAP;
417
459
  } else {
418
- style.top = pos.top;
460
+ style.top = pos.top + GAP;
419
461
  }
420
462
  if (position.endsWith("right")) {
421
- style.right = window.innerWidth - pos.left;
463
+ style.right = window.innerWidth - pos.left + GAP;
422
464
  } else {
423
- style.left = pos.left;
465
+ style.left = pos.left + GAP;
424
466
  }
425
467
  return style;
426
468
  }
@@ -462,7 +504,8 @@ function DevStatsPanel({
462
504
  allFrameTimes.current.push(avgFrameTime);
463
505
  const sorted = [...allFrameTimes.current].sort((a, b) => a - b);
464
506
  const el = targetRef.current;
465
- const dims = el ? `${el.offsetWidth} x ${el.offsetHeight}` : "\u2013";
507
+ const r = el ? getEffectiveRect(el) : null;
508
+ const dims = r ? `${Math.round(r.width)} x ${Math.round(r.height)}` : "\u2013";
466
509
  const perf = performance;
467
510
  const mem = perf.memory ? Math.round(perf.memory.usedJSHeapSize / 1024 / 1024) : 0;
468
511
  setStats({
@@ -497,23 +540,17 @@ function DevStatsPanel({
497
540
  const handleExport = (0, import_react2.useCallback)(() => {
498
541
  const payload = { timestamp: (/* @__PURE__ */ new Date()).toISOString(), ...stats };
499
542
  const json = JSON.stringify(payload, null, 2);
500
- try {
501
- navigator.clipboard.writeText(json).then(() => {
502
- setExported(true);
503
- setTimeout(() => setExported(false), 1200);
504
- });
505
- } catch {
506
- const ta = document.createElement("textarea");
507
- ta.value = json;
508
- ta.style.position = "fixed";
509
- ta.style.opacity = "0";
510
- document.body.appendChild(ta);
511
- ta.select();
512
- document.execCommand("copy");
513
- document.body.removeChild(ta);
514
- setExported(true);
515
- setTimeout(() => setExported(false), 1200);
516
- }
543
+ const blob = new Blob([json], { type: "application/json" });
544
+ const url = URL.createObjectURL(blob);
545
+ const a = document.createElement("a");
546
+ a.href = url;
547
+ a.download = `devprofiler-${Date.now()}.json`;
548
+ document.body.appendChild(a);
549
+ a.click();
550
+ document.body.removeChild(a);
551
+ URL.revokeObjectURL(url);
552
+ setExported(true);
553
+ setTimeout(() => setExported(false), 1200);
517
554
  }, [stats]);
518
555
  const ftColor = stats.frameTime > 33 ? "#ef4444" : stats.frameTime > 16.67 ? "#f59e0b" : "#4ade80";
519
556
  const rpsColor = stats.rendersPerSecond > 30 ? "#ef4444" : stats.rendersPerSecond > 10 ? "#f59e0b" : "#4ade80";
@@ -523,36 +560,26 @@ function DevStatsPanel({
523
560
  const p99Color = stats.frameTimeP99 > 33 ? "#ef4444" : stats.frameTimeP99 > 16.67 ? "#f59e0b" : "#4ade80";
524
561
  const exportStyle = exported ? { ...s.iconBtn, ...s.iconBtnActive } : s.iconBtn;
525
562
  return (0, import_react_dom.createPortal)(
526
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: getPanelStyle(pos, offset, position), children: [
527
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
528
- "div",
529
- {
530
- style: s.panelHeader,
531
- ...dragHandlers,
532
- children: [
533
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: s.panelTitle, children: [
534
- "Dev Profiler",
535
- instanceCount > 1 && instanceId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: s.instanceBadge, children: instanceId })
536
- ] }),
537
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: s.headerActions, children: [
538
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
539
- "button",
540
- {
541
- style: exportStyle,
542
- onClick: handleExport,
543
- title: exported ? "Copied!" : "Copy stats to clipboard",
544
- children: exported ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.75.75 0 0 1 1.06-1.06L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0z" }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "currentColor", children: [
545
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25z" }),
546
- /* @__PURE__ */ (0, import_jsx_runtime.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" })
547
- ] })
548
- }
549
- ),
550
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: s.iconBtn, onClick: handleReset, title: "Reset counters", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime.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" }) }) }),
551
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: s.closeBtn, onClick: onClose, children: "\u2715" })
552
- ] })
553
- ]
554
- }
555
- ),
563
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: getPanelStyle(pos, offset, position), ...dragHandlers, children: [
564
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: s.panelHeader, children: [
565
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: s.panelTitle, children: [
566
+ "Dev Profiler",
567
+ instanceCount > 1 && instanceId && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: s.instanceBadge, children: instanceId })
568
+ ] }),
569
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: s.headerActions, children: [
570
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
571
+ "button",
572
+ {
573
+ style: exportStyle,
574
+ onClick: handleExport,
575
+ title: exported ? "Exported!" : "Export stats as JSON",
576
+ children: exported ? /* @__PURE__ */ (0, import_jsx_runtime.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_runtime.jsx)("polyline", { points: "3.5 8.5 6.5 11.5 12.5 4.5" }) }) : /* @__PURE__ */ (0, import_jsx_runtime.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_runtime.jsx)("path", { d: "M8 2v8M4 7l4 4 4-4M2 14h12" }) })
577
+ }
578
+ ),
579
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: s.iconBtn, onClick: handleReset, title: "Reset counters", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime.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" }) }) }),
580
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { style: s.closeBtn, onClick: onClose, children: "\u2715" })
581
+ ] })
582
+ ] }),
556
583
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: s.body, children: [
557
584
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: s.section, children: "Rendering" }),
558
585
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatRow, { label: "Frame time", value: `${stats.frameTime.toFixed(1)}ms`, sub: `${fps} fps`, color: ftColor }),
@@ -599,35 +626,35 @@ function DevStatsPanel({
599
626
  var import_react3 = require("react");
600
627
  var import_react_dom2 = require("react-dom");
601
628
  var import_jsx_runtime2 = require("react/jsx-runtime");
629
+ var GAP2 = 8;
602
630
  function getButtonStyle(pos, position) {
603
631
  const style = { ...s.toggleBtn };
604
632
  if (position.startsWith("bottom")) {
605
- style.bottom = window.innerHeight - pos.top + 8;
633
+ style.bottom = window.innerHeight - pos.top + GAP2;
606
634
  } else {
607
- style.top = pos.top + 8;
635
+ style.top = pos.top + GAP2;
608
636
  }
609
637
  if (position.endsWith("right")) {
610
- style.right = window.innerWidth - pos.left;
638
+ style.right = window.innerWidth - pos.left + GAP2;
611
639
  } else {
612
- style.left = pos.left;
640
+ style.left = pos.left + GAP2;
613
641
  }
614
642
  return style;
615
643
  }
616
644
  function ToggleButton({
617
645
  targetRef,
618
646
  onClick,
619
- position = "bottom-left"
647
+ position = "bottom-left",
648
+ accentColor = "#6366f1"
620
649
  }) {
621
650
  const pos = useAnchorPosition(targetRef, position);
622
651
  const [fps, setFps] = (0, import_react3.useState)(0);
623
- const lastFrame = (0, import_react3.useRef)(performance.now());
624
652
  (0, import_react3.useEffect)(() => {
625
653
  let animId;
626
654
  let count = 0;
627
655
  let lastSecond = performance.now();
628
656
  const tick = () => {
629
657
  const now = performance.now();
630
- lastFrame.current = now;
631
658
  count++;
632
659
  if (now - lastSecond >= 1e3) {
633
660
  setFps(count);
@@ -639,15 +666,18 @@ function ToggleButton({
639
666
  animId = requestAnimationFrame(tick);
640
667
  return () => cancelAnimationFrame(animId);
641
668
  }, []);
642
- const fpsColor = fps < 30 ? "#ef4444" : fps < 55 ? "#f59e0b" : "#4ade80";
643
669
  return (0, import_react_dom2.createPortal)(
644
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
670
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
645
671
  "button",
646
672
  {
647
673
  onClick,
648
674
  title: "Dev Profiler (Ctrl+I)",
649
675
  style: getButtonStyle(pos, position),
650
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { ...s.toggleFps, color: fpsColor }, children: fps })
676
+ children: [
677
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { ...s.toggleDot, background: accentColor, boxShadow: `0 0 4px ${accentColor}` } }),
678
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: s.toggleFps, children: fps }),
679
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: s.toggleLabel, children: "fps" })
680
+ ]
651
681
  }
652
682
  ),
653
683
  document.body
@@ -672,7 +702,8 @@ var activeInstances = /* @__PURE__ */ new Set();
672
702
  function DevProfiler({
673
703
  children,
674
704
  position = "bottom-left",
675
- id
705
+ id,
706
+ accentColor = "#6366f1"
676
707
  }) {
677
708
  const wrapperRef = (0, import_react4.useRef)(null);
678
709
  const [open, setOpen] = (0, import_react4.useState)(false);
@@ -712,7 +743,7 @@ function DevProfiler({
712
743
  if (!__DEV__) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children });
713
744
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { ref: wrapperRef, style: { display: "contents" }, children: [
714
745
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react4.Profiler, { id: "DevProfiler", onRender, children }),
715
- !open && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ToggleButton, { targetRef: wrapperRef, onClick: toggle, position }),
746
+ !open && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ToggleButton, { targetRef: wrapperRef, onClick: toggle, position, accentColor }),
716
747
  open && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
717
748
  DevStatsPanel,
718
749
  {