react-render-guard 0.1.1 → 0.1.2
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 +3 -2
- package/dist/components/RenderGuard.test.d.ts +1 -0
- package/dist/components/RenderOverlay.d.ts +8 -0
- package/dist/core/index.test.d.ts +1 -0
- package/dist/render-guard.es.js +269 -136
- package/dist/render-guard.umd.js +2 -2
- package/dist/test/setup.d.ts +0 -0
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# 🛡️
|
|
1
|
+
# 🛡️ React Render Guard
|
|
2
2
|
|
|
3
3
|
> **Stop guessing. Start optimizing.**
|
|
4
4
|
> A lightweight, non-intrusive React library to detect, visualize, and eliminate unnecessary re-renders in your application.
|
|
@@ -26,7 +26,8 @@ Finding these bottlenecks manually with general profiling tools is tedious and d
|
|
|
26
26
|
- **🔍 Precision Monitoring**: Uses React's internal Profiler API 100% safely.
|
|
27
27
|
- **⚡ Zero Production Overhead**: Designed to be stripped out or disabled in production.
|
|
28
28
|
- **🛠️ Developer Experience**: Simple `Provider` API.
|
|
29
|
-
- **📊 Real-time Insights**: Console alerts for expensive renders
|
|
29
|
+
- **📊 Real-time Insights**: Console alerts for expensive renders.
|
|
30
|
+
- **👁️ Visual Overlay**: A non-intrusive floating panel showing render duration, total render counts, and color-coded health status (Green/Orange/Red) in real-time.
|
|
30
31
|
|
|
31
32
|
## 📦 Installation
|
|
32
33
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/render-guard.es.js
CHANGED
|
@@ -1,69 +1,70 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
var
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
1
|
+
import C, { useState as D, useEffect as z, Profiler as oe, useCallback as ae, useRef as se } from "react";
|
|
2
|
+
import { createPortal as le } from "react-dom";
|
|
3
|
+
var g = { exports: {} }, x = {};
|
|
4
|
+
var M;
|
|
5
|
+
function ie() {
|
|
6
|
+
if (M) return x;
|
|
7
|
+
M = 1;
|
|
8
|
+
var n = /* @__PURE__ */ Symbol.for("react.transitional.element"), s = /* @__PURE__ */ Symbol.for("react.fragment");
|
|
9
|
+
function p(d, i, c) {
|
|
10
|
+
var u = null;
|
|
11
|
+
if (c !== void 0 && (u = "" + c), i.key !== void 0 && (u = "" + i.key), "key" in i) {
|
|
12
|
+
c = {};
|
|
13
|
+
for (var m in i)
|
|
14
|
+
m !== "key" && (c[m] = i[m]);
|
|
15
|
+
} else c = i;
|
|
16
|
+
return i = c.ref, {
|
|
17
|
+
$$typeof: n,
|
|
18
|
+
type: d,
|
|
19
|
+
key: u,
|
|
20
|
+
ref: i !== void 0 ? i : null,
|
|
21
|
+
props: c
|
|
21
22
|
};
|
|
22
23
|
}
|
|
23
|
-
return
|
|
24
|
+
return x.Fragment = s, x.jsx = p, x.jsxs = p, x;
|
|
24
25
|
}
|
|
25
|
-
var
|
|
26
|
-
var
|
|
27
|
-
function
|
|
28
|
-
return
|
|
29
|
-
function
|
|
26
|
+
var E = {};
|
|
27
|
+
var G;
|
|
28
|
+
function ce() {
|
|
29
|
+
return G || (G = 1, process.env.NODE_ENV !== "production" && (function() {
|
|
30
|
+
function n(e) {
|
|
30
31
|
if (e == null) return null;
|
|
31
32
|
if (typeof e == "function")
|
|
32
|
-
return e.$$typeof ===
|
|
33
|
+
return e.$$typeof === re ? null : e.displayName || e.name || null;
|
|
33
34
|
if (typeof e == "string") return e;
|
|
34
35
|
switch (e) {
|
|
35
36
|
case k:
|
|
36
37
|
return "Fragment";
|
|
37
|
-
case
|
|
38
|
+
case q:
|
|
38
39
|
return "Profiler";
|
|
39
|
-
case
|
|
40
|
+
case J:
|
|
40
41
|
return "StrictMode";
|
|
41
|
-
case
|
|
42
|
+
case Z:
|
|
42
43
|
return "Suspense";
|
|
43
|
-
case
|
|
44
|
+
case Q:
|
|
44
45
|
return "SuspenseList";
|
|
45
|
-
case
|
|
46
|
+
case ee:
|
|
46
47
|
return "Activity";
|
|
47
48
|
}
|
|
48
49
|
if (typeof e == "object")
|
|
49
50
|
switch (typeof e.tag == "number" && console.error(
|
|
50
51
|
"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
|
|
51
52
|
), e.$$typeof) {
|
|
52
|
-
case
|
|
53
|
+
case V:
|
|
53
54
|
return "Portal";
|
|
54
|
-
case
|
|
55
|
+
case X:
|
|
55
56
|
return e.displayName || "Context";
|
|
56
|
-
case
|
|
57
|
+
case B:
|
|
57
58
|
return (e._context.displayName || "Context") + ".Consumer";
|
|
58
|
-
case
|
|
59
|
+
case H:
|
|
59
60
|
var r = e.render;
|
|
60
61
|
return e = e.displayName, e || (e = r.displayName || r.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e;
|
|
61
|
-
case
|
|
62
|
-
return r = e.displayName || null, r !== null ? r :
|
|
63
|
-
case
|
|
62
|
+
case K:
|
|
63
|
+
return r = e.displayName || null, r !== null ? r : n(e.type) || "Memo";
|
|
64
|
+
case S:
|
|
64
65
|
r = e._payload, e = e._init;
|
|
65
66
|
try {
|
|
66
|
-
return
|
|
67
|
+
return n(e(r));
|
|
67
68
|
} catch {
|
|
68
69
|
}
|
|
69
70
|
}
|
|
@@ -72,7 +73,7 @@ function ae() {
|
|
|
72
73
|
function s(e) {
|
|
73
74
|
return "" + e;
|
|
74
75
|
}
|
|
75
|
-
function
|
|
76
|
+
function p(e) {
|
|
76
77
|
try {
|
|
77
78
|
s(e);
|
|
78
79
|
var r = !1;
|
|
@@ -81,42 +82,42 @@ function ae() {
|
|
|
81
82
|
}
|
|
82
83
|
if (r) {
|
|
83
84
|
r = console;
|
|
84
|
-
var t = r.error,
|
|
85
|
+
var t = r.error, o = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
|
|
85
86
|
return t.call(
|
|
86
87
|
r,
|
|
87
88
|
"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
|
|
88
|
-
|
|
89
|
+
o
|
|
89
90
|
), s(e);
|
|
90
91
|
}
|
|
91
92
|
}
|
|
92
|
-
function
|
|
93
|
+
function d(e) {
|
|
93
94
|
if (e === k) return "<>";
|
|
94
|
-
if (typeof e == "object" && e !== null && e.$$typeof ===
|
|
95
|
+
if (typeof e == "object" && e !== null && e.$$typeof === S)
|
|
95
96
|
return "<...>";
|
|
96
97
|
try {
|
|
97
|
-
var r =
|
|
98
|
+
var r = n(e);
|
|
98
99
|
return r ? "<" + r + ">" : "<...>";
|
|
99
100
|
} catch {
|
|
100
101
|
return "<...>";
|
|
101
102
|
}
|
|
102
103
|
}
|
|
103
|
-
function
|
|
104
|
-
var e =
|
|
104
|
+
function i() {
|
|
105
|
+
var e = w.A;
|
|
105
106
|
return e === null ? null : e.getOwner();
|
|
106
107
|
}
|
|
107
|
-
function
|
|
108
|
+
function c() {
|
|
108
109
|
return Error("react-stack-top-frame");
|
|
109
110
|
}
|
|
110
|
-
function
|
|
111
|
-
if (
|
|
111
|
+
function u(e) {
|
|
112
|
+
if (I.call(e, "key")) {
|
|
112
113
|
var r = Object.getOwnPropertyDescriptor(e, "key").get;
|
|
113
114
|
if (r && r.isReactWarning) return !1;
|
|
114
115
|
}
|
|
115
116
|
return e.key !== void 0;
|
|
116
117
|
}
|
|
117
|
-
function
|
|
118
|
+
function m(e, r) {
|
|
118
119
|
function t() {
|
|
119
|
-
|
|
120
|
+
F || (F = !0, console.error(
|
|
120
121
|
"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
|
|
121
122
|
r
|
|
122
123
|
));
|
|
@@ -126,23 +127,23 @@ function ae() {
|
|
|
126
127
|
configurable: !0
|
|
127
128
|
});
|
|
128
129
|
}
|
|
129
|
-
function
|
|
130
|
-
var e =
|
|
131
|
-
return
|
|
130
|
+
function R() {
|
|
131
|
+
var e = n(this.type);
|
|
132
|
+
return Y[e] || (Y[e] = !0, console.error(
|
|
132
133
|
"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
|
|
133
134
|
)), e = this.props.ref, e !== void 0 ? e : null;
|
|
134
135
|
}
|
|
135
|
-
function
|
|
136
|
-
var
|
|
136
|
+
function j(e, r, t, o, y, A) {
|
|
137
|
+
var a = t.ref;
|
|
137
138
|
return e = {
|
|
138
|
-
$$typeof:
|
|
139
|
+
$$typeof: N,
|
|
139
140
|
type: e,
|
|
140
141
|
key: r,
|
|
141
142
|
props: t,
|
|
142
|
-
_owner:
|
|
143
|
-
}, (
|
|
143
|
+
_owner: o
|
|
144
|
+
}, (a !== void 0 ? a : null) !== null ? Object.defineProperty(e, "ref", {
|
|
144
145
|
enumerable: !1,
|
|
145
|
-
get:
|
|
146
|
+
get: R
|
|
146
147
|
}) : Object.defineProperty(e, "ref", { enumerable: !1, value: null }), e._store = {}, Object.defineProperty(e._store, "validated", {
|
|
147
148
|
configurable: !1,
|
|
148
149
|
enumerable: !1,
|
|
@@ -157,138 +158,270 @@ function ae() {
|
|
|
157
158
|
configurable: !1,
|
|
158
159
|
enumerable: !1,
|
|
159
160
|
writable: !0,
|
|
160
|
-
value:
|
|
161
|
+
value: y
|
|
161
162
|
}), Object.defineProperty(e, "_debugTask", {
|
|
162
163
|
configurable: !1,
|
|
163
164
|
enumerable: !1,
|
|
164
165
|
writable: !0,
|
|
165
|
-
value:
|
|
166
|
+
value: A
|
|
166
167
|
}), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
|
|
167
168
|
}
|
|
168
|
-
function
|
|
169
|
-
var
|
|
170
|
-
if (
|
|
171
|
-
if (
|
|
172
|
-
if (
|
|
173
|
-
for (
|
|
174
|
-
|
|
175
|
-
Object.freeze && Object.freeze(
|
|
169
|
+
function _(e, r, t, o, y, A) {
|
|
170
|
+
var a = r.children;
|
|
171
|
+
if (a !== void 0)
|
|
172
|
+
if (o)
|
|
173
|
+
if (te(a)) {
|
|
174
|
+
for (o = 0; o < a.length; o++)
|
|
175
|
+
v(a[o]);
|
|
176
|
+
Object.freeze && Object.freeze(a);
|
|
176
177
|
} else
|
|
177
178
|
console.error(
|
|
178
179
|
"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
|
|
179
180
|
);
|
|
180
|
-
else
|
|
181
|
-
if (
|
|
182
|
-
|
|
183
|
-
var
|
|
184
|
-
return
|
|
181
|
+
else v(a);
|
|
182
|
+
if (I.call(r, "key")) {
|
|
183
|
+
a = n(e);
|
|
184
|
+
var b = Object.keys(r).filter(function(ne) {
|
|
185
|
+
return ne !== "key";
|
|
185
186
|
});
|
|
186
|
-
|
|
187
|
+
o = 0 < b.length ? "{key: someKey, " + b.join(": ..., ") + ": ...}" : "{key: someKey}", L[a + o] || (b = 0 < b.length ? "{" + b.join(": ..., ") + ": ...}" : "{}", console.error(
|
|
187
188
|
`A props object containing a "key" prop is being spread into JSX:
|
|
188
189
|
let props = %s;
|
|
189
190
|
<%s {...props} />
|
|
190
191
|
React keys must be passed directly to JSX without using spread:
|
|
191
192
|
let props = %s;
|
|
192
193
|
<%s key={someKey} {...props} />`,
|
|
193
|
-
n,
|
|
194
194
|
o,
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
195
|
+
a,
|
|
196
|
+
b,
|
|
197
|
+
a
|
|
198
|
+
), L[a + o] = !0);
|
|
198
199
|
}
|
|
199
|
-
if (
|
|
200
|
+
if (a = null, t !== void 0 && (p(t), a = "" + t), u(r) && (p(r.key), a = "" + r.key), "key" in r) {
|
|
200
201
|
t = {};
|
|
201
|
-
for (var
|
|
202
|
-
|
|
202
|
+
for (var P in r)
|
|
203
|
+
P !== "key" && (t[P] = r[P]);
|
|
203
204
|
} else t = r;
|
|
204
|
-
return
|
|
205
|
+
return a && m(
|
|
205
206
|
t,
|
|
206
207
|
typeof e == "function" ? e.displayName || e.name || "Unknown" : e
|
|
207
|
-
),
|
|
208
|
+
), j(
|
|
208
209
|
e,
|
|
209
|
-
|
|
210
|
+
a,
|
|
210
211
|
t,
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
212
|
+
i(),
|
|
213
|
+
y,
|
|
214
|
+
A
|
|
214
215
|
);
|
|
215
216
|
}
|
|
216
|
-
function
|
|
217
|
-
|
|
217
|
+
function v(e) {
|
|
218
|
+
T(e) ? e._store && (e._store.validated = 1) : typeof e == "object" && e !== null && e.$$typeof === S && (e._payload.status === "fulfilled" ? T(e._payload.value) && e._payload.value._store && (e._payload.value._store.validated = 1) : e._store && (e._store.validated = 1));
|
|
218
219
|
}
|
|
219
|
-
function
|
|
220
|
-
return typeof e == "object" && e !== null && e.$$typeof ===
|
|
220
|
+
function T(e) {
|
|
221
|
+
return typeof e == "object" && e !== null && e.$$typeof === N;
|
|
221
222
|
}
|
|
222
|
-
var
|
|
223
|
+
var h = C, N = /* @__PURE__ */ Symbol.for("react.transitional.element"), V = /* @__PURE__ */ Symbol.for("react.portal"), k = /* @__PURE__ */ Symbol.for("react.fragment"), J = /* @__PURE__ */ Symbol.for("react.strict_mode"), q = /* @__PURE__ */ Symbol.for("react.profiler"), B = /* @__PURE__ */ Symbol.for("react.consumer"), X = /* @__PURE__ */ Symbol.for("react.context"), H = /* @__PURE__ */ Symbol.for("react.forward_ref"), Z = /* @__PURE__ */ Symbol.for("react.suspense"), Q = /* @__PURE__ */ Symbol.for("react.suspense_list"), K = /* @__PURE__ */ Symbol.for("react.memo"), S = /* @__PURE__ */ Symbol.for("react.lazy"), ee = /* @__PURE__ */ Symbol.for("react.activity"), re = /* @__PURE__ */ Symbol.for("react.client.reference"), w = h.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, I = Object.prototype.hasOwnProperty, te = Array.isArray, O = console.createTask ? console.createTask : function() {
|
|
223
224
|
return null;
|
|
224
225
|
};
|
|
225
|
-
|
|
226
|
+
h = {
|
|
226
227
|
react_stack_bottom_frame: function(e) {
|
|
227
228
|
return e();
|
|
228
229
|
}
|
|
229
230
|
};
|
|
230
|
-
var
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
)(),
|
|
234
|
-
|
|
235
|
-
var
|
|
236
|
-
return
|
|
231
|
+
var F, Y = {}, $ = h.react_stack_bottom_frame.bind(
|
|
232
|
+
h,
|
|
233
|
+
c
|
|
234
|
+
)(), W = O(d(c)), L = {};
|
|
235
|
+
E.Fragment = k, E.jsx = function(e, r, t) {
|
|
236
|
+
var o = 1e4 > w.recentlyCreatedOwnerStacks++;
|
|
237
|
+
return _(
|
|
237
238
|
e,
|
|
238
239
|
r,
|
|
239
240
|
t,
|
|
240
241
|
!1,
|
|
241
|
-
|
|
242
|
-
|
|
242
|
+
o ? Error("react-stack-top-frame") : $,
|
|
243
|
+
o ? O(d(e)) : W
|
|
243
244
|
);
|
|
244
|
-
},
|
|
245
|
-
var
|
|
246
|
-
return
|
|
245
|
+
}, E.jsxs = function(e, r, t) {
|
|
246
|
+
var o = 1e4 > w.recentlyCreatedOwnerStacks++;
|
|
247
|
+
return _(
|
|
247
248
|
e,
|
|
248
249
|
r,
|
|
249
250
|
t,
|
|
250
251
|
!0,
|
|
251
|
-
|
|
252
|
-
|
|
252
|
+
o ? Error("react-stack-top-frame") : $,
|
|
253
|
+
o ? O(d(e)) : W
|
|
253
254
|
);
|
|
254
255
|
};
|
|
255
|
-
})()),
|
|
256
|
+
})()), E;
|
|
256
257
|
}
|
|
257
|
-
var
|
|
258
|
-
function
|
|
259
|
-
return
|
|
258
|
+
var U;
|
|
259
|
+
function ue() {
|
|
260
|
+
return U || (U = 1, process.env.NODE_ENV === "production" ? g.exports = ie() : g.exports = ce()), g.exports;
|
|
260
261
|
}
|
|
261
|
-
var
|
|
262
|
-
const
|
|
263
|
-
|
|
262
|
+
var l = ue();
|
|
263
|
+
const f = {
|
|
264
|
+
container: {
|
|
265
|
+
position: "fixed",
|
|
266
|
+
bottom: "20px",
|
|
267
|
+
right: "20px",
|
|
268
|
+
backgroundColor: "rgba(0, 0, 0, 0.85)",
|
|
269
|
+
color: "#fff",
|
|
270
|
+
padding: "12px",
|
|
271
|
+
borderRadius: "8px",
|
|
272
|
+
fontFamily: "monospace",
|
|
273
|
+
fontSize: "12px",
|
|
274
|
+
zIndex: 9999,
|
|
275
|
+
boxShadow: "0 4px 12px rgba(0,0,0,0.3)",
|
|
276
|
+
minWidth: "200px",
|
|
277
|
+
border: "1px solid #333",
|
|
278
|
+
backdropFilter: "blur(4px)",
|
|
279
|
+
transition: "border-color 0.3s ease"
|
|
280
|
+
},
|
|
281
|
+
metricRow: {
|
|
282
|
+
display: "flex",
|
|
283
|
+
justifyContent: "space-between",
|
|
284
|
+
marginBottom: "4px"
|
|
285
|
+
},
|
|
286
|
+
label: {
|
|
287
|
+
color: "#aaa"
|
|
288
|
+
},
|
|
289
|
+
value: {
|
|
290
|
+
fontWeight: "bold"
|
|
291
|
+
},
|
|
292
|
+
indicator: {
|
|
293
|
+
display: "inline-block",
|
|
294
|
+
width: "8px",
|
|
295
|
+
height: "8px",
|
|
296
|
+
borderRadius: "50%",
|
|
297
|
+
marginRight: "8px"
|
|
298
|
+
},
|
|
299
|
+
title: {
|
|
300
|
+
margin: "0 0 8px 0",
|
|
301
|
+
fontSize: "14px",
|
|
302
|
+
fontWeight: "bold",
|
|
303
|
+
borderBottom: "1px solid #444",
|
|
304
|
+
paddingBottom: "4px",
|
|
305
|
+
display: "flex",
|
|
306
|
+
alignItems: "center"
|
|
307
|
+
}
|
|
308
|
+
}, fe = (n) => n < 16 ? "#4caf50" : n < 50 ? "#ff9800" : "#f44336", de = ({
|
|
309
|
+
lastRenderTime: n,
|
|
310
|
+
renderCount: s,
|
|
311
|
+
lastRenderId: p
|
|
312
|
+
}) => {
|
|
313
|
+
const [d, i] = D(!1), [c, u] = D(!1);
|
|
314
|
+
if (z(() => {
|
|
315
|
+
if (s > 0) {
|
|
316
|
+
i(!0), u(!0);
|
|
317
|
+
const R = setTimeout(() => u(!1), 300);
|
|
318
|
+
return () => clearTimeout(R);
|
|
319
|
+
}
|
|
320
|
+
}, [s, n]), !d) return null;
|
|
321
|
+
const m = fe(n);
|
|
322
|
+
return /* @__PURE__ */ l.jsxs(
|
|
323
|
+
"div",
|
|
324
|
+
{
|
|
325
|
+
style: {
|
|
326
|
+
...f.container,
|
|
327
|
+
borderColor: c ? m : "#333"
|
|
328
|
+
},
|
|
329
|
+
children: [
|
|
330
|
+
/* @__PURE__ */ l.jsxs("h4", { style: f.title, children: [
|
|
331
|
+
/* @__PURE__ */ l.jsx(
|
|
332
|
+
"span",
|
|
333
|
+
{
|
|
334
|
+
style: { ...f.indicator, backgroundColor: m }
|
|
335
|
+
}
|
|
336
|
+
),
|
|
337
|
+
"RenderGuard"
|
|
338
|
+
] }),
|
|
339
|
+
/* @__PURE__ */ l.jsxs("div", { style: f.metricRow, children: [
|
|
340
|
+
/* @__PURE__ */ l.jsx("span", { style: f.label, children: "Last Render:" }),
|
|
341
|
+
/* @__PURE__ */ l.jsxs("span", { style: { ...f.value, color: m }, children: [
|
|
342
|
+
n.toFixed(2),
|
|
343
|
+
"ms"
|
|
344
|
+
] })
|
|
345
|
+
] }),
|
|
346
|
+
/* @__PURE__ */ l.jsxs("div", { style: f.metricRow, children: [
|
|
347
|
+
/* @__PURE__ */ l.jsx("span", { style: f.label, children: "Total Renders:" }),
|
|
348
|
+
/* @__PURE__ */ l.jsx("span", { style: f.value, children: s })
|
|
349
|
+
] }),
|
|
350
|
+
/* @__PURE__ */ l.jsxs("div", { style: f.metricRow, children: [
|
|
351
|
+
/* @__PURE__ */ l.jsx("span", { style: f.label, children: "Source:" }),
|
|
352
|
+
/* @__PURE__ */ l.jsx(
|
|
353
|
+
"span",
|
|
354
|
+
{
|
|
355
|
+
style: {
|
|
356
|
+
...f.value,
|
|
357
|
+
maxWidth: "100px",
|
|
358
|
+
whiteSpace: "nowrap",
|
|
359
|
+
overflow: "hidden",
|
|
360
|
+
textOverflow: "ellipsis"
|
|
361
|
+
},
|
|
362
|
+
children: p
|
|
363
|
+
}
|
|
364
|
+
)
|
|
365
|
+
] })
|
|
366
|
+
]
|
|
367
|
+
}
|
|
368
|
+
);
|
|
369
|
+
}, me = 3, pe = C.memo(
|
|
370
|
+
({
|
|
371
|
+
children: n,
|
|
372
|
+
onRender: s
|
|
373
|
+
}) => /* @__PURE__ */ l.jsx(oe, { id: "RenderGuardRoot", onRender: s, children: n })
|
|
374
|
+
), xe = ({
|
|
375
|
+
children: n,
|
|
264
376
|
onRenderCallback: s,
|
|
265
|
-
threshold:
|
|
377
|
+
threshold: p = me
|
|
266
378
|
}) => {
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
379
|
+
const [d, i] = C.useState({
|
|
380
|
+
lastRenderTime: 0,
|
|
381
|
+
renderCount: 0,
|
|
382
|
+
lastRenderId: ""
|
|
383
|
+
}), c = ae(
|
|
384
|
+
(u, m, R, j, _, v) => {
|
|
385
|
+
i((T) => ({
|
|
386
|
+
lastRenderTime: R,
|
|
387
|
+
renderCount: T.renderCount + 1,
|
|
388
|
+
lastRenderId: u
|
|
389
|
+
})), R > 5 && console.warn(
|
|
390
|
+
`[RenderGuard] Slow render detected in ${u}: ${R.toFixed(2)}ms`
|
|
271
391
|
), s && s(
|
|
272
|
-
a,
|
|
273
392
|
u,
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
393
|
+
m,
|
|
394
|
+
R,
|
|
395
|
+
j,
|
|
396
|
+
_,
|
|
397
|
+
v
|
|
278
398
|
);
|
|
279
399
|
},
|
|
280
|
-
[s,
|
|
400
|
+
[s, p]
|
|
281
401
|
);
|
|
282
|
-
return /* @__PURE__ */
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
402
|
+
return /* @__PURE__ */ l.jsxs(l.Fragment, { children: [
|
|
403
|
+
/* @__PURE__ */ l.jsx(pe, { onRender: c, children: n }),
|
|
404
|
+
typeof document < "u" && le(
|
|
405
|
+
/* @__PURE__ */ l.jsx(
|
|
406
|
+
de,
|
|
407
|
+
{
|
|
408
|
+
lastRenderTime: d.lastRenderTime,
|
|
409
|
+
renderCount: d.renderCount,
|
|
410
|
+
lastRenderId: d.lastRenderId
|
|
411
|
+
}
|
|
412
|
+
),
|
|
413
|
+
document.body
|
|
414
|
+
)
|
|
415
|
+
] });
|
|
416
|
+
}, Ee = (n) => {
|
|
417
|
+
const s = se(0);
|
|
418
|
+
return z(() => {
|
|
286
419
|
s.current += 1, console.log(
|
|
287
|
-
`[RenderGuard] ${
|
|
420
|
+
`[RenderGuard] ${n} rendered ${s.current} times`
|
|
288
421
|
);
|
|
289
422
|
}), s.current;
|
|
290
423
|
};
|
|
291
424
|
export {
|
|
292
|
-
|
|
293
|
-
|
|
425
|
+
xe as RenderGuard,
|
|
426
|
+
Ee as useRenderCheck
|
|
294
427
|
};
|
package/dist/render-guard.umd.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(b,u){typeof exports=="object"&&typeof module<"u"?u(exports,require("react"),require("react-dom")):typeof define=="function"&&define.amd?define(["exports","react","react-dom"],u):(b=typeof globalThis<"u"?globalThis:b||self,u(b.RenderGuard={},b.React,b.ReactDOM))})(this,(function(b,u,z){"use strict";var T={exports:{}},_={};var I;function V(){if(I)return _;I=1;var n=Symbol.for("react.transitional.element"),s=Symbol.for("react.fragment");function R(m,i,c){var f=null;if(c!==void 0&&(f=""+c),i.key!==void 0&&(f=""+i.key),"key"in i){c={};for(var p in i)p!=="key"&&(c[p]=i[p])}else c=i;return i=c.ref,{$$typeof:n,type:m,key:f,ref:i!==void 0?i:null,props:c}}return _.Fragment=s,_.jsx=R,_.jsxs=R,_}var v={};var F;function q(){return F||(F=1,process.env.NODE_ENV!=="production"&&(function(){function n(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===ce?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case w:return"Fragment";case te:return"Profiler";case re:return"StrictMode";case se:return"Suspense";case le:return"SuspenseList";case ue:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case ee:return"Portal";case oe:return e.displayName||"Context";case ne:return(e._context.displayName||"Context")+".Consumer";case ae:var r=e.render;return e=e.displayName,e||(e=r.displayName||r.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case ie:return r=e.displayName||null,r!==null?r:n(e.type)||"Memo";case O:r=e._payload,e=e._init;try{return n(e(r))}catch{}}return null}function s(e){return""+e}function R(e){try{s(e);var r=!1}catch{r=!0}if(r){r=console;var t=r.error,o=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return t.call(r,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",o),s(e)}}function m(e){if(e===w)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===O)return"<...>";try{var r=n(e);return r?"<"+r+">":"<...>"}catch{return"<...>"}}function i(){var e=A.A;return e===null?null:e.getOwner()}function c(){return Error("react-stack-top-frame")}function f(e){if(W.call(e,"key")){var r=Object.getOwnPropertyDescriptor(e,"key").get;if(r&&r.isReactWarning)return!1}return e.key!==void 0}function p(e,r){function t(){L||(L=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",r))}t.isReactWarning=!0,Object.defineProperty(e,"key",{get:t,configurable:!0})}function E(){var e=n(this.type);return M[e]||(M[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function k(e,r,t,o,g,C){var a=t.ref;return e={$$typeof:$,type:e,key:r,props:t,_owner:o},(a!==void 0?a:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:E}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:g}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:C}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function h(e,r,t,o,g,C){var a=r.children;if(a!==void 0)if(o)if(de(a)){for(o=0;o<a.length;o++)y(a[o]);Object.freeze&&Object.freeze(a)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else y(a);if(W.call(r,"key")){a=n(e);var x=Object.keys(r).filter(function(fe){return fe!=="key"});o=0<x.length?"{key: someKey, "+x.join(": ..., ")+": ...}":"{key: someKey}",U[a+o]||(x=0<x.length?"{"+x.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
|
|
2
2
|
let props = %s;
|
|
3
3
|
<%s {...props} />
|
|
4
4
|
React keys must be passed directly to JSX without using spread:
|
|
5
5
|
let props = %s;
|
|
6
|
-
<%s key={someKey} {...props} />`,
|
|
6
|
+
<%s key={someKey} {...props} />`,o,a,x,a),U[a+o]=!0)}if(a=null,t!==void 0&&(R(t),a=""+t),f(r)&&(R(r.key),a=""+r.key),"key"in r){t={};for(var N in r)N!=="key"&&(t[N]=r[N])}else t=r;return a&&p(t,typeof e=="function"?e.displayName||e.name||"Unknown":e),k(e,a,t,i(),g,C)}function y(e){j(e)?e._store&&(e._store.validated=1):typeof e=="object"&&e!==null&&e.$$typeof===O&&(e._payload.status==="fulfilled"?j(e._payload.value)&&e._payload.value._store&&(e._payload.value._store.validated=1):e._store&&(e._store.validated=1))}function j(e){return typeof e=="object"&&e!==null&&e.$$typeof===$}var S=u,$=Symbol.for("react.transitional.element"),ee=Symbol.for("react.portal"),w=Symbol.for("react.fragment"),re=Symbol.for("react.strict_mode"),te=Symbol.for("react.profiler"),ne=Symbol.for("react.consumer"),oe=Symbol.for("react.context"),ae=Symbol.for("react.forward_ref"),se=Symbol.for("react.suspense"),le=Symbol.for("react.suspense_list"),ie=Symbol.for("react.memo"),O=Symbol.for("react.lazy"),ue=Symbol.for("react.activity"),ce=Symbol.for("react.client.reference"),A=S.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,W=Object.prototype.hasOwnProperty,de=Array.isArray,P=console.createTask?console.createTask:function(){return null};S={react_stack_bottom_frame:function(e){return e()}};var L,M={},D=S.react_stack_bottom_frame.bind(S,c)(),G=P(m(c)),U={};v.Fragment=w,v.jsx=function(e,r,t){var o=1e4>A.recentlyCreatedOwnerStacks++;return h(e,r,t,!1,o?Error("react-stack-top-frame"):D,o?P(m(e)):G)},v.jsxs=function(e,r,t){var o=1e4>A.recentlyCreatedOwnerStacks++;return h(e,r,t,!0,o?Error("react-stack-top-frame"):D,o?P(m(e)):G)}})()),v}var Y;function J(){return Y||(Y=1,process.env.NODE_ENV==="production"?T.exports=V():T.exports=q()),T.exports}var l=J();const d={container:{position:"fixed",bottom:"20px",right:"20px",backgroundColor:"rgba(0, 0, 0, 0.85)",color:"#fff",padding:"12px",borderRadius:"8px",fontFamily:"monospace",fontSize:"12px",zIndex:9999,boxShadow:"0 4px 12px rgba(0,0,0,0.3)",minWidth:"200px",border:"1px solid #333",backdropFilter:"blur(4px)",transition:"border-color 0.3s ease"},metricRow:{display:"flex",justifyContent:"space-between",marginBottom:"4px"},label:{color:"#aaa"},value:{fontWeight:"bold"},indicator:{display:"inline-block",width:"8px",height:"8px",borderRadius:"50%",marginRight:"8px"},title:{margin:"0 0 8px 0",fontSize:"14px",fontWeight:"bold",borderBottom:"1px solid #444",paddingBottom:"4px",display:"flex",alignItems:"center"}},B=n=>n<16?"#4caf50":n<50?"#ff9800":"#f44336",X=({lastRenderTime:n,renderCount:s,lastRenderId:R})=>{const[m,i]=u.useState(!1),[c,f]=u.useState(!1);if(u.useEffect(()=>{if(s>0){i(!0),f(!0);const E=setTimeout(()=>f(!1),300);return()=>clearTimeout(E)}},[s,n]),!m)return null;const p=B(n);return l.jsxs("div",{style:{...d.container,borderColor:c?p:"#333"},children:[l.jsxs("h4",{style:d.title,children:[l.jsx("span",{style:{...d.indicator,backgroundColor:p}}),"RenderGuard"]}),l.jsxs("div",{style:d.metricRow,children:[l.jsx("span",{style:d.label,children:"Last Render:"}),l.jsxs("span",{style:{...d.value,color:p},children:[n.toFixed(2),"ms"]})]}),l.jsxs("div",{style:d.metricRow,children:[l.jsx("span",{style:d.label,children:"Total Renders:"}),l.jsx("span",{style:d.value,children:s})]}),l.jsxs("div",{style:d.metricRow,children:[l.jsx("span",{style:d.label,children:"Source:"}),l.jsx("span",{style:{...d.value,maxWidth:"100px",whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis"},children:R})]})]})},H=3,Z=u.memo(({children:n,onRender:s})=>l.jsx(u.Profiler,{id:"RenderGuardRoot",onRender:s,children:n})),Q=({children:n,onRenderCallback:s,threshold:R=H})=>{const[m,i]=u.useState({lastRenderTime:0,renderCount:0,lastRenderId:""}),c=u.useCallback((f,p,E,k,h,y)=>{i(j=>({lastRenderTime:E,renderCount:j.renderCount+1,lastRenderId:f})),E>5&&console.warn(`[RenderGuard] Slow render detected in ${f}: ${E.toFixed(2)}ms`),s&&s(f,p,E,k,h,y)},[s,R]);return l.jsxs(l.Fragment,{children:[l.jsx(Z,{onRender:c,children:n}),typeof document<"u"&&z.createPortal(l.jsx(X,{lastRenderTime:m.lastRenderTime,renderCount:m.renderCount,lastRenderId:m.lastRenderId}),document.body)]})},K=n=>{const s=u.useRef(0);return u.useEffect(()=>{s.current+=1,console.log(`[RenderGuard] ${n} rendered ${s.current} times`)}),s.current};b.RenderGuard=Q,b.useRenderCheck=K,Object.defineProperty(b,Symbol.toStringTag,{value:"Module"})}));
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-render-guard",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/render-guard.umd.js",
|
|
6
6
|
"module": "./dist/render-guard.es.js",
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
],
|
|
17
17
|
"scripts": {
|
|
18
18
|
"build": "tsc && vite build",
|
|
19
|
-
"dev": "vite build --watch"
|
|
19
|
+
"dev": "vite build --watch",
|
|
20
|
+
"test": "vitest"
|
|
20
21
|
},
|
|
21
22
|
"keywords": [
|
|
22
23
|
"react",
|
|
@@ -36,14 +37,19 @@
|
|
|
36
37
|
"react-dom": ">=16.8.0"
|
|
37
38
|
},
|
|
38
39
|
"devDependencies": {
|
|
40
|
+
"@testing-library/dom": "^10.4.1",
|
|
41
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
42
|
+
"@testing-library/react": "^16.3.2",
|
|
39
43
|
"@types/node": "^25.2.0",
|
|
40
44
|
"@types/react": "^19.2.11",
|
|
41
45
|
"@types/react-dom": "^19.2.3",
|
|
42
46
|
"@vitejs/plugin-react": "^5.1.3",
|
|
47
|
+
"jsdom": "^28.0.0",
|
|
43
48
|
"react": "^19.2.4",
|
|
44
49
|
"react-dom": "^19.2.4",
|
|
45
50
|
"typescript": "^5.9.3",
|
|
46
51
|
"vite": "^7.3.1",
|
|
47
|
-
"vite-plugin-dts": "^4.5.4"
|
|
52
|
+
"vite-plugin-dts": "^4.5.4",
|
|
53
|
+
"vitest": "^4.0.18"
|
|
48
54
|
}
|
|
49
55
|
}
|