@buoy-gg/highlight-updates 2.1.11 → 2.1.13
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/LICENSE +58 -0
- package/lib/commonjs/highlight-updates/HighlightUpdatesOverlay.js +1 -285
- package/lib/commonjs/highlight-updates/components/HighlightFilterView.js +1 -1371
- package/lib/commonjs/highlight-updates/components/HighlightUpdatesModal.js +1 -591
- package/lib/commonjs/highlight-updates/components/IdentifierBadge.js +1 -267
- package/lib/commonjs/highlight-updates/components/IsolatedRenderList.js +1 -178
- package/lib/commonjs/highlight-updates/components/ModalHeaderContent.js +1 -303
- package/lib/commonjs/highlight-updates/components/RenderCauseBadge.js +1 -500
- package/lib/commonjs/highlight-updates/components/RenderDetailView.js +1 -830
- package/lib/commonjs/highlight-updates/components/RenderHistoryViewer.js +1 -894
- package/lib/commonjs/highlight-updates/components/RenderListItem.js +1 -220
- package/lib/commonjs/highlight-updates/components/StatsDisplay.js +1 -70
- package/lib/commonjs/highlight-updates/components/index.js +1 -97
- package/lib/commonjs/highlight-updates/utils/HighlightUpdatesController.js +1 -1435
- package/lib/commonjs/highlight-updates/utils/PerformanceLogger.js +1 -359
- package/lib/commonjs/highlight-updates/utils/ProfilerInterceptor.js +1 -371
- package/lib/commonjs/highlight-updates/utils/RenderCauseDetector.js +1 -1828
- package/lib/commonjs/highlight-updates/utils/RenderTracker.js +1 -903
- package/lib/commonjs/highlight-updates/utils/ViewTypeMapper.js +1 -264
- package/lib/commonjs/highlight-updates/utils/renderExportFormatter.js +1 -58
- package/lib/commonjs/index.js +1 -311
- package/lib/commonjs/preset.js +1 -278
- package/lib/module/highlight-updates/HighlightUpdatesOverlay.js +1 -278
- package/lib/module/highlight-updates/components/HighlightFilterView.js +1 -1365
- package/lib/module/highlight-updates/components/HighlightUpdatesModal.js +1 -585
- package/lib/module/highlight-updates/components/IdentifierBadge.js +1 -259
- package/lib/module/highlight-updates/components/IsolatedRenderList.js +1 -174
- package/lib/module/highlight-updates/components/ModalHeaderContent.js +1 -298
- package/lib/module/highlight-updates/components/RenderCauseBadge.js +1 -491
- package/lib/module/highlight-updates/components/RenderDetailView.js +1 -826
- package/lib/module/highlight-updates/components/RenderHistoryViewer.js +1 -888
- package/lib/module/highlight-updates/components/RenderListItem.js +1 -215
- package/lib/module/highlight-updates/components/StatsDisplay.js +1 -67
- package/lib/module/highlight-updates/components/index.js +1 -16
- package/lib/module/highlight-updates/utils/HighlightUpdatesController.js +1 -1431
- package/lib/module/highlight-updates/utils/PerformanceLogger.js +1 -353
- package/lib/module/highlight-updates/utils/ProfilerInterceptor.js +1 -358
- package/lib/module/highlight-updates/utils/RenderCauseDetector.js +1 -1818
- package/lib/module/highlight-updates/utils/RenderTracker.js +1 -900
- package/lib/module/highlight-updates/utils/ViewTypeMapper.js +1 -255
- package/lib/module/highlight-updates/utils/renderExportFormatter.js +1 -54
- package/lib/module/index.js +1 -71
- package/lib/module/preset.js +1 -272
- package/package.json +16 -16
- package/lib/typescript/highlight-updates/HighlightUpdatesOverlay.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/HighlightFilterView.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/HighlightUpdatesModal.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/IdentifierBadge.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/IsolatedRenderList.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/ModalHeaderContent.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/RenderCauseBadge.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/RenderDetailView.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/RenderHistoryViewer.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/RenderListItem.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/StatsDisplay.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/index.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/HighlightUpdatesController.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/PerformanceLogger.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/ProfilerInterceptor.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/RenderCauseDetector.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/RenderTracker.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/ViewTypeMapper.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/renderExportFormatter.d.ts.map +0 -1
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/preset.d.ts.map +0 -1
package/lib/commonjs/preset.js
CHANGED
|
@@ -1,278 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.createHighlightUpdatesModalTool = createHighlightUpdatesModalTool;
|
|
7
|
-
exports.createHighlightUpdatesTool = createHighlightUpdatesTool;
|
|
8
|
-
exports.highlightUpdatesPreset = exports.highlightUpdatesModalPreset = void 0;
|
|
9
|
-
var _react = _interopRequireWildcard(require("react"));
|
|
10
|
-
var _floatingToolsCore = require("@buoy-gg/floating-tools-core");
|
|
11
|
-
var _HighlightUpdatesController = _interopRequireDefault(require("./highlight-updates/utils/HighlightUpdatesController"));
|
|
12
|
-
var _HighlightUpdatesModal = require("./highlight-updates/components/HighlightUpdatesModal");
|
|
13
|
-
var _jsxRuntime = require("react/jsx-runtime");
|
|
14
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
|
-
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
16
|
-
/**
|
|
17
|
-
* Pre-configured highlight updates tool for FloatingDevTools
|
|
18
|
-
*
|
|
19
|
-
* This preset provides standalone "Highlight updates when components render"
|
|
20
|
-
* functionality. Tap the icon to toggle highlights on/off.
|
|
21
|
-
*
|
|
22
|
-
* The overlay is automatically rendered by FloatingDevTools when the
|
|
23
|
-
* @buoy-gg/highlight-updates package is installed.
|
|
24
|
-
*
|
|
25
|
-
* Two presets available:
|
|
26
|
-
* - highlightUpdatesPreset: Quick toggle (no modal)
|
|
27
|
-
* - highlightUpdatesModalPreset: Full modal with filters and render list
|
|
28
|
-
*
|
|
29
|
-
* @example
|
|
30
|
-
* ```tsx
|
|
31
|
-
* import { highlightUpdatesPreset, highlightUpdatesModalPreset } from '@buoy-gg/highlight-updates';
|
|
32
|
-
*
|
|
33
|
-
* // Toggle-only: Just tap to enable/disable highlighting
|
|
34
|
-
* <FloatingDevTools apps={[highlightUpdatesPreset]} />
|
|
35
|
-
*
|
|
36
|
-
* // Modal: Opens interface with filters, render list, and controls
|
|
37
|
-
* <FloatingDevTools apps={[highlightUpdatesModalPreset]} />
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Icon component that changes color based on enabled state.
|
|
43
|
-
*
|
|
44
|
-
* ⚠️ IMPORTANT - DO NOT MODIFY THIS COMPONENT ⚠️
|
|
45
|
-
* This component MUST use useState and useEffect hooks to subscribe to the controller.
|
|
46
|
-
* It is rendered as a JSX component (<IconComponent />) in FloatingMenu and DialIcon,
|
|
47
|
-
* which allows hooks to work properly.
|
|
48
|
-
*
|
|
49
|
-
* If you remove the hooks or change this to read isEnabled() directly,
|
|
50
|
-
* the icon color will NOT update when the toggle is pressed.
|
|
51
|
-
*/function HighlightIcon({
|
|
52
|
-
size
|
|
53
|
-
}) {
|
|
54
|
-
const [enabled, setEnabled] = (0, _react.useState)(() => _HighlightUpdatesController.default.isEnabled());
|
|
55
|
-
(0, _react.useEffect)(() => {
|
|
56
|
-
const unsubscribe = _HighlightUpdatesController.default.subscribe(isEnabled => {
|
|
57
|
-
setEnabled(isEnabled);
|
|
58
|
-
});
|
|
59
|
-
return unsubscribe;
|
|
60
|
-
}, []);
|
|
61
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.HighlightIcon, {
|
|
62
|
-
size: size,
|
|
63
|
-
color: enabled ? "#10b981" : "#6b7280"
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Empty component for toggle-only tools (no modal needed)
|
|
69
|
-
* The actual overlay is rendered by FloatingDevTools automatically
|
|
70
|
-
*/
|
|
71
|
-
function EmptyComponent() {
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Wrapper component for the modal that handles badge press navigation.
|
|
77
|
-
* Registers a callback with the controller to receive badge press events
|
|
78
|
-
* and passes the target nativeTag to the modal for deep linking.
|
|
79
|
-
*/
|
|
80
|
-
function HighlightUpdatesModalWithBadgeNavigation(props) {
|
|
81
|
-
const [targetNativeTag, setTargetNativeTag] = (0, _react.useState)(null);
|
|
82
|
-
|
|
83
|
-
// Register badge press callback when modal is visible
|
|
84
|
-
(0, _react.useEffect)(() => {
|
|
85
|
-
if (props.visible) {
|
|
86
|
-
// Register callback to handle badge presses
|
|
87
|
-
_HighlightUpdatesController.default.setBadgePressCallback(nativeTag => {
|
|
88
|
-
setTargetNativeTag(nativeTag);
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
return () => {
|
|
92
|
-
// Clear callback when modal is closed or unmounted
|
|
93
|
-
if (!props.visible) {
|
|
94
|
-
_HighlightUpdatesController.default.setBadgePressCallback(null);
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
}, [props.visible]);
|
|
98
|
-
|
|
99
|
-
// Clear the target after it's been handled
|
|
100
|
-
const handleInitialNativeTagHandled = (0, _react.useCallback)(() => {
|
|
101
|
-
setTargetNativeTag(null);
|
|
102
|
-
}, []);
|
|
103
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_HighlightUpdatesModal.HighlightUpdatesModal, {
|
|
104
|
-
...props,
|
|
105
|
-
initialNativeTag: targetNativeTag,
|
|
106
|
-
onInitialNativeTagHandled: handleInitialNativeTagHandled
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Pre-configured highlight updates tool for FloatingDevTools.
|
|
112
|
-
* Tap the icon to toggle component render highlighting on/off.
|
|
113
|
-
*
|
|
114
|
-
* Features:
|
|
115
|
-
* - Standalone implementation - no DevTools connection required
|
|
116
|
-
* - Simple direct toggle (no modal)
|
|
117
|
-
* - Icon changes color: gray when off, green when on
|
|
118
|
-
* - Overlay auto-rendered by FloatingDevTools
|
|
119
|
-
*/
|
|
120
|
-
const highlightUpdatesPreset = exports.highlightUpdatesPreset = {
|
|
121
|
-
id: "highlight-updates",
|
|
122
|
-
name: "TOGGLE HIGHLIGHT",
|
|
123
|
-
description: "Toggle component render highlights",
|
|
124
|
-
slot: "row",
|
|
125
|
-
icon: HighlightIcon,
|
|
126
|
-
component: EmptyComponent,
|
|
127
|
-
props: {},
|
|
128
|
-
launchMode: "toggle-only",
|
|
129
|
-
onPress: () => {
|
|
130
|
-
// Initialize on first press if not already initialized
|
|
131
|
-
if (!_HighlightUpdatesController.default.isInitialized()) {
|
|
132
|
-
_HighlightUpdatesController.default.initialize();
|
|
133
|
-
}
|
|
134
|
-
_HighlightUpdatesController.default.toggle();
|
|
135
|
-
// Icon updates automatically via subscription in HighlightIcon component
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Create a custom highlight updates tool configuration.
|
|
141
|
-
* Use this if you want to override default settings.
|
|
142
|
-
*
|
|
143
|
-
* @example
|
|
144
|
-
* ```tsx
|
|
145
|
-
* import { createHighlightUpdatesTool } from '@buoy-gg/highlight-updates';
|
|
146
|
-
*
|
|
147
|
-
* const myHighlightTool = createHighlightUpdatesTool({
|
|
148
|
-
* name: "RENDERS",
|
|
149
|
-
* enabledColor: "#ec4899",
|
|
150
|
-
* disabledColor: "#9ca3af",
|
|
151
|
-
* autoInitialize: true,
|
|
152
|
-
* });
|
|
153
|
-
* ```
|
|
154
|
-
*/
|
|
155
|
-
function createHighlightUpdatesTool(options) {
|
|
156
|
-
const enabledColor = options?.enabledColor || "#10b981";
|
|
157
|
-
const disabledColor = options?.disabledColor || "#6b7280";
|
|
158
|
-
|
|
159
|
-
// Auto-initialize if requested
|
|
160
|
-
if (options?.autoInitialize) {
|
|
161
|
-
// Delay to allow DevTools to connect
|
|
162
|
-
setTimeout(() => {
|
|
163
|
-
_HighlightUpdatesController.default.initialize();
|
|
164
|
-
}, 1000);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Custom icon component with hooks - rendered as JSX component.
|
|
169
|
-
*
|
|
170
|
-
* ⚠️ IMPORTANT - DO NOT MODIFY THIS COMPONENT ⚠️
|
|
171
|
-
* This component MUST use useState and useEffect hooks to subscribe to the controller.
|
|
172
|
-
* See the comment on HighlightIcon above for full explanation.
|
|
173
|
-
*/
|
|
174
|
-
const CustomHighlightIcon = ({
|
|
175
|
-
size
|
|
176
|
-
}) => {
|
|
177
|
-
const [enabled, setEnabled] = (0, _react.useState)(() => _HighlightUpdatesController.default.isEnabled());
|
|
178
|
-
(0, _react.useEffect)(() => {
|
|
179
|
-
const unsubscribe = _HighlightUpdatesController.default.subscribe(isEnabled => {
|
|
180
|
-
setEnabled(isEnabled);
|
|
181
|
-
});
|
|
182
|
-
return unsubscribe;
|
|
183
|
-
}, []);
|
|
184
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.HighlightIcon, {
|
|
185
|
-
size: size,
|
|
186
|
-
color: enabled ? enabledColor : disabledColor
|
|
187
|
-
});
|
|
188
|
-
};
|
|
189
|
-
return {
|
|
190
|
-
id: options?.id || "highlight-updates",
|
|
191
|
-
name: options?.name || "TOGGLE HIGHLIGHT",
|
|
192
|
-
description: options?.description || "Toggle component render highlights",
|
|
193
|
-
slot: "row",
|
|
194
|
-
icon: CustomHighlightIcon,
|
|
195
|
-
component: EmptyComponent,
|
|
196
|
-
props: {},
|
|
197
|
-
launchMode: "toggle-only",
|
|
198
|
-
onPress: () => {
|
|
199
|
-
// Initialize on first press if not already initialized
|
|
200
|
-
if (!_HighlightUpdatesController.default.isInitialized()) {
|
|
201
|
-
_HighlightUpdatesController.default.initialize();
|
|
202
|
-
}
|
|
203
|
-
_HighlightUpdatesController.default.toggle();
|
|
204
|
-
// Icon updates automatically via subscription
|
|
205
|
-
}
|
|
206
|
-
};
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Modal preset for highlight updates tool.
|
|
211
|
-
* Opens a full modal interface with:
|
|
212
|
-
* - List of tracked component renders
|
|
213
|
-
* - Start/Stop and Pause/Resume controls
|
|
214
|
-
* - Clear button to reset render counts
|
|
215
|
-
* - Search bar in navbar (expandable)
|
|
216
|
-
* - Filter by viewType, testID, nativeID, componentName
|
|
217
|
-
* - Tap overlay badge to jump to component detail view
|
|
218
|
-
*
|
|
219
|
-
* Use this preset when you want detailed render tracking and filtering.
|
|
220
|
-
*/
|
|
221
|
-
const highlightUpdatesModalPreset = exports.highlightUpdatesModalPreset = {
|
|
222
|
-
id: "highlight-updates-modal",
|
|
223
|
-
name: "HIGHLIGHT",
|
|
224
|
-
description: "View component render tracking modal",
|
|
225
|
-
slot: "both",
|
|
226
|
-
icon: ({
|
|
227
|
-
size
|
|
228
|
-
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.HighlighterIcon, {
|
|
229
|
-
size: size
|
|
230
|
-
}),
|
|
231
|
-
component: HighlightUpdatesModalWithBadgeNavigation,
|
|
232
|
-
props: {
|
|
233
|
-
enableSharedModalDimensions: false
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Create a custom highlight updates modal tool configuration.
|
|
239
|
-
* Use this if you want to override default settings for the modal version.
|
|
240
|
-
*
|
|
241
|
-
* @example
|
|
242
|
-
* ```tsx
|
|
243
|
-
* import { createHighlightUpdatesModalTool } from '@buoy-gg/highlight-updates';
|
|
244
|
-
*
|
|
245
|
-
* const myRendersTool = createHighlightUpdatesModalTool({
|
|
246
|
-
* name: "PROFILER",
|
|
247
|
-
* enabledColor: "#8b5cf6",
|
|
248
|
-
* disabledColor: "#9ca3af",
|
|
249
|
-
* });
|
|
250
|
-
* ```
|
|
251
|
-
*/
|
|
252
|
-
function createHighlightUpdatesModalTool(options) {
|
|
253
|
-
const enabledColor = options?.enabledColor || "#10b981";
|
|
254
|
-
const disabledColor = options?.disabledColor || "#6b7280";
|
|
255
|
-
|
|
256
|
-
// Auto-initialize if requested
|
|
257
|
-
if (options?.autoInitialize) {
|
|
258
|
-
setTimeout(() => {
|
|
259
|
-
_HighlightUpdatesController.default.initialize();
|
|
260
|
-
}, 1000);
|
|
261
|
-
}
|
|
262
|
-
return {
|
|
263
|
-
id: options?.id || "highlight-updates-modal",
|
|
264
|
-
name: options?.name || "HIGHLIGHT",
|
|
265
|
-
description: options?.description || "View component render tracking modal",
|
|
266
|
-
slot: "both",
|
|
267
|
-
icon: ({
|
|
268
|
-
size
|
|
269
|
-
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsCore.HighlighterIcon, {
|
|
270
|
-
size: size,
|
|
271
|
-
color: enabledColor
|
|
272
|
-
}),
|
|
273
|
-
component: HighlightUpdatesModalWithBadgeNavigation,
|
|
274
|
-
props: {
|
|
275
|
-
enableSharedModalDimensions: false
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.createHighlightUpdatesModalTool=createHighlightUpdatesModalTool,exports.createHighlightUpdatesTool=createHighlightUpdatesTool,exports.highlightUpdatesPreset=exports.highlightUpdatesModalPreset=void 0;var _react=_interopRequireWildcard(require("react")),_floatingToolsCore=require("@buoy-gg/floating-tools-core"),_HighlightUpdatesController=_interopRequireDefault(require("./highlight-updates/utils/HighlightUpdatesController")),_HighlightUpdatesModal=require("./highlight-updates/components/HighlightUpdatesModal"),_jsxRuntime=require("react/jsx-runtime");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _interopRequireWildcard(e,t){if("function"==typeof WeakMap)var i=new WeakMap,o=new WeakMap;return(_interopRequireWildcard=function(e,t){if(!t&&e&&e.__esModule)return e;var l,a,n={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return n;if(l=t?o:i){if(l.has(e))return l.get(e);l.set(e,n)}for(const t in e)"default"!==t&&{}.hasOwnProperty.call(e,t)&&((a=(l=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,t))&&(a.get||a.set)?l(n,t,a):n[t]=e[t]);return n})(e,t)}function HighlightIcon({size:e}){const[t,i]=(0,_react.useState)(()=>_HighlightUpdatesController.default.isEnabled());return(0,_react.useEffect)(()=>_HighlightUpdatesController.default.subscribe(e=>{i(e)}),[]),(0,_jsxRuntime.jsx)(_floatingToolsCore.HighlightIcon,{size:e,color:t?"#10b981":"#6b7280"})}function EmptyComponent(){return null}function HighlightUpdatesModalWithBadgeNavigation(e){const[t,i]=(0,_react.useState)(null);(0,_react.useEffect)(()=>(e.visible&&_HighlightUpdatesController.default.setBadgePressCallback(e=>{i(e)}),()=>{e.visible||_HighlightUpdatesController.default.setBadgePressCallback(null)}),[e.visible]);const o=(0,_react.useCallback)(()=>{i(null)},[]);return(0,_jsxRuntime.jsx)(_HighlightUpdatesModal.HighlightUpdatesModal,{...e,initialNativeTag:t,onInitialNativeTagHandled:o})}const highlightUpdatesPreset=exports.highlightUpdatesPreset={id:"highlight-updates",name:"TOGGLE HIGHLIGHT",description:"Toggle component render highlights",slot:"row",icon:HighlightIcon,component:EmptyComponent,props:{},launchMode:"toggle-only",onPress:()=>{_HighlightUpdatesController.default.isInitialized()||_HighlightUpdatesController.default.initialize(),_HighlightUpdatesController.default.toggle()}};function createHighlightUpdatesTool(e){const t=e?.enabledColor||"#10b981",i=e?.disabledColor||"#6b7280";return e?.autoInitialize&&setTimeout(()=>{_HighlightUpdatesController.default.initialize()},1e3),{id:e?.id||"highlight-updates",name:e?.name||"TOGGLE HIGHLIGHT",description:e?.description||"Toggle component render highlights",slot:"row",icon:({size:e})=>{const[o,l]=(0,_react.useState)(()=>_HighlightUpdatesController.default.isEnabled());return(0,_react.useEffect)(()=>_HighlightUpdatesController.default.subscribe(e=>{l(e)}),[]),(0,_jsxRuntime.jsx)(_floatingToolsCore.HighlightIcon,{size:e,color:o?t:i})},component:EmptyComponent,props:{},launchMode:"toggle-only",onPress:()=>{_HighlightUpdatesController.default.isInitialized()||_HighlightUpdatesController.default.initialize(),_HighlightUpdatesController.default.toggle()}}}const highlightUpdatesModalPreset=exports.highlightUpdatesModalPreset={id:"highlight-updates-modal",name:"HIGHLIGHT",description:"View component render tracking modal",slot:"both",icon:({size:e})=>(0,_jsxRuntime.jsx)(_floatingToolsCore.HighlighterIcon,{size:e}),component:HighlightUpdatesModalWithBadgeNavigation,props:{enableSharedModalDimensions:!1}};function createHighlightUpdatesModalTool(e){const t=e?.enabledColor||"#10b981";return e?.autoInitialize&&setTimeout(()=>{_HighlightUpdatesController.default.initialize()},1e3),{id:e?.id||"highlight-updates-modal",name:e?.name||"HIGHLIGHT",description:e?.description||"View component render tracking modal",slot:"both",icon:({size:e})=>(0,_jsxRuntime.jsx)(_floatingToolsCore.HighlighterIcon,{size:e,color:t}),component:HighlightUpdatesModalWithBadgeNavigation,props:{enableSharedModalDimensions:!1}}}
|
|
@@ -1,278 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* HighlightUpdatesOverlay
|
|
5
|
-
*
|
|
6
|
-
* Renders colored highlight rectangles for components that have updated.
|
|
7
|
-
* Uses View-based rendering (similar to debug-borders) instead of the
|
|
8
|
-
* native DebuggingOverlay component for better compatibility.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import React, { useEffect, useState, useRef, useCallback, useLayoutEffect } from "react";
|
|
12
|
-
import { View, Text, StyleSheet, TouchableOpacity } from "react-native";
|
|
13
|
-
import { buoyColors } from "@buoy-gg/shared-ui";
|
|
14
|
-
import HighlightUpdatesController from "./utils/HighlightUpdatesController";
|
|
15
|
-
import { PerformanceLogger, markOverlayRendered } from "./utils/PerformanceLogger";
|
|
16
|
-
import { RenderTracker } from "./utils/RenderTracker";
|
|
17
|
-
|
|
18
|
-
// Declare performance API available in React Native's JavaScript environment
|
|
19
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
20
|
-
// How long highlights stay visible (ms)
|
|
21
|
-
const HIGHLIGHT_DURATION = 1000;
|
|
22
|
-
export function HighlightUpdatesOverlay({
|
|
23
|
-
onBadgePress
|
|
24
|
-
} = {}) {
|
|
25
|
-
const [highlights, setHighlights] = useState([]);
|
|
26
|
-
const [isFrozen, setIsFrozen] = useState(() => HighlightUpdatesController.getFrozen());
|
|
27
|
-
const [spotlightTag, setSpotlightTag] = useState(null);
|
|
28
|
-
const cleanupTimerRef = useRef(null);
|
|
29
|
-
const renderStartTimeRef = useRef(0);
|
|
30
|
-
const highlightCountRef = useRef(0);
|
|
31
|
-
const frozenRef = useRef(isFrozen);
|
|
32
|
-
|
|
33
|
-
// Keep ref in sync with state for use in interval callback
|
|
34
|
-
frozenRef.current = isFrozen;
|
|
35
|
-
|
|
36
|
-
// Track render start time
|
|
37
|
-
if (PerformanceLogger.isEnabled()) {
|
|
38
|
-
renderStartTimeRef.current = performance.now();
|
|
39
|
-
highlightCountRef.current = highlights.length;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Measure render completion time using useLayoutEffect (runs after DOM mutations)
|
|
43
|
-
useLayoutEffect(() => {
|
|
44
|
-
if (PerformanceLogger.isEnabled() && renderStartTimeRef.current > 0 && highlightCountRef.current > 0) {
|
|
45
|
-
const renderTime = performance.now() - renderStartTimeRef.current;
|
|
46
|
-
// Mark end-to-end timing (for benchmark recording only - no console logs)
|
|
47
|
-
markOverlayRendered(highlightCountRef.current, renderTime);
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
// Subscribe to freeze state changes
|
|
52
|
-
useEffect(() => {
|
|
53
|
-
const unsubscribe = HighlightUpdatesController.subscribeToFreeze(frozen => {
|
|
54
|
-
setIsFrozen(frozen);
|
|
55
|
-
});
|
|
56
|
-
return unsubscribe;
|
|
57
|
-
}, []);
|
|
58
|
-
|
|
59
|
-
// Subscribe to filter changes - refresh frozen highlights when filters change
|
|
60
|
-
useEffect(() => {
|
|
61
|
-
const unsubscribe = RenderTracker.subscribeToFilters(() => {
|
|
62
|
-
// When filters change, filter out highlights that no longer match
|
|
63
|
-
setHighlights(prev => {
|
|
64
|
-
return prev.filter(highlight => {
|
|
65
|
-
// Look up the render by nativeTag
|
|
66
|
-
const render = RenderTracker.getRender(String(highlight.id));
|
|
67
|
-
if (!render) {
|
|
68
|
-
// If render not found, keep the highlight (it might be from a different source)
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
71
|
-
// Check if the render should still be shown based on new filters
|
|
72
|
-
return RenderTracker.shouldShowRender(render);
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
return unsubscribe;
|
|
77
|
-
}, []);
|
|
78
|
-
|
|
79
|
-
// Subscribe to spotlight changes - show which component is being viewed in detail
|
|
80
|
-
useEffect(() => {
|
|
81
|
-
HighlightUpdatesController.setSpotlightCallback(tag => {
|
|
82
|
-
setSpotlightTag(tag);
|
|
83
|
-
});
|
|
84
|
-
return () => {
|
|
85
|
-
HighlightUpdatesController.setSpotlightCallback(null);
|
|
86
|
-
};
|
|
87
|
-
}, []);
|
|
88
|
-
|
|
89
|
-
// Callback to add new highlights
|
|
90
|
-
const addHighlights = useCallback(newRects => {
|
|
91
|
-
const now = Date.now();
|
|
92
|
-
const timestampedRects = newRects.map(rect => ({
|
|
93
|
-
...rect,
|
|
94
|
-
timestamp: now
|
|
95
|
-
}));
|
|
96
|
-
setHighlights(prev => {
|
|
97
|
-
// Merge new highlights, replacing any with same id
|
|
98
|
-
const updated = [...prev];
|
|
99
|
-
for (const newRect of timestampedRects) {
|
|
100
|
-
const existingIndex = updated.findIndex(r => r.id === newRect.id);
|
|
101
|
-
if (existingIndex >= 0) {
|
|
102
|
-
updated[existingIndex] = newRect;
|
|
103
|
-
} else {
|
|
104
|
-
updated.push(newRect);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return updated;
|
|
108
|
-
});
|
|
109
|
-
}, []);
|
|
110
|
-
|
|
111
|
-
// Register the callback with the controller
|
|
112
|
-
useEffect(() => {
|
|
113
|
-
HighlightUpdatesController.setHighlightCallback(addHighlights);
|
|
114
|
-
|
|
115
|
-
// Cleanup timer to remove old highlights
|
|
116
|
-
// When frozen, skip cleanup to keep highlights visible indefinitely
|
|
117
|
-
cleanupTimerRef.current = setInterval(() => {
|
|
118
|
-
// Check frozen state via ref (doesn't cause re-subscription)
|
|
119
|
-
if (frozenRef.current) {
|
|
120
|
-
return; // Skip cleanup when frozen
|
|
121
|
-
}
|
|
122
|
-
const now = Date.now();
|
|
123
|
-
setHighlights(prev => prev.filter(rect => now - rect.timestamp < HIGHLIGHT_DURATION));
|
|
124
|
-
}, 50);
|
|
125
|
-
return () => {
|
|
126
|
-
HighlightUpdatesController.setHighlightCallback(null);
|
|
127
|
-
if (cleanupTimerRef.current) {
|
|
128
|
-
clearInterval(cleanupTimerRef.current);
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
}, [addHighlights]);
|
|
132
|
-
|
|
133
|
-
// Check if badge press handling is enabled (via props or controller)
|
|
134
|
-
const hasBadgePressHandler = onBadgePress || HighlightUpdatesController.getBadgePressCallback();
|
|
135
|
-
|
|
136
|
-
// Handle badge press - navigate to detail view for this component
|
|
137
|
-
const handleBadgePress = useCallback(nativeTag => {
|
|
138
|
-
// First try the prop callback
|
|
139
|
-
if (onBadgePress) {
|
|
140
|
-
onBadgePress(nativeTag);
|
|
141
|
-
} else {
|
|
142
|
-
// Fall back to controller callback
|
|
143
|
-
HighlightUpdatesController.handleBadgePress(nativeTag);
|
|
144
|
-
}
|
|
145
|
-
}, [onBadgePress]);
|
|
146
|
-
|
|
147
|
-
// Get spotlight render info if we have a spotlight active
|
|
148
|
-
const spotlightRender = spotlightTag ? RenderTracker.getRender(String(spotlightTag)) : null;
|
|
149
|
-
|
|
150
|
-
// Render nothing if no highlights and no spotlight
|
|
151
|
-
if (highlights.length === 0 && !spotlightRender?.measurements) {
|
|
152
|
-
return null;
|
|
153
|
-
}
|
|
154
|
-
return /*#__PURE__*/_jsxs(View, {
|
|
155
|
-
style: styles.overlay,
|
|
156
|
-
pointerEvents: "box-none",
|
|
157
|
-
nativeID: "highlight-updates-overlay",
|
|
158
|
-
children: [spotlightRender?.measurements && /*#__PURE__*/_jsxs(_Fragment, {
|
|
159
|
-
children: [/*#__PURE__*/_jsx(View, {
|
|
160
|
-
pointerEvents: "none",
|
|
161
|
-
nativeID: "__spotlight_highlight__",
|
|
162
|
-
style: [styles.spotlightHighlight, {
|
|
163
|
-
// Offset by border width so border renders outside the component bounds
|
|
164
|
-
left: spotlightRender.measurements.x - 3,
|
|
165
|
-
top: spotlightRender.measurements.y - 3,
|
|
166
|
-
width: spotlightRender.measurements.width + 6,
|
|
167
|
-
height: spotlightRender.measurements.height + 6
|
|
168
|
-
}]
|
|
169
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
170
|
-
pointerEvents: "none",
|
|
171
|
-
style: [styles.spotlightLabel, {
|
|
172
|
-
left: spotlightRender.measurements.x,
|
|
173
|
-
top: spotlightRender.measurements.y + spotlightRender.measurements.height + 4
|
|
174
|
-
}],
|
|
175
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
176
|
-
style: styles.spotlightLabelText,
|
|
177
|
-
children: spotlightRender.componentName || spotlightRender.displayName || spotlightRender.viewType
|
|
178
|
-
})
|
|
179
|
-
})]
|
|
180
|
-
}), highlights.map(rect => /*#__PURE__*/_jsx(View, {
|
|
181
|
-
pointerEvents: "box-none",
|
|
182
|
-
nativeID: `__highlight_rect_${rect.id}__`,
|
|
183
|
-
style: [styles.highlight, {
|
|
184
|
-
left: rect.x,
|
|
185
|
-
top: rect.y,
|
|
186
|
-
width: rect.width,
|
|
187
|
-
height: rect.height,
|
|
188
|
-
borderColor: rect.color
|
|
189
|
-
}],
|
|
190
|
-
children: rect.count > 0 && (hasBadgePressHandler ? /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
191
|
-
onPress: () => handleBadgePress(rect.id),
|
|
192
|
-
style: [styles.badge, {
|
|
193
|
-
backgroundColor: rect.color
|
|
194
|
-
}],
|
|
195
|
-
activeOpacity: 0.7,
|
|
196
|
-
hitSlop: {
|
|
197
|
-
top: 8,
|
|
198
|
-
bottom: 8,
|
|
199
|
-
left: 8,
|
|
200
|
-
right: 8
|
|
201
|
-
},
|
|
202
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
203
|
-
style: styles.badgeText,
|
|
204
|
-
nativeID: `__highlight_text_${rect.id}__`,
|
|
205
|
-
children: rect.count
|
|
206
|
-
})
|
|
207
|
-
}) : /*#__PURE__*/_jsx(View, {
|
|
208
|
-
style: [styles.badge, {
|
|
209
|
-
backgroundColor: rect.color
|
|
210
|
-
}],
|
|
211
|
-
nativeID: `__highlight_badge_${rect.id}__`,
|
|
212
|
-
pointerEvents: "none",
|
|
213
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
214
|
-
style: styles.badgeText,
|
|
215
|
-
nativeID: `__highlight_text_${rect.id}__`,
|
|
216
|
-
children: rect.count
|
|
217
|
-
})
|
|
218
|
-
}))
|
|
219
|
-
}, `highlight-${rect.id}`))]
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
const styles = StyleSheet.create({
|
|
223
|
-
overlay: {
|
|
224
|
-
position: "absolute",
|
|
225
|
-
top: 0,
|
|
226
|
-
left: 0,
|
|
227
|
-
right: 0,
|
|
228
|
-
bottom: 0,
|
|
229
|
-
zIndex: 999999,
|
|
230
|
-
elevation: 999999,
|
|
231
|
-
borderWidth: 0
|
|
232
|
-
},
|
|
233
|
-
highlight: {
|
|
234
|
-
position: "absolute",
|
|
235
|
-
borderWidth: 2,
|
|
236
|
-
borderStyle: "solid",
|
|
237
|
-
backgroundColor: "transparent"
|
|
238
|
-
},
|
|
239
|
-
badge: {
|
|
240
|
-
position: "absolute",
|
|
241
|
-
top: 0,
|
|
242
|
-
right: 0,
|
|
243
|
-
height: 14,
|
|
244
|
-
borderRadius: 0,
|
|
245
|
-
justifyContent: "center",
|
|
246
|
-
alignItems: "center",
|
|
247
|
-
paddingHorizontal: 2
|
|
248
|
-
},
|
|
249
|
-
badgeText: {
|
|
250
|
-
color: "#000",
|
|
251
|
-
fontSize: 9,
|
|
252
|
-
fontWeight: "bold"
|
|
253
|
-
},
|
|
254
|
-
// Spotlight highlight styles
|
|
255
|
-
spotlightHighlight: {
|
|
256
|
-
position: "absolute",
|
|
257
|
-
borderWidth: 2,
|
|
258
|
-
borderStyle: "dashed",
|
|
259
|
-
borderColor: buoyColors.primary,
|
|
260
|
-
backgroundColor: "transparent"
|
|
261
|
-
},
|
|
262
|
-
spotlightLabel: {
|
|
263
|
-
position: "absolute",
|
|
264
|
-
backgroundColor: buoyColors.card,
|
|
265
|
-
borderWidth: 1,
|
|
266
|
-
borderColor: buoyColors.primary,
|
|
267
|
-
paddingHorizontal: 8,
|
|
268
|
-
paddingVertical: 3,
|
|
269
|
-
borderRadius: 4
|
|
270
|
-
},
|
|
271
|
-
spotlightLabelText: {
|
|
272
|
-
color: buoyColors.primary,
|
|
273
|
-
fontSize: 11,
|
|
274
|
-
fontWeight: "600",
|
|
275
|
-
fontFamily: "monospace"
|
|
276
|
-
}
|
|
277
|
-
});
|
|
278
|
-
export default HighlightUpdatesOverlay;
|
|
1
|
+
"use strict";import React,{useEffect,useState,useRef,useCallback,useLayoutEffect}from"react";import{View,Text,StyleSheet,TouchableOpacity}from"react-native";import{buoyColors}from"@buoy-gg/shared-ui";import HighlightUpdatesController from"./utils/HighlightUpdatesController";import{PerformanceLogger,markOverlayRendered}from"./utils/PerformanceLogger";import{RenderTracker}from"./utils/RenderTracker";import{jsx as _jsx,Fragment as _Fragment,jsxs as _jsxs}from"react/jsx-runtime";const HIGHLIGHT_DURATION=1e3;export function HighlightUpdatesOverlay({onBadgePress:e}={}){const[t,r]=useState([]),[o,l]=useState(()=>HighlightUpdatesController.getFrozen()),[s,i]=useState(null),n=useRef(null),a=useRef(0),h=useRef(0),g=useRef(o);g.current=o,PerformanceLogger.isEnabled()&&(a.current=performance.now(),h.current=t.length),useLayoutEffect(()=>{if(PerformanceLogger.isEnabled()&&a.current>0&&h.current>0){const e=performance.now()-a.current;markOverlayRendered(h.current,e)}}),useEffect(()=>HighlightUpdatesController.subscribeToFreeze(e=>{l(e)}),[]),useEffect(()=>RenderTracker.subscribeToFilters(()=>{r(e=>e.filter(e=>{const t=RenderTracker.getRender(String(e.id));return!t||RenderTracker.shouldShowRender(t)}))}),[]),useEffect(()=>(HighlightUpdatesController.setSpotlightCallback(e=>{i(e)}),()=>{HighlightUpdatesController.setSpotlightCallback(null)}),[]);const d=useCallback(e=>{const t=Date.now(),o=e.map(e=>({...e,timestamp:t}));r(e=>{const t=[...e];for(const e of o){const r=t.findIndex(t=>t.id===e.id);r>=0?t[r]=e:t.push(e)}return t})},[]);useEffect(()=>(HighlightUpdatesController.setHighlightCallback(d),n.current=setInterval(()=>{if(g.current)return;const e=Date.now();r(t=>t.filter(t=>e-t.timestamp<1e3))},50),()=>{HighlightUpdatesController.setHighlightCallback(null),n.current&&clearInterval(n.current)}),[d]);const c=e||HighlightUpdatesController.getBadgePressCallback(),u=useCallback(t=>{e?e(t):HighlightUpdatesController.handleBadgePress(t)},[e]),p=s?RenderTracker.getRender(String(s)):null;return 0!==t.length||p?.measurements?_jsxs(View,{style:styles.overlay,pointerEvents:"box-none",nativeID:"highlight-updates-overlay",children:[p?.measurements&&_jsxs(_Fragment,{children:[_jsx(View,{pointerEvents:"none",nativeID:"__spotlight_highlight__",style:[styles.spotlightHighlight,{left:p.measurements.x-3,top:p.measurements.y-3,width:p.measurements.width+6,height:p.measurements.height+6}]}),_jsx(View,{pointerEvents:"none",style:[styles.spotlightLabel,{left:p.measurements.x,top:p.measurements.y+p.measurements.height+4}],children:_jsx(Text,{style:styles.spotlightLabelText,children:p.componentName||p.displayName||p.viewType})})]}),t.map(e=>_jsx(View,{pointerEvents:"box-none",nativeID:`__highlight_rect_${e.id}__`,style:[styles.highlight,{left:e.x,top:e.y,width:e.width,height:e.height,borderColor:e.color}],children:e.count>0&&(c?_jsx(TouchableOpacity,{onPress:()=>u(e.id),style:[styles.badge,{backgroundColor:e.color}],activeOpacity:.7,hitSlop:{top:8,bottom:8,left:8,right:8},children:_jsx(Text,{style:styles.badgeText,nativeID:`__highlight_text_${e.id}__`,children:e.count})}):_jsx(View,{style:[styles.badge,{backgroundColor:e.color}],nativeID:`__highlight_badge_${e.id}__`,pointerEvents:"none",children:_jsx(Text,{style:styles.badgeText,nativeID:`__highlight_text_${e.id}__`,children:e.count})}))},`highlight-${e.id}`))]}):null}const styles=StyleSheet.create({overlay:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:999999,elevation:999999,borderWidth:0},highlight:{position:"absolute",borderWidth:2,borderStyle:"solid",backgroundColor:"transparent"},badge:{position:"absolute",top:0,right:0,height:14,borderRadius:0,justifyContent:"center",alignItems:"center",paddingHorizontal:2},badgeText:{color:"#000",fontSize:9,fontWeight:"bold"},spotlightHighlight:{position:"absolute",borderWidth:2,borderStyle:"dashed",borderColor:buoyColors.primary,backgroundColor:"transparent"},spotlightLabel:{position:"absolute",backgroundColor:buoyColors.card,borderWidth:1,borderColor:buoyColors.primary,paddingHorizontal:8,paddingVertical:3,borderRadius:4},spotlightLabelText:{color:buoyColors.primary,fontSize:11,fontWeight:"600",fontFamily:"monospace"}});export default HighlightUpdatesOverlay;
|