react-dev-insight 1.0.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.
@@ -0,0 +1,765 @@
1
+ import { subscribeToReRenders } from './chunk-HH72HK3H.mjs';
2
+ import React3, { useState, useEffect, useMemo, useRef } from 'react';
3
+ import { createPortal } from 'react-dom';
4
+
5
+ var RenderBadge = ({ count }) => {
6
+ return /* @__PURE__ */ React3.createElement(
7
+ "div",
8
+ {
9
+ style: {
10
+ position: "absolute",
11
+ top: -10,
12
+ right: -10,
13
+ backgroundColor: "rgba(10, 10, 10, 0.75)",
14
+ backdropFilter: "blur(12px)",
15
+ WebkitBackdropFilter: "blur(12px)",
16
+ border: "1px solid rgba(255, 255, 255, 0.12)",
17
+ borderRadius: "10px",
18
+ padding: "2px 8px",
19
+ color: "#f1f5f9",
20
+ fontSize: "11px",
21
+ fontWeight: 600,
22
+ fontFamily: "system-ui, -apple-system, sans-serif",
23
+ boxShadow: "0 2px 8px rgba(0, 0, 0, 0.3)",
24
+ zIndex: 1000001,
25
+ pointerEvents: "none",
26
+ display: "flex",
27
+ alignItems: "center",
28
+ justifyContent: "center",
29
+ minWidth: "16px"
30
+ }
31
+ },
32
+ /* @__PURE__ */ React3.createElement("span", { style: { textShadow: "0 0 8px rgba(255,255,255,0.3)" } }, count)
33
+ );
34
+ };
35
+ var HighlightBox = ({
36
+ rect,
37
+ count,
38
+ changedProps,
39
+ name,
40
+ cause,
41
+ isFrequent,
42
+ showHighlight = true,
43
+ showBadge = true
44
+ }) => {
45
+ const [visible, setVisible] = useState(true);
46
+ useEffect(() => {
47
+ setVisible(true);
48
+ const timer = setTimeout(() => {
49
+ setVisible(false);
50
+ }, 1200);
51
+ return () => clearTimeout(timer);
52
+ }, [count]);
53
+ if (!visible) return null;
54
+ if (!showHighlight && !showBadge) return null;
55
+ const borderColor = isFrequent ? "rgba(248, 113, 113, 0.4)" : "rgba(45, 212, 191, 0.4)";
56
+ const glowColor = isFrequent ? "rgba(248, 113, 113, 0.15)" : "rgba(45, 212, 191, 0.15)";
57
+ return /* @__PURE__ */ React3.createElement(
58
+ "div",
59
+ {
60
+ style: {
61
+ position: "absolute",
62
+ top: rect.top + window.scrollY,
63
+ left: rect.left + window.scrollX,
64
+ width: rect.width,
65
+ height: rect.height,
66
+ pointerEvents: "none",
67
+ zIndex: 1e6,
68
+ border: showHighlight ? `1px solid ${borderColor}` : "none",
69
+ borderRadius: "4px",
70
+ boxShadow: showHighlight ? `0 0 12px ${glowColor}, inset 0 0 8px ${glowColor}` : "none",
71
+ background: showHighlight ? "rgba(255, 255, 255, 0.02)" : "transparent",
72
+ transition: "opacity 0.2s ease-out",
73
+ animation: showHighlight ? "react-dev-insight-pulse 0.4s cubic-bezier(0.16, 1, 0.3, 1)" : "none"
74
+ }
75
+ },
76
+ showBadge && /* @__PURE__ */ React3.createElement(RenderBadge, { count }),
77
+ showHighlight && /* @__PURE__ */ React3.createElement(
78
+ "div",
79
+ {
80
+ style: {
81
+ position: "absolute",
82
+ top: "100%",
83
+ marginTop: "6px",
84
+ left: 0,
85
+ background: "rgba(10, 10, 10, 0.85)",
86
+ backdropFilter: "blur(12px)",
87
+ WebkitBackdropFilter: "blur(12px)",
88
+ color: "#e2e8f0",
89
+ fontSize: "11px",
90
+ padding: "8px 10px",
91
+ borderRadius: "6px",
92
+ whiteSpace: "nowrap",
93
+ fontFamily: "system-ui, -apple-system, sans-serif",
94
+ border: "1px solid rgba(255,255,255,0.08)",
95
+ pointerEvents: "none",
96
+ zIndex: 1000002,
97
+ boxShadow: "0 10px 25px -5px rgba(0, 0, 0, 0.5), 0 8px 10px -6px rgba(0, 0, 0, 0.3)"
98
+ }
99
+ },
100
+ /* @__PURE__ */ React3.createElement(
101
+ "div",
102
+ {
103
+ style: {
104
+ fontWeight: 600,
105
+ color: "#f8fafc",
106
+ marginBottom: "3px",
107
+ letterSpacing: "0.02em"
108
+ }
109
+ },
110
+ name
111
+ ),
112
+ /* @__PURE__ */ React3.createElement("div", { style: { display: "flex", gap: "6px", alignItems: "center" } }, /* @__PURE__ */ React3.createElement("span", { style: { color: "#64748b" } }, "Cause:"), /* @__PURE__ */ React3.createElement("span", { style: { color: "#e2e8f0" } }, cause)),
113
+ changedProps.length > 0 && /* @__PURE__ */ React3.createElement("div", { style: { marginTop: "3px", display: "flex", gap: "6px" } }, /* @__PURE__ */ React3.createElement("span", { style: { color: "#64748b" } }, "Props:"), /* @__PURE__ */ React3.createElement("span", { style: { color: "#cbd5e1" } }, changedProps.join(", "))),
114
+ isFrequent && /* @__PURE__ */ React3.createElement(
115
+ "div",
116
+ {
117
+ style: {
118
+ marginTop: "6px",
119
+ color: "#f87171",
120
+ fontWeight: 500,
121
+ display: "flex",
122
+ alignItems: "center",
123
+ gap: "4px",
124
+ fontSize: "10px",
125
+ textTransform: "uppercase",
126
+ letterSpacing: "0.05em"
127
+ }
128
+ },
129
+ /* @__PURE__ */ React3.createElement(
130
+ "div",
131
+ {
132
+ style: {
133
+ width: "6px",
134
+ height: "6px",
135
+ borderRadius: "50%",
136
+ background: "#f87171",
137
+ boxShadow: "0 0 4px #f87171"
138
+ }
139
+ }
140
+ ),
141
+ "Frequent"
142
+ )
143
+ )
144
+ );
145
+ };
146
+ function useDraggable(initialPos = { x: 20, y: 20 }) {
147
+ const [position, setPosition] = useState(initialPos);
148
+ const [isDragging, setIsDragging] = useState(false);
149
+ const dragRef = useRef(null);
150
+ const offsetRef = useRef({ x: 0, y: 0 });
151
+ useEffect(() => {
152
+ const handleMouseMove = (e) => {
153
+ if (!isDragging) return;
154
+ setPosition({
155
+ x: e.clientX - offsetRef.current.x,
156
+ y: e.clientY - offsetRef.current.y
157
+ });
158
+ };
159
+ const handleMouseUp = () => {
160
+ setIsDragging(false);
161
+ };
162
+ if (isDragging) {
163
+ document.addEventListener("mousemove", handleMouseMove);
164
+ document.addEventListener("mouseup", handleMouseUp);
165
+ }
166
+ return () => {
167
+ document.removeEventListener("mousemove", handleMouseMove);
168
+ document.removeEventListener("mouseup", handleMouseUp);
169
+ };
170
+ }, [isDragging]);
171
+ const onMouseDown = (e) => {
172
+ if (dragRef.current) {
173
+ const rect = dragRef.current.getBoundingClientRect();
174
+ offsetRef.current = {
175
+ x: e.clientX - rect.left,
176
+ y: e.clientY - rect.top
177
+ };
178
+ setIsDragging(true);
179
+ e.preventDefault();
180
+ }
181
+ };
182
+ return { position, isDragging, dragRef, onMouseDown };
183
+ }
184
+
185
+ // src/overlay/Dashboard.tsx
186
+ var Dashboard = ({
187
+ isVisible,
188
+ onClose,
189
+ totalRenders,
190
+ highlightBoxesEnabled,
191
+ setHighlightBoxesEnabled,
192
+ badgesEnabled,
193
+ setBadgesEnabled,
194
+ tracesEnabled,
195
+ setTracesEnabled,
196
+ componentStats
197
+ }) => {
198
+ const { position, dragRef, onMouseDown } = useDraggable({
199
+ x: typeof window !== "undefined" ? window.innerWidth - 300 : 20,
200
+ y: typeof window !== "undefined" ? window.innerHeight - 380 : 20
201
+ });
202
+ if (!isVisible) return null;
203
+ return /* @__PURE__ */ React3.createElement(
204
+ "div",
205
+ {
206
+ style: {
207
+ position: "fixed",
208
+ left: position.x,
209
+ top: position.y,
210
+ width: "260px",
211
+ maxHeight: "380px",
212
+ display: "flex",
213
+ flexDirection: "column",
214
+ borderRadius: "12px",
215
+ background: "rgba(10, 10, 10, 0.75)",
216
+ backdropFilter: "blur(24px)",
217
+ WebkitBackdropFilter: "blur(24px)",
218
+ border: "1px solid rgba(255, 255, 255, 0.08)",
219
+ boxShadow: "0 10px 40px -10px rgba(0, 0, 0, 0.6), inset 0 1px 0 rgba(255, 255, 255, 0.05)",
220
+ zIndex: 1000004,
221
+ color: "#e2e8f0",
222
+ fontFamily: "system-ui, -apple-system, sans-serif",
223
+ overflow: "hidden",
224
+ animation: "react-dev-insight-slide-up 0.3s cubic-bezier(0.16, 1, 0.3, 1)"
225
+ }
226
+ },
227
+ /* @__PURE__ */ React3.createElement(
228
+ "div",
229
+ {
230
+ ref: dragRef,
231
+ onMouseDown,
232
+ style: {
233
+ padding: "12px 16px",
234
+ borderBottom: "1px solid rgba(255, 255, 255, 0.06)",
235
+ display: "flex",
236
+ justifyContent: "space-between",
237
+ alignItems: "center",
238
+ cursor: "grab",
239
+ background: "rgba(255,255,255,0.02)"
240
+ }
241
+ },
242
+ /* @__PURE__ */ React3.createElement("div", { style: { display: "flex", alignItems: "center", gap: "8px" } }, /* @__PURE__ */ React3.createElement(
243
+ "div",
244
+ {
245
+ style: {
246
+ width: "6px",
247
+ height: "6px",
248
+ borderRadius: "50%",
249
+ background: "#f8fafc",
250
+ boxShadow: "0 0 8px rgba(255,255,255,0.8)"
251
+ }
252
+ }
253
+ ), /* @__PURE__ */ React3.createElement(
254
+ "span",
255
+ {
256
+ style: {
257
+ fontWeight: 500,
258
+ fontSize: "12px",
259
+ letterSpacing: "0.04em",
260
+ color: "#f8fafc"
261
+ }
262
+ },
263
+ "Dev Overlay"
264
+ )),
265
+ /* @__PURE__ */ React3.createElement(
266
+ "button",
267
+ {
268
+ onClick: onClose,
269
+ style: {
270
+ background: "none",
271
+ border: "none",
272
+ color: "#64748b",
273
+ cursor: "pointer",
274
+ padding: "2px",
275
+ display: "flex",
276
+ alignItems: "center",
277
+ justifyContent: "center",
278
+ borderRadius: "4px",
279
+ transition: "color 0.2s"
280
+ },
281
+ onMouseOver: (e) => e.currentTarget.style.color = "#e2e8f0",
282
+ onMouseOut: (e) => e.currentTarget.style.color = "#64748b"
283
+ },
284
+ /* @__PURE__ */ React3.createElement(
285
+ "svg",
286
+ {
287
+ width: "14",
288
+ height: "14",
289
+ viewBox: "0 0 24 24",
290
+ fill: "none",
291
+ stroke: "currentColor",
292
+ strokeWidth: "2",
293
+ strokeLinecap: "round",
294
+ strokeLinejoin: "round"
295
+ },
296
+ /* @__PURE__ */ React3.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
297
+ /* @__PURE__ */ React3.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
298
+ )
299
+ )
300
+ ),
301
+ /* @__PURE__ */ React3.createElement("div", { style: { padding: "16px", overflowY: "auto" } }, /* @__PURE__ */ React3.createElement("div", { style: { marginBottom: "24px" } }, /* @__PURE__ */ React3.createElement(
302
+ "div",
303
+ {
304
+ style: {
305
+ fontSize: "10px",
306
+ color: "#64748b",
307
+ textTransform: "uppercase",
308
+ marginBottom: "8px",
309
+ letterSpacing: "0.06em"
310
+ }
311
+ },
312
+ "Performance"
313
+ ), /* @__PURE__ */ React3.createElement(
314
+ "div",
315
+ {
316
+ style: {
317
+ display: "flex",
318
+ justifyContent: "space-between",
319
+ alignItems: "center"
320
+ }
321
+ },
322
+ /* @__PURE__ */ React3.createElement("span", { style: { fontSize: "13px", color: "#cbd5e1" } }, "Total Renders"),
323
+ /* @__PURE__ */ React3.createElement(
324
+ "span",
325
+ {
326
+ style: { fontSize: "15px", fontWeight: 600, color: "#f8fafc" }
327
+ },
328
+ totalRenders
329
+ )
330
+ )), /* @__PURE__ */ React3.createElement("div", { style: { marginBottom: "24px" } }, /* @__PURE__ */ React3.createElement(
331
+ "div",
332
+ {
333
+ style: {
334
+ fontSize: "10px",
335
+ color: "#64748b",
336
+ textTransform: "uppercase",
337
+ marginBottom: "8px",
338
+ letterSpacing: "0.06em"
339
+ }
340
+ },
341
+ "Settings"
342
+ ), /* @__PURE__ */ React3.createElement(
343
+ "div",
344
+ {
345
+ style: { display: "flex", flexDirection: "column", gap: "10px" }
346
+ },
347
+ /* @__PURE__ */ React3.createElement(
348
+ "label",
349
+ {
350
+ style: {
351
+ display: "flex",
352
+ alignItems: "center",
353
+ justifyContent: "space-between",
354
+ fontSize: "12px",
355
+ cursor: "pointer",
356
+ color: "#cbd5e1"
357
+ }
358
+ },
359
+ /* @__PURE__ */ React3.createElement("span", null, "Highlight Boxes"),
360
+ /* @__PURE__ */ React3.createElement(
361
+ "input",
362
+ {
363
+ type: "checkbox",
364
+ checked: highlightBoxesEnabled,
365
+ onChange: (e) => setHighlightBoxesEnabled(e.target.checked),
366
+ style: {
367
+ accentColor: "#475569",
368
+ width: "14px",
369
+ height: "14px",
370
+ cursor: "pointer"
371
+ }
372
+ }
373
+ )
374
+ ),
375
+ /* @__PURE__ */ React3.createElement(
376
+ "label",
377
+ {
378
+ style: {
379
+ display: "flex",
380
+ alignItems: "center",
381
+ justifyContent: "space-between",
382
+ fontSize: "12px",
383
+ cursor: "pointer",
384
+ color: "#cbd5e1"
385
+ }
386
+ },
387
+ /* @__PURE__ */ React3.createElement("span", null, "Render Badges"),
388
+ /* @__PURE__ */ React3.createElement(
389
+ "input",
390
+ {
391
+ type: "checkbox",
392
+ checked: badgesEnabled,
393
+ onChange: (e) => setBadgesEnabled(e.target.checked),
394
+ style: {
395
+ accentColor: "#475569",
396
+ width: "14px",
397
+ height: "14px",
398
+ cursor: "pointer"
399
+ }
400
+ }
401
+ )
402
+ ),
403
+ /* @__PURE__ */ React3.createElement(
404
+ "label",
405
+ {
406
+ style: {
407
+ display: "flex",
408
+ alignItems: "center",
409
+ justifyContent: "space-between",
410
+ fontSize: "12px",
411
+ cursor: "pointer",
412
+ color: "#cbd5e1"
413
+ }
414
+ },
415
+ /* @__PURE__ */ React3.createElement(
416
+ "div",
417
+ {
418
+ style: { display: "flex", alignItems: "center", gap: "6px" }
419
+ },
420
+ /* @__PURE__ */ React3.createElement("span", null, "Render Traces"),
421
+ /* @__PURE__ */ React3.createElement(
422
+ "span",
423
+ {
424
+ style: {
425
+ fontSize: "9px",
426
+ padding: "2px 4px",
427
+ background: "rgba(45, 212, 191, 0.2)",
428
+ color: "#2dd4bf",
429
+ borderRadius: "4px"
430
+ }
431
+ },
432
+ "NEW"
433
+ )
434
+ ),
435
+ /* @__PURE__ */ React3.createElement(
436
+ "input",
437
+ {
438
+ type: "checkbox",
439
+ checked: tracesEnabled,
440
+ onChange: (e) => setTracesEnabled(e.target.checked),
441
+ style: {
442
+ accentColor: "#475569",
443
+ width: "14px",
444
+ height: "14px",
445
+ cursor: "pointer"
446
+ }
447
+ }
448
+ )
449
+ )
450
+ )), /* @__PURE__ */ React3.createElement("div", null, /* @__PURE__ */ React3.createElement(
451
+ "div",
452
+ {
453
+ style: {
454
+ fontSize: "10px",
455
+ color: "#64748b",
456
+ textTransform: "uppercase",
457
+ marginBottom: "8px",
458
+ letterSpacing: "0.06em"
459
+ }
460
+ },
461
+ "Most Re-rendered"
462
+ ), componentStats.length === 0 ? /* @__PURE__ */ React3.createElement(
463
+ "div",
464
+ {
465
+ style: {
466
+ fontSize: "12px",
467
+ color: "#475569",
468
+ fontStyle: "italic"
469
+ }
470
+ },
471
+ "No tracking data."
472
+ ) : /* @__PURE__ */ React3.createElement(
473
+ "div",
474
+ {
475
+ style: { display: "flex", flexDirection: "column", gap: "6px" }
476
+ },
477
+ componentStats.map((stat, idx) => /* @__PURE__ */ React3.createElement(
478
+ "div",
479
+ {
480
+ key: idx,
481
+ style: {
482
+ display: "flex",
483
+ justifyContent: "space-between",
484
+ fontSize: "12px",
485
+ alignItems: "center"
486
+ }
487
+ },
488
+ /* @__PURE__ */ React3.createElement(
489
+ "span",
490
+ {
491
+ style: {
492
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
493
+ color: "#94a3b8"
494
+ }
495
+ },
496
+ stat.name
497
+ ),
498
+ /* @__PURE__ */ React3.createElement(
499
+ "span",
500
+ {
501
+ style: {
502
+ color: "#e2e8f0",
503
+ fontWeight: 500,
504
+ background: "rgba(255,255,255,0.05)",
505
+ padding: "2px 6px",
506
+ borderRadius: "4px"
507
+ }
508
+ },
509
+ stat.count
510
+ )
511
+ ))
512
+ )))
513
+ );
514
+ };
515
+ var FloatingToggle = ({
516
+ onClick,
517
+ isOpen
518
+ }) => {
519
+ const { position, dragRef, onMouseDown, isDragging } = useDraggable({
520
+ x: typeof window !== "undefined" ? window.innerWidth - 80 : 20,
521
+ y: typeof window !== "undefined" ? window.innerHeight - 80 : 20
522
+ });
523
+ return /* @__PURE__ */ React3.createElement(
524
+ "div",
525
+ {
526
+ ref: dragRef,
527
+ onMouseDown,
528
+ onClick: () => {
529
+ if (!isDragging) onClick();
530
+ },
531
+ style: {
532
+ position: "fixed",
533
+ left: position.x,
534
+ top: position.y,
535
+ width: "44px",
536
+ height: "44px",
537
+ borderRadius: "50%",
538
+ background: "rgba(10, 10, 10, 0.65)",
539
+ backdropFilter: "blur(16px)",
540
+ WebkitBackdropFilter: "blur(16px)",
541
+ border: "1px solid rgba(255, 255, 255, 0.08)",
542
+ boxShadow: isOpen ? "0 0 16px rgba(255, 255, 255, 0.1), inset 0 0 8px rgba(255, 255, 255, 0.05)" : "0 4px 12px rgba(0, 0, 0, 0.4)",
543
+ display: "flex",
544
+ alignItems: "center",
545
+ justifyContent: "center",
546
+ cursor: isDragging ? "grabbing" : "grab",
547
+ zIndex: 1000005,
548
+ transition: isDragging ? "none" : "box-shadow 0.3s ease, transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275)",
549
+ transform: isDragging ? "scale(1.05)" : "scale(1)",
550
+ color: "#e2e8f0"
551
+ }
552
+ },
553
+ /* @__PURE__ */ React3.createElement(
554
+ "svg",
555
+ {
556
+ width: "20",
557
+ height: "20",
558
+ viewBox: "0 0 24 24",
559
+ fill: "none",
560
+ stroke: "currentColor",
561
+ strokeWidth: "2",
562
+ strokeLinecap: "round",
563
+ strokeLinejoin: "round",
564
+ style: {
565
+ transition: "transform 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55)",
566
+ transform: isOpen ? "rotate(90deg)" : "rotate(0deg)"
567
+ }
568
+ },
569
+ /* @__PURE__ */ React3.createElement("path", { d: "M12 3a9 9 0 0 0-9 9 9 9 0 0 0 9 9 9 9 0 0 0 9-9 9 9 0 0 0-9-9" }),
570
+ /* @__PURE__ */ React3.createElement("path", { d: "M12 8v8" }),
571
+ /* @__PURE__ */ React3.createElement("path", { d: "M8 12h8" })
572
+ )
573
+ );
574
+ };
575
+
576
+ // src/overlay/OverlayRoot.tsx
577
+ var OverlayRoot = () => {
578
+ const [renders, setRenders] = useState(/* @__PURE__ */ new Map());
579
+ const [totalRenders, setTotalRenders] = useState(0);
580
+ const [componentStats, setComponentStats] = useState(
581
+ {}
582
+ );
583
+ const [isDashboardVisible, setIsDashboardVisible] = useState(false);
584
+ const [highlightBoxesEnabled, setHighlightBoxesEnabled] = useState(true);
585
+ const [badgesEnabled, setBadgesEnabled] = useState(true);
586
+ const [tracesEnabled, setTracesEnabled] = useState(true);
587
+ useEffect(() => {
588
+ if (typeof document !== "undefined") {
589
+ let style = document.getElementById("react-dev-insight-styles");
590
+ if (!style) {
591
+ style = document.createElement("style");
592
+ style.id = "react-dev-insight-styles";
593
+ style.innerHTML = `
594
+ @keyframes react-dev-insight-pulse {
595
+ 0% { transform: scale(0.98); opacity: 0; }
596
+ 30% { transform: scale(1.01); opacity: 1; }
597
+ 100% { transform: scale(1); opacity: 1; }
598
+ }
599
+ @keyframes react-dev-insight-slide-up {
600
+ from { transform: translateY(10px) scale(0.98); opacity: 0; }
601
+ to { transform: translateY(0) scale(1); opacity: 1; }
602
+ }
603
+ `;
604
+ document.head.appendChild(style);
605
+ }
606
+ }
607
+ const listener = (ref, data) => {
608
+ setTotalRenders((prev) => prev + 1);
609
+ setComponentStats((prev) => ({
610
+ ...prev,
611
+ [data.name]: Math.max(data.count, prev[data.name] || 0)
612
+ }));
613
+ if (!data.elementRef) return;
614
+ const rect = data.elementRef.getBoundingClientRect();
615
+ if (rect.width === 0 && rect.height === 0) return;
616
+ setRenders((prev) => {
617
+ const next = new Map(prev);
618
+ next.set(ref, {
619
+ rect,
620
+ count: data.count,
621
+ changedProps: Object.keys(data.changedProps),
622
+ name: data.name,
623
+ timestamp: data.timestamp,
624
+ cause: data.cause,
625
+ isFrequent: data.isFrequent,
626
+ sourceRef: data.sourceRef
627
+ });
628
+ return next;
629
+ });
630
+ };
631
+ const unsubscribe = subscribeToReRenders(listener);
632
+ return () => unsubscribe();
633
+ }, []);
634
+ useEffect(() => {
635
+ const interval = setInterval(() => {
636
+ const now = performance.now();
637
+ setRenders((prev) => {
638
+ let changed = false;
639
+ const next = new Map(prev);
640
+ for (const [key, value] of next.entries()) {
641
+ if (now - value.timestamp > 1200) {
642
+ next.delete(key);
643
+ changed = true;
644
+ }
645
+ }
646
+ return changed ? next : prev;
647
+ });
648
+ }, 1e3);
649
+ return () => clearInterval(interval);
650
+ }, []);
651
+ const statsList = useMemo(() => {
652
+ return Object.entries(componentStats).map(([name, count]) => ({ name, count })).sort((a, b) => b.count - a.count).slice(0, 10);
653
+ }, [componentStats]);
654
+ if (typeof document === "undefined") return null;
655
+ const boxes = Array.from(renders.values()).map((r, i) => /* @__PURE__ */ React3.createElement(
656
+ HighlightBox,
657
+ {
658
+ key: `${r.name}-${i}`,
659
+ rect: r.rect,
660
+ count: r.count,
661
+ changedProps: r.changedProps,
662
+ name: r.name,
663
+ cause: r.cause,
664
+ isFrequent: r.isFrequent,
665
+ showHighlight: highlightBoxesEnabled,
666
+ showBadge: badgesEnabled
667
+ }
668
+ ));
669
+ const svgTraces = [];
670
+ if (tracesEnabled) {
671
+ const rendersArr = Array.from(renders.entries());
672
+ rendersArr.forEach(([key, r], i) => {
673
+ if (r.sourceRef && renders.has(r.sourceRef)) {
674
+ const sourceRect = renders.get(r.sourceRef).rect;
675
+ const targetRect = r.rect;
676
+ const startX = sourceRect.left + sourceRect.width / 2;
677
+ const startY = sourceRect.top + sourceRect.height / 2;
678
+ const endX = targetRect.left + targetRect.width / 2;
679
+ const endY = targetRect.top + targetRect.height / 2;
680
+ const cx1 = startX;
681
+ const cy1 = startY + (endY - startY) * 0.5;
682
+ const cx2 = endX;
683
+ const cy2 = startY + (endY - startY) * 0.5;
684
+ const age = performance.now() - r.timestamp;
685
+ const opacity = Math.max(0, 1 - age / 1200);
686
+ const pathId = `trace-path-${i}`;
687
+ svgTraces.push(
688
+ /* @__PURE__ */ React3.createElement("g", { key: pathId, style: { opacity } }, /* @__PURE__ */ React3.createElement(
689
+ "path",
690
+ {
691
+ d: `M ${startX} ${startY} C ${cx1} ${cy1}, ${cx2} ${cy2}, ${endX} ${endY}`,
692
+ fill: "none",
693
+ stroke: "rgba(45, 212, 191, 0.4)",
694
+ strokeWidth: "2",
695
+ strokeDasharray: "4 4"
696
+ }
697
+ ), /* @__PURE__ */ React3.createElement("circle", { r: "3", fill: "#2dd4bf" }, /* @__PURE__ */ React3.createElement(
698
+ "animateMotion",
699
+ {
700
+ dur: "0.8s",
701
+ repeatCount: "1",
702
+ path: `M ${startX} ${startY} C ${cx1} ${cy1}, ${cx2} ${cy2}, ${endX} ${endY}`,
703
+ fill: "freeze"
704
+ }
705
+ )))
706
+ );
707
+ }
708
+ });
709
+ }
710
+ return createPortal(
711
+ /* @__PURE__ */ React3.createElement(React3.Fragment, null, tracesEnabled && svgTraces.length > 0 && /* @__PURE__ */ React3.createElement(
712
+ "svg",
713
+ {
714
+ style: {
715
+ position: "fixed",
716
+ top: 0,
717
+ left: 0,
718
+ width: "100vw",
719
+ height: "100vh",
720
+ pointerEvents: "none",
721
+ zIndex: 999998
722
+ }
723
+ },
724
+ svgTraces
725
+ ), /* @__PURE__ */ React3.createElement(
726
+ "div",
727
+ {
728
+ style: {
729
+ position: "fixed",
730
+ top: 0,
731
+ left: 0,
732
+ width: "100%",
733
+ pointerEvents: "none",
734
+ zIndex: 999999
735
+ }
736
+ },
737
+ boxes
738
+ ), /* @__PURE__ */ React3.createElement("div", { style: { zIndex: 1000003, position: "fixed", top: 0, left: 0 } }, /* @__PURE__ */ React3.createElement(
739
+ FloatingToggle,
740
+ {
741
+ isOpen: isDashboardVisible,
742
+ onClick: () => setIsDashboardVisible((prev) => !prev)
743
+ }
744
+ ), /* @__PURE__ */ React3.createElement(
745
+ Dashboard,
746
+ {
747
+ isVisible: isDashboardVisible,
748
+ onClose: () => setIsDashboardVisible(false),
749
+ totalRenders,
750
+ componentStats: statsList,
751
+ highlightBoxesEnabled,
752
+ setHighlightBoxesEnabled,
753
+ badgesEnabled,
754
+ setBadgesEnabled,
755
+ tracesEnabled,
756
+ setTracesEnabled
757
+ }
758
+ ))),
759
+ document.body
760
+ );
761
+ };
762
+
763
+ export { HighlightBox, OverlayRoot, RenderBadge };
764
+ //# sourceMappingURL=chunk-IDEYIAB5.mjs.map
765
+ //# sourceMappingURL=chunk-IDEYIAB5.mjs.map