@buoy-gg/highlight-updates 7.0.40 → 7.0.42
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 +11 -67
- package/lib/commonjs/highlight-updates/HighlightUpdatesOverlay.js +1 -281
- package/lib/commonjs/highlight-updates/components/HighlightFilterView.js +1 -1474
- package/lib/commonjs/highlight-updates/components/HighlightUpdatesModal.js +1 -641
- package/lib/commonjs/highlight-updates/components/IdentifierBadge.js +1 -273
- package/lib/commonjs/highlight-updates/components/IsolatedRenderList.js +1 -188
- package/lib/commonjs/highlight-updates/components/ModalHeaderContent.js +1 -293
- package/lib/commonjs/highlight-updates/components/RenderCauseBadge.js +1 -508
- package/lib/commonjs/highlight-updates/components/RenderDetailView.js +1 -846
- package/lib/commonjs/highlight-updates/components/RenderHistoryViewer.js +1 -915
- package/lib/commonjs/highlight-updates/components/RenderListItem.js +1 -235
- package/lib/commonjs/highlight-updates/components/RendersCopySettingsView.js +1 -469
- package/lib/commonjs/highlight-updates/components/StatsDisplay.js +1 -73
- package/lib/commonjs/highlight-updates/types/copySettings.js +1 -107
- package/lib/commonjs/highlight-updates/utils/CommitProfiler.js +1 -446
- package/lib/commonjs/highlight-updates/utils/HighlightUpdatesController.js +1 -1920
- package/lib/commonjs/highlight-updates/utils/PerformanceLogger.js +26 -359
- package/lib/commonjs/highlight-updates/utils/ProfilerInterceptor.js +1 -371
- package/lib/commonjs/highlight-updates/utils/RenderCauseDetector.js +5 -1840
- package/lib/commonjs/highlight-updates/utils/RenderTracker.js +1 -952
- package/lib/commonjs/highlight-updates/utils/ViewTypeMapper.js +1 -264
- package/lib/commonjs/highlight-updates/utils/copySettingsStorage.js +1 -32
- package/lib/commonjs/highlight-updates/utils/devtoolsComponentNames.js +1 -188
- package/lib/commonjs/highlight-updates/utils/namedComposite.js +1 -41
- package/lib/commonjs/highlight-updates/utils/ownStateChanged.js +1 -103
- package/lib/commonjs/highlight-updates/utils/rawEventEmitter.js +1 -50
- package/lib/commonjs/highlight-updates/utils/rawEventEmitter.web.js +1 -0
- package/lib/commonjs/highlight-updates/utils/renderExportFormatter.js +1 -58
- package/lib/commonjs/highlight-updates/utils/rendersExportFormatter.js +1 -485
- package/lib/commonjs/highlight-updates/utils/screenElements.js +1 -1248
- package/lib/commonjs/highlight-updates/utils/tapMatch.js +1 -83
- package/lib/commonjs/highlight-updates/utils/testIDs.js +1 -68
- package/lib/commonjs/highlight-updates/utils/touchCapture.js +1 -277
- package/lib/commonjs/index.js +1 -429
- package/lib/commonjs/preset.js +1 -278
- package/lib/commonjs/sync/highlightUpdatesSyncAdapter.js +1 -235
- package/lib/module/highlight-updates/HighlightUpdatesOverlay.js +1 -274
- package/lib/module/highlight-updates/components/HighlightFilterView.js +1 -1468
- package/lib/module/highlight-updates/components/HighlightUpdatesModal.js +1 -634
- package/lib/module/highlight-updates/components/IdentifierBadge.js +1 -265
- package/lib/module/highlight-updates/components/IsolatedRenderList.js +1 -183
- package/lib/module/highlight-updates/components/ModalHeaderContent.js +1 -288
- package/lib/module/highlight-updates/components/RenderCauseBadge.js +1 -499
- package/lib/module/highlight-updates/components/RenderDetailView.js +1 -840
- package/lib/module/highlight-updates/components/RenderHistoryViewer.js +1 -908
- package/lib/module/highlight-updates/components/RenderListItem.js +1 -230
- package/lib/module/highlight-updates/components/RendersCopySettingsView.js +1 -465
- package/lib/module/highlight-updates/components/StatsDisplay.js +1 -70
- package/lib/module/highlight-updates/types/copySettings.js +1 -102
- package/lib/module/highlight-updates/utils/CommitProfiler.js +1 -442
- package/lib/module/highlight-updates/utils/HighlightUpdatesController.js +1 -1916
- package/lib/module/highlight-updates/utils/PerformanceLogger.js +26 -353
- package/lib/module/highlight-updates/utils/ProfilerInterceptor.js +1 -358
- package/lib/module/highlight-updates/utils/RenderCauseDetector.js +5 -1830
- package/lib/module/highlight-updates/utils/RenderTracker.js +1 -949
- package/lib/module/highlight-updates/utils/ViewTypeMapper.js +1 -255
- package/lib/module/highlight-updates/utils/copySettingsStorage.js +1 -26
- package/lib/module/highlight-updates/utils/devtoolsComponentNames.js +1 -178
- package/lib/module/highlight-updates/utils/namedComposite.js +1 -36
- package/lib/module/highlight-updates/utils/ownStateChanged.js +1 -98
- package/lib/module/highlight-updates/utils/rawEventEmitter.js +1 -46
- package/lib/module/highlight-updates/utils/rawEventEmitter.web.js +1 -0
- package/lib/module/highlight-updates/utils/renderExportFormatter.js +1 -54
- package/lib/module/highlight-updates/utils/rendersExportFormatter.js +1 -478
- package/lib/module/highlight-updates/utils/screenElements.js +1 -1242
- package/lib/module/highlight-updates/utils/tapMatch.js +1 -76
- package/lib/module/highlight-updates/utils/testIDs.js +1 -60
- package/lib/module/highlight-updates/utils/touchCapture.js +1 -270
- package/lib/module/index.js +1 -130
- package/lib/module/preset.js +1 -272
- package/lib/module/sync/highlightUpdatesSyncAdapter.js +1 -230
- package/lib/typescript/highlight-updates/utils/HighlightUpdatesController.d.ts +0 -26
- package/lib/typescript/highlight-updates/utils/rawEventEmitter.web.d.ts +3 -0
- package/lib/typescript/highlight-updates/utils/screenElements.d.ts +0 -19
- package/lib/web/index.mjs +38 -0
- package/package.json +34 -14
- 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/RendersCopySettingsView.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/components/StatsDisplay.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/types/copySettings.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/CommitProfiler.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/copySettingsStorage.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/devtoolsComponentNames.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/namedComposite.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/ownStateChanged.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/rawEventEmitter.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/renderExportFormatter.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/rendersExportFormatter.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/screenElements.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/tapMatch.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/testIDs.d.ts.map +0 -1
- package/lib/typescript/highlight-updates/utils/touchCapture.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/typescript/sync/highlightUpdatesSyncAdapter.d.ts.map +0 -1
package/lib/module/preset.js
CHANGED
|
@@ -1,272 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Pre-configured highlight updates tool for FloatingDevTools
|
|
5
|
-
*
|
|
6
|
-
* This preset provides standalone "Highlight updates when components render"
|
|
7
|
-
* functionality. Tap the icon to toggle highlights on/off.
|
|
8
|
-
*
|
|
9
|
-
* The overlay is automatically rendered by FloatingDevTools when the
|
|
10
|
-
* @buoy-gg/highlight-updates package is installed.
|
|
11
|
-
*
|
|
12
|
-
* Two presets available:
|
|
13
|
-
* - highlightUpdatesPreset: Quick toggle (no modal)
|
|
14
|
-
* - highlightUpdatesModalPreset: Full modal with filters and render list
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```tsx
|
|
18
|
-
* import { highlightUpdatesPreset, highlightUpdatesModalPreset } from '@buoy-gg/highlight-updates';
|
|
19
|
-
*
|
|
20
|
-
* // Toggle-only: Just tap to enable/disable highlighting
|
|
21
|
-
* <FloatingDevTools apps={[highlightUpdatesPreset]} />
|
|
22
|
-
*
|
|
23
|
-
* // Modal: Opens interface with filters, render list, and controls
|
|
24
|
-
* <FloatingDevTools apps={[highlightUpdatesModalPreset]} />
|
|
25
|
-
* ```
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
import React, { useState, useEffect, useCallback } from "react";
|
|
29
|
-
import { HighlighterIcon, HighlightIcon as HighlightIconBase } from "@buoy-gg/floating-tools-core";
|
|
30
|
-
import HighlightUpdatesController from "./highlight-updates/utils/HighlightUpdatesController";
|
|
31
|
-
import { HighlightUpdatesModal } from "./highlight-updates/components/HighlightUpdatesModal";
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Icon component that changes color based on enabled state.
|
|
35
|
-
*
|
|
36
|
-
* ⚠️ IMPORTANT - DO NOT MODIFY THIS COMPONENT ⚠️
|
|
37
|
-
* This component MUST use useState and useEffect hooks to subscribe to the controller.
|
|
38
|
-
* It is rendered as a JSX component (<IconComponent />) in FloatingMenu and DialIcon,
|
|
39
|
-
* which allows hooks to work properly.
|
|
40
|
-
*
|
|
41
|
-
* If you remove the hooks or change this to read isEnabled() directly,
|
|
42
|
-
* the icon color will NOT update when the toggle is pressed.
|
|
43
|
-
*/
|
|
44
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
45
|
-
function HighlightIcon({
|
|
46
|
-
size
|
|
47
|
-
}) {
|
|
48
|
-
const [enabled, setEnabled] = useState(() => HighlightUpdatesController.isEnabled());
|
|
49
|
-
useEffect(() => {
|
|
50
|
-
const unsubscribe = HighlightUpdatesController.subscribe(isEnabled => {
|
|
51
|
-
setEnabled(isEnabled);
|
|
52
|
-
});
|
|
53
|
-
return unsubscribe;
|
|
54
|
-
}, []);
|
|
55
|
-
return /*#__PURE__*/_jsx(HighlightIconBase, {
|
|
56
|
-
size: size,
|
|
57
|
-
color: enabled ? "#10b981" : "#6b7280"
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Empty component for toggle-only tools (no modal needed)
|
|
63
|
-
* The actual overlay is rendered by FloatingDevTools automatically
|
|
64
|
-
*/
|
|
65
|
-
function EmptyComponent() {
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Wrapper component for the modal that handles badge press navigation.
|
|
71
|
-
* Registers a callback with the controller to receive badge press events
|
|
72
|
-
* and passes the target nativeTag to the modal for deep linking.
|
|
73
|
-
*/
|
|
74
|
-
function HighlightUpdatesModalWithBadgeNavigation(props) {
|
|
75
|
-
const [targetNativeTag, setTargetNativeTag] = useState(null);
|
|
76
|
-
|
|
77
|
-
// Register badge press callback when modal is visible
|
|
78
|
-
useEffect(() => {
|
|
79
|
-
if (props.visible) {
|
|
80
|
-
// Register callback to handle badge presses
|
|
81
|
-
HighlightUpdatesController.setBadgePressCallback(nativeTag => {
|
|
82
|
-
setTargetNativeTag(nativeTag);
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
return () => {
|
|
86
|
-
// Clear callback when modal is closed or unmounted
|
|
87
|
-
if (!props.visible) {
|
|
88
|
-
HighlightUpdatesController.setBadgePressCallback(null);
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
}, [props.visible]);
|
|
92
|
-
|
|
93
|
-
// Clear the target after it's been handled
|
|
94
|
-
const handleInitialNativeTagHandled = useCallback(() => {
|
|
95
|
-
setTargetNativeTag(null);
|
|
96
|
-
}, []);
|
|
97
|
-
return /*#__PURE__*/_jsx(HighlightUpdatesModal, {
|
|
98
|
-
...props,
|
|
99
|
-
initialNativeTag: targetNativeTag,
|
|
100
|
-
onInitialNativeTagHandled: handleInitialNativeTagHandled
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Pre-configured highlight updates tool for FloatingDevTools.
|
|
106
|
-
* Tap the icon to toggle component render highlighting on/off.
|
|
107
|
-
*
|
|
108
|
-
* Features:
|
|
109
|
-
* - Standalone implementation - no DevTools connection required
|
|
110
|
-
* - Simple direct toggle (no modal)
|
|
111
|
-
* - Icon changes color: gray when off, green when on
|
|
112
|
-
* - Overlay auto-rendered by FloatingDevTools
|
|
113
|
-
*/
|
|
114
|
-
export const highlightUpdatesPreset = {
|
|
115
|
-
id: "highlight-updates",
|
|
116
|
-
name: "TOGGLE HIGHLIGHT",
|
|
117
|
-
description: "Toggle component render highlights",
|
|
118
|
-
slot: "row",
|
|
119
|
-
icon: HighlightIcon,
|
|
120
|
-
component: EmptyComponent,
|
|
121
|
-
props: {},
|
|
122
|
-
launchMode: "toggle-only",
|
|
123
|
-
onPress: () => {
|
|
124
|
-
// Initialize on first press if not already initialized
|
|
125
|
-
if (!HighlightUpdatesController.isInitialized()) {
|
|
126
|
-
HighlightUpdatesController.initialize();
|
|
127
|
-
}
|
|
128
|
-
HighlightUpdatesController.toggle();
|
|
129
|
-
// Icon updates automatically via subscription in HighlightIcon component
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Create a custom highlight updates tool configuration.
|
|
135
|
-
* Use this if you want to override default settings.
|
|
136
|
-
*
|
|
137
|
-
* @example
|
|
138
|
-
* ```tsx
|
|
139
|
-
* import { createHighlightUpdatesTool } from '@buoy-gg/highlight-updates';
|
|
140
|
-
*
|
|
141
|
-
* const myHighlightTool = createHighlightUpdatesTool({
|
|
142
|
-
* name: "RENDERS",
|
|
143
|
-
* enabledColor: "#ec4899",
|
|
144
|
-
* disabledColor: "#9ca3af",
|
|
145
|
-
* autoInitialize: true,
|
|
146
|
-
* });
|
|
147
|
-
* ```
|
|
148
|
-
*/
|
|
149
|
-
export function createHighlightUpdatesTool(options) {
|
|
150
|
-
const enabledColor = options?.enabledColor || "#10b981";
|
|
151
|
-
const disabledColor = options?.disabledColor || "#6b7280";
|
|
152
|
-
|
|
153
|
-
// Auto-initialize if requested
|
|
154
|
-
if (options?.autoInitialize) {
|
|
155
|
-
// Delay to allow DevTools to connect
|
|
156
|
-
setTimeout(() => {
|
|
157
|
-
HighlightUpdatesController.initialize();
|
|
158
|
-
}, 1000);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Custom icon component with hooks - rendered as JSX component.
|
|
163
|
-
*
|
|
164
|
-
* ⚠️ IMPORTANT - DO NOT MODIFY THIS COMPONENT ⚠️
|
|
165
|
-
* This component MUST use useState and useEffect hooks to subscribe to the controller.
|
|
166
|
-
* See the comment on HighlightIcon above for full explanation.
|
|
167
|
-
*/
|
|
168
|
-
const CustomHighlightIcon = ({
|
|
169
|
-
size
|
|
170
|
-
}) => {
|
|
171
|
-
const [enabled, setEnabled] = useState(() => HighlightUpdatesController.isEnabled());
|
|
172
|
-
useEffect(() => {
|
|
173
|
-
const unsubscribe = HighlightUpdatesController.subscribe(isEnabled => {
|
|
174
|
-
setEnabled(isEnabled);
|
|
175
|
-
});
|
|
176
|
-
return unsubscribe;
|
|
177
|
-
}, []);
|
|
178
|
-
return /*#__PURE__*/_jsx(HighlightIconBase, {
|
|
179
|
-
size: size,
|
|
180
|
-
color: enabled ? enabledColor : disabledColor
|
|
181
|
-
});
|
|
182
|
-
};
|
|
183
|
-
return {
|
|
184
|
-
id: options?.id || "highlight-updates",
|
|
185
|
-
name: options?.name || "TOGGLE HIGHLIGHT",
|
|
186
|
-
description: options?.description || "Toggle component render highlights",
|
|
187
|
-
slot: "row",
|
|
188
|
-
icon: CustomHighlightIcon,
|
|
189
|
-
component: EmptyComponent,
|
|
190
|
-
props: {},
|
|
191
|
-
launchMode: "toggle-only",
|
|
192
|
-
onPress: () => {
|
|
193
|
-
// Initialize on first press if not already initialized
|
|
194
|
-
if (!HighlightUpdatesController.isInitialized()) {
|
|
195
|
-
HighlightUpdatesController.initialize();
|
|
196
|
-
}
|
|
197
|
-
HighlightUpdatesController.toggle();
|
|
198
|
-
// Icon updates automatically via subscription
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Modal preset for highlight updates tool.
|
|
205
|
-
* Opens a full modal interface with:
|
|
206
|
-
* - List of tracked component renders
|
|
207
|
-
* - Start/Stop and Pause/Resume controls
|
|
208
|
-
* - Clear button to reset render counts
|
|
209
|
-
* - Search bar in navbar (expandable)
|
|
210
|
-
* - Filter by viewType, testID, nativeID, componentName
|
|
211
|
-
* - Tap overlay badge to jump to component detail view
|
|
212
|
-
*
|
|
213
|
-
* Use this preset when you want detailed render tracking and filtering.
|
|
214
|
-
*/
|
|
215
|
-
export const highlightUpdatesModalPreset = {
|
|
216
|
-
id: "highlight-updates-modal",
|
|
217
|
-
name: "HIGHLIGHT",
|
|
218
|
-
description: "View component render tracking modal",
|
|
219
|
-
slot: "both",
|
|
220
|
-
icon: ({
|
|
221
|
-
size
|
|
222
|
-
}) => /*#__PURE__*/_jsx(HighlighterIcon, {
|
|
223
|
-
size: size
|
|
224
|
-
}),
|
|
225
|
-
component: HighlightUpdatesModalWithBadgeNavigation,
|
|
226
|
-
props: {
|
|
227
|
-
enableSharedModalDimensions: false
|
|
228
|
-
}
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Create a custom highlight updates modal tool configuration.
|
|
233
|
-
* Use this if you want to override default settings for the modal version.
|
|
234
|
-
*
|
|
235
|
-
* @example
|
|
236
|
-
* ```tsx
|
|
237
|
-
* import { createHighlightUpdatesModalTool } from '@buoy-gg/highlight-updates';
|
|
238
|
-
*
|
|
239
|
-
* const myRendersTool = createHighlightUpdatesModalTool({
|
|
240
|
-
* name: "PROFILER",
|
|
241
|
-
* enabledColor: "#8b5cf6",
|
|
242
|
-
* disabledColor: "#9ca3af",
|
|
243
|
-
* });
|
|
244
|
-
* ```
|
|
245
|
-
*/
|
|
246
|
-
export function createHighlightUpdatesModalTool(options) {
|
|
247
|
-
const enabledColor = options?.enabledColor || "#10b981";
|
|
248
|
-
const disabledColor = options?.disabledColor || "#6b7280";
|
|
249
|
-
|
|
250
|
-
// Auto-initialize if requested
|
|
251
|
-
if (options?.autoInitialize) {
|
|
252
|
-
setTimeout(() => {
|
|
253
|
-
HighlightUpdatesController.initialize();
|
|
254
|
-
}, 1000);
|
|
255
|
-
}
|
|
256
|
-
return {
|
|
257
|
-
id: options?.id || "highlight-updates-modal",
|
|
258
|
-
name: options?.name || "HIGHLIGHT",
|
|
259
|
-
description: options?.description || "View component render tracking modal",
|
|
260
|
-
slot: "both",
|
|
261
|
-
icon: ({
|
|
262
|
-
size
|
|
263
|
-
}) => /*#__PURE__*/_jsx(HighlighterIcon, {
|
|
264
|
-
size: size,
|
|
265
|
-
color: enabledColor
|
|
266
|
-
}),
|
|
267
|
-
component: HighlightUpdatesModalWithBadgeNavigation,
|
|
268
|
-
props: {
|
|
269
|
-
enableSharedModalDimensions: false
|
|
270
|
-
}
|
|
271
|
-
};
|
|
272
|
-
}
|
|
1
|
+
"use strict";import C,{useState as s,useEffect as r,useCallback as H}from"react";import{HighlighterIcon as d,HighlightIcon as g}from"@buoy-gg/floating-tools-core";import i from"./highlight-updates/utils/HighlightUpdatesController";import{HighlightUpdatesModal as f}from"./highlight-updates/components/HighlightUpdatesModal";import{jsx as a}from"react/jsx-runtime";function I({size:e}){const[t,o]=s(()=>i.isEnabled());r(()=>{const n=i.subscribe(l=>{o(l)});return n},[]);return a(g,{size:e,color:t?"#10b981":"#6b7280"})}function c(){return null}function h(e){const[t,o]=s(null);r(()=>{if(e.visible){i.setBadgePressCallback(l=>{o(l)})}return()=>{if(!e.visible){i.setBadgePressCallback(null)}}},[e.visible]);const n=H(()=>{o(null)},[]);return a(f,{...e,initialNativeTag:t,onInitialNativeTagHandled:n})}export const highlightUpdatesPreset={id:"highlight-updates",name:"TOGGLE HIGHLIGHT",description:"Toggle component render highlights",slot:"row",icon:I,component:c,props:{},launchMode:"toggle-only",onPress:()=>{if(!i.isInitialized()){i.initialize()}i.toggle()}};export function createHighlightUpdatesTool(e){const t=e?.enabledColor||"#10b981";const o=e?.disabledColor||"#6b7280";if(e?.autoInitialize){setTimeout(()=>{i.initialize()},1e3)}const n=({size:l})=>{const[u,b]=s(()=>i.isEnabled());r(()=>{const m=i.subscribe(p=>{b(p)});return m},[]);return a(g,{size:l,color:u?t:o})};return{id:e?.id||"highlight-updates",name:e?.name||"TOGGLE HIGHLIGHT",description:e?.description||"Toggle component render highlights",slot:"row",icon:n,component:c,props:{},launchMode:"toggle-only",onPress:()=>{if(!i.isInitialized()){i.initialize()}i.toggle()}}}export const highlightUpdatesModalPreset={id:"highlight-updates-modal",name:"HIGHLIGHT",description:"View component render tracking modal",slot:"both",icon:({size:e})=>a(d,{size:e}),component:h,props:{enableSharedModalDimensions:false}};export function createHighlightUpdatesModalTool(e){const t=e?.enabledColor||"#10b981";const o=e?.disabledColor||"#6b7280";if(e?.autoInitialize){setTimeout(()=>{i.initialize()},1e3)}return{id:e?.id||"highlight-updates-modal",name:e?.name||"HIGHLIGHT",description:e?.description||"View component render tracking modal",slot:"both",icon:({size:n})=>a(d,{size:n,color:t}),component:h,props:{enableSharedModalDimensions:false}}}
|
|
@@ -1,230 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import HighlightUpdatesController from "../highlight-updates/utils/HighlightUpdatesController";
|
|
4
|
-
import { RenderTracker } from "../highlight-updates/utils/RenderTracker";
|
|
5
|
-
import { describeScreen, tapElement, waitFor } from "../highlight-updates/utils/screenElements";
|
|
6
|
-
import { clearTouchCapture, getTouchCaptureStatus, readTouchCapture, startTouchCapture, stopTouchCapture } from "../highlight-updates/utils/touchCapture";
|
|
7
|
-
import { CommitProfiler } from "../highlight-updates/utils/CommitProfiler";
|
|
8
|
-
function ensureInitialized() {
|
|
9
|
-
if (!HighlightUpdatesController.isInitialized()) {
|
|
10
|
-
HighlightUpdatesController.initialize();
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
function toWireCause(cause) {
|
|
14
|
-
if (!cause) return undefined;
|
|
15
|
-
const {
|
|
16
|
-
hookChanges: _hookChanges,
|
|
17
|
-
...rest
|
|
18
|
-
} = cause;
|
|
19
|
-
return rest;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Wire-form render: keep identity + counts + last cause type, drop the
|
|
24
|
-
* per-component history buffer (up to 20 events, and hook/prop snapshots
|
|
25
|
-
* when those settings are on). Dashboards fetch history via getRenderDetail.
|
|
26
|
-
*/
|
|
27
|
-
function toWireRender(render) {
|
|
28
|
-
const {
|
|
29
|
-
renderHistory,
|
|
30
|
-
lastRenderCause,
|
|
31
|
-
...rest
|
|
32
|
-
} = render;
|
|
33
|
-
return {
|
|
34
|
-
...rest,
|
|
35
|
-
lastRenderCause: toWireCause(lastRenderCause),
|
|
36
|
-
historyCount: renderHistory?.length ?? 0
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Deliberately serializes to test serializability, unlike the snapshot guards
|
|
42
|
-
* elsewhere. This runs once per `getRenderDetail` — a user clicking one row —
|
|
43
|
-
* not on the ~5x/sec snapshot, so there is no unbounded per-tick cost to
|
|
44
|
-
* avoid. Probing with a size walk first would just traverse the whole render
|
|
45
|
-
* before doing this anyway.
|
|
46
|
-
*/
|
|
47
|
-
function jsonSafeRender(render) {
|
|
48
|
-
try {
|
|
49
|
-
JSON.stringify(render);
|
|
50
|
-
return render;
|
|
51
|
-
} catch {
|
|
52
|
-
return {
|
|
53
|
-
...render,
|
|
54
|
-
lastRenderCause: toWireCause(render.lastRenderCause),
|
|
55
|
-
renderHistory: render.renderHistory?.map(event => ({
|
|
56
|
-
...event,
|
|
57
|
-
capturedProps: undefined,
|
|
58
|
-
capturedState: undefined,
|
|
59
|
-
cause: toWireCause(event.cause) ?? event.cause
|
|
60
|
-
}))
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Measurement window for automated callers (MCP `measure_renders`).
|
|
67
|
-
*
|
|
68
|
-
* Backed by CommitProfiler, NOT the RenderTracker that feeds the overlay, and
|
|
69
|
-
* the difference is the whole point. RenderTracker tracks HOST VIEWS: ask it
|
|
70
|
-
* why `DealRow` re-rendered and it answers about the native `View` inside it —
|
|
71
|
-
* "props changed: accessibilityState, accessibilityValue" — which is true and
|
|
72
|
-
* useless. CommitProfiler walks COMPOSITE fibers, so it answers about the
|
|
73
|
-
* component you named: which of ITS props changed, whether they changed by
|
|
74
|
-
* value or only by identity, and which parent dragged it along.
|
|
75
|
-
*
|
|
76
|
-
* It also touches none of the user's overlay state — no enabling, no clearing
|
|
77
|
-
* counters someone was collecting, nothing drawn on screen. A measurement is
|
|
78
|
-
* invisible.
|
|
79
|
-
*/
|
|
80
|
-
function beginMeasurement() {
|
|
81
|
-
if (!CommitProfiler.isSupported()) {
|
|
82
|
-
return {
|
|
83
|
-
ok: false,
|
|
84
|
-
reason: "render capture needs a dev build with the React DevTools hook available"
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
CommitProfiler.startCapture({
|
|
88
|
-
detail: true
|
|
89
|
-
});
|
|
90
|
-
return {
|
|
91
|
-
ok: true
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
function endMeasurement() {
|
|
95
|
-
return {
|
|
96
|
-
summary: CommitProfiler.stopCapture()
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Sync adapter for the highlight-updates tool, consumed by
|
|
102
|
-
* @buoy-gg/external-sync's `useExternalSync` (structurally matches its
|
|
103
|
-
* ToolSyncAdapter interface so this package doesn't need a dependency on it).
|
|
104
|
-
*
|
|
105
|
-
* The visual highlights draw on the DEVICE's UI, but the render-tracking
|
|
106
|
-
* data (component list, render counts, causes, history) is plain data — the
|
|
107
|
-
* snapshot carries it so the dashboard renders the real HighlightUpdatesModal
|
|
108
|
-
* as a mirror. Mutations (toggle, freeze, clear, spotlight) come back as
|
|
109
|
-
* actions and run on the device; spotlight even highlights the component on
|
|
110
|
-
* the phone screen while browsing details from the desktop.
|
|
111
|
-
*
|
|
112
|
-
* v2: per-component `renderHistory` (and hook-change values on lastRenderCause)
|
|
113
|
-
* stay on the device. Dashboards fetch them via `getRenderDetail`.
|
|
114
|
-
*/
|
|
115
|
-
export const highlightUpdatesSyncAdapter = {
|
|
116
|
-
// v3: beginMeasurement / endMeasurement — a CommitProfiler capture window
|
|
117
|
-
// for automated callers, with per-component causes. Invisible to the user.
|
|
118
|
-
version: 3,
|
|
119
|
-
getSnapshot: () => ({
|
|
120
|
-
enabled: HighlightUpdatesController.isEnabled(),
|
|
121
|
-
frozen: HighlightUpdatesController.getFrozen(),
|
|
122
|
-
// True while tracking but the visual boxes are hidden (screenshot tool).
|
|
123
|
-
highlightsSuppressed: HighlightUpdatesController.getHighlightsSuppressed(),
|
|
124
|
-
renders: RenderTracker.getRenders().map(toWireRender),
|
|
125
|
-
trackerState: RenderTracker.getState()
|
|
126
|
-
}),
|
|
127
|
-
subscribe: onChange => {
|
|
128
|
-
const unsubscribeEnabled = HighlightUpdatesController.subscribe(onChange);
|
|
129
|
-
const unsubscribeFreeze = HighlightUpdatesController.subscribeToFreeze(onChange);
|
|
130
|
-
const unsubscribeRenders = RenderTracker.subscribe(onChange);
|
|
131
|
-
const unsubscribeTrackerState = RenderTracker.subscribeToState(onChange);
|
|
132
|
-
return () => {
|
|
133
|
-
unsubscribeEnabled();
|
|
134
|
-
unsubscribeFreeze();
|
|
135
|
-
unsubscribeRenders();
|
|
136
|
-
unsubscribeTrackerState();
|
|
137
|
-
};
|
|
138
|
-
},
|
|
139
|
-
actions: {
|
|
140
|
-
// Capture window for automated callers (MCP `measure_renders`). Pairs:
|
|
141
|
-
// begin -> drive the UI -> end. `end` always restores.
|
|
142
|
-
beginMeasurement: () => beginMeasurement(),
|
|
143
|
-
endMeasurement: () => endMeasurement(),
|
|
144
|
-
/**
|
|
145
|
-
* On-demand detail: one component's real renderHistory + lastRenderCause
|
|
146
|
-
* (including hookChanges). Wire-form snapshots omit those.
|
|
147
|
-
*/
|
|
148
|
-
getRenderDetail: params => {
|
|
149
|
-
const {
|
|
150
|
-
nativeTag
|
|
151
|
-
} = params ?? {};
|
|
152
|
-
if (nativeTag == null) {
|
|
153
|
-
return {
|
|
154
|
-
found: false,
|
|
155
|
-
reason: "missing nativeTag"
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
const render = RenderTracker.getRender(String(nativeTag));
|
|
159
|
-
if (!render) return {
|
|
160
|
-
found: false,
|
|
161
|
-
reason: "unknown nativeTag"
|
|
162
|
-
};
|
|
163
|
-
return {
|
|
164
|
-
found: true,
|
|
165
|
-
nativeTag,
|
|
166
|
-
render: jsonSafeRender(render)
|
|
167
|
-
};
|
|
168
|
-
},
|
|
169
|
-
toggle: () => {
|
|
170
|
-
ensureInitialized();
|
|
171
|
-
HighlightUpdatesController.toggle();
|
|
172
|
-
},
|
|
173
|
-
setEnabled: params => {
|
|
174
|
-
ensureInitialized();
|
|
175
|
-
HighlightUpdatesController.setEnabled(params.enabled);
|
|
176
|
-
},
|
|
177
|
-
toggleFreeze: () => {
|
|
178
|
-
HighlightUpdatesController.toggleFreeze();
|
|
179
|
-
},
|
|
180
|
-
clearRenderCounts: () => {
|
|
181
|
-
HighlightUpdatesController.clearRenderCounts();
|
|
182
|
-
},
|
|
183
|
-
setSpotlight: params => {
|
|
184
|
-
HighlightUpdatesController.setSpotlight(params.nativeTag);
|
|
185
|
-
},
|
|
186
|
-
// Resolve a component (by testID/nativeID/name/nativeTag) to a fresh
|
|
187
|
-
// on-screen rectangle — best-effort scrolling it into view first — so the
|
|
188
|
-
// desktop can crop a simulator screenshot to exactly that component. The
|
|
189
|
-
// returned value (rect + scale + screen) flows back as the action result.
|
|
190
|
-
locateComponent: params => {
|
|
191
|
-
ensureInitialized();
|
|
192
|
-
return HighlightUpdatesController.locateComponent(params ?? {});
|
|
193
|
-
},
|
|
194
|
-
// Track + measure components WITHOUT drawing the highlight boxes, so the
|
|
195
|
-
// desktop screenshot tool can locate components with no on-device overlay.
|
|
196
|
-
setSilentTracking: params => {
|
|
197
|
-
ensureInitialized();
|
|
198
|
-
HighlightUpdatesController.setSilentTracking(params.enabled ?? false);
|
|
199
|
-
},
|
|
200
|
-
// Walk the live fiber tree and return the current screen's meaningful /
|
|
201
|
-
// interactive elements, each with normalized tap coordinates. Powers the
|
|
202
|
-
// MCP `describe_screen` reader — no screenshot, no silent-tracking needed.
|
|
203
|
-
describeScreen: params => describeScreen(params ?? {}),
|
|
204
|
-
// Tap an element purely in JS: resolve it (by nativeTag / testID / query),
|
|
205
|
-
// find the nearest onPress up its fiber chain, and invoke it with a
|
|
206
|
-
// synthetic press event. Powers the MCP `tap_element` action.
|
|
207
|
-
tapElement: params => tapElement(params ?? {}),
|
|
208
|
-
// Block until an element is on screen (or gone), so a driver can act on a
|
|
209
|
-
// screen that has finished loading instead of the skeleton that was there
|
|
210
|
-
// when `navigate` returned. Same matcher `tapElement` ranks by.
|
|
211
|
-
waitFor: params => waitFor(params ?? {}),
|
|
212
|
-
// ── Touch capture: the recording half of tapElement ──────────────────
|
|
213
|
-
// Observe what a HUMAN taps, named in the same vocabulary tapElement
|
|
214
|
-
// searches by, so the Scenarios recorder can turn a real session into a
|
|
215
|
-
// replayable macro. Lives here because this tool already owns the fiber
|
|
216
|
-
// walk both halves need.
|
|
217
|
-
startTouchCapture: () => startTouchCapture(),
|
|
218
|
-
stopTouchCapture: () => {
|
|
219
|
-
stopTouchCapture();
|
|
220
|
-
return getTouchCaptureStatus();
|
|
221
|
-
},
|
|
222
|
-
clearTouchCapture: () => {
|
|
223
|
-
clearTouchCapture();
|
|
224
|
-
return {
|
|
225
|
-
ok: true
|
|
226
|
-
};
|
|
227
|
-
},
|
|
228
|
-
readTouchCapture: params => readTouchCapture(params?.sinceSeq ?? 0)
|
|
229
|
-
}
|
|
230
|
-
};
|
|
1
|
+
"use strict";import t from"../highlight-updates/utils/HighlightUpdatesController";import{RenderTracker as s}from"../highlight-updates/utils/RenderTracker";import{describeScreen as d,tapElement as l,waitFor as p}from"../highlight-updates/utils/screenElements";import{clearTouchCapture as g,getTouchCaptureStatus as b,readTouchCapture as f,startTouchCapture as h,stopTouchCapture as m}from"../highlight-updates/utils/touchCapture";import{CommitProfiler as o}from"../highlight-updates/utils/CommitProfiler";function a(){if(!t.isInitialized()){t.initialize()}}function i(e){if(!e)return void 0;const{hookChanges:r,...n}=e;return n}function C(e){const{renderHistory:r,lastRenderCause:n,...u}=e;return{...u,lastRenderCause:i(n),historyCount:r?.length??0}}function S(e){try{JSON.stringify(e);return e}catch{return{...e,lastRenderCause:i(e.lastRenderCause),renderHistory:e.renderHistory?.map(r=>({...r,capturedProps:void 0,capturedState:void 0,cause:i(r.cause)??r.cause}))}}}function T(){if(!o.isSupported()){return{ok:false,reason:"render capture needs a dev build with the React DevTools hook available"}}o.startCapture({detail:true});return{ok:true}}function R(){return{summary:o.stopCapture()}}export const highlightUpdatesSyncAdapter={version:3,getSnapshot:()=>({enabled:t.isEnabled(),frozen:t.getFrozen(),highlightsSuppressed:t.getHighlightsSuppressed(),renders:s.getRenders().map(C),trackerState:s.getState()}),subscribe:e=>{const r=t.subscribe(e);const n=t.subscribeToFreeze(e);const u=s.subscribe(e);const c=s.subscribeToState(e);return()=>{r();n();u();c()}},actions:{beginMeasurement:()=>T(),endMeasurement:()=>R(),getRenderDetail:e=>{const{nativeTag:r}=e??{};if(r==null){return{found:false,reason:"missing nativeTag"}}const n=s.getRender(String(r));if(!n)return{found:false,reason:"unknown nativeTag"};return{found:true,nativeTag:r,render:S(n)}},toggle:()=>{a();t.toggle()},setEnabled:e=>{a();t.setEnabled(e.enabled)},toggleFreeze:()=>{t.toggleFreeze()},clearRenderCounts:()=>{t.clearRenderCounts()},setSpotlight:e=>{t.setSpotlight(e.nativeTag)},locateComponent:e=>{a();return t.locateComponent(e??{})},setSilentTracking:e=>{a();t.setSilentTracking(e.enabled??false)},describeScreen:e=>d(e??{}),tapElement:e=>l(e??{}),waitFor:e=>p(e??{}),startTouchCapture:()=>h(),stopTouchCapture:()=>{m();return b()},clearTouchCapture:()=>{g();return{ok:true}},readTouchCapture:e=>f(e?.sinceSeq??0)}};
|
|
@@ -1,29 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Highlight Updates Controller
|
|
3
|
-
*
|
|
4
|
-
* Standalone implementation that replicates React DevTools' "Highlight updates
|
|
5
|
-
* when components render" feature WITHOUT requiring DevTools to be connected.
|
|
6
|
-
*
|
|
7
|
-
* Architecture:
|
|
8
|
-
* This controller directly enables the DevTools backend's traceUpdates feature
|
|
9
|
-
* by calling setTraceUpdatesEnabled(true) on each renderer interface. This is
|
|
10
|
-
* the same function that DevTools' frontend calls when you check the
|
|
11
|
-
* "Highlight updates when components render" checkbox.
|
|
12
|
-
*
|
|
13
|
-
* Key insight: The rendererInterfaces are available on the global hook even
|
|
14
|
-
* without DevTools frontend connected. We just need to enable tracing directly.
|
|
15
|
-
*
|
|
16
|
-
* Flow:
|
|
17
|
-
* 1. User enables highlights via toggle()
|
|
18
|
-
* 2. We call rendererInterface.setTraceUpdatesEnabled(true) on all renderers
|
|
19
|
-
* 3. DevTools backend now tracks renders and emits 'traceUpdates' events
|
|
20
|
-
* 4. We subscribe to 'traceUpdates' via hook.sub()
|
|
21
|
-
* 5. When components re-render, we receive the Set of host stateNodes
|
|
22
|
-
* 6. We measure each node and render colored border highlights
|
|
23
|
-
*
|
|
24
|
-
* This gives us 100% accuracy with DevTools behavior because we're using the
|
|
25
|
-
* exact same detection code - we're just enabling it programmatically.
|
|
26
|
-
*/
|
|
27
1
|
interface HighlightRect {
|
|
28
2
|
id: number;
|
|
29
3
|
x: number;
|
|
@@ -1,22 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* On-device screen element discovery + in-JS tap.
|
|
3
|
-
*
|
|
4
|
-
* This powers the MCP "describe_screen" / "tap_element" tools. It walks the
|
|
5
|
-
* live React fiber tree (all renderers), collects the meaningful / interactive
|
|
6
|
-
* elements on the current screen, and measures each one's on-screen rect — the
|
|
7
|
-
* same idea as the desktop screenshot tool's component-locate, but producing a
|
|
8
|
-
* whole-screen list with normalized tap coordinates instead of a single crop.
|
|
9
|
-
*
|
|
10
|
-
* Tapping is done PURELY in JS: we resolve the target element, find the nearest
|
|
11
|
-
* `onPress` handler up its fiber chain, and invoke it with a synthetic press
|
|
12
|
-
* event. No screenshots, no OS-level touch injection, and it works on physical
|
|
13
|
-
* devices — because Buoy runs INSIDE the app (unlike external simulator drivers
|
|
14
|
-
* that have to inject an OS touch at a pixel coordinate).
|
|
15
|
-
*
|
|
16
|
-
* Fiber traversal is adapted from image-overlay/utils/fiberScanner.ts and
|
|
17
|
-
* debug-borders/utils/fiberTreeTraversal.js; the fiber-access triad matches the
|
|
18
|
-
* rest of highlight-updates (Fabric / Paper / RN-CLI-dev).
|
|
19
|
-
*/
|
|
20
1
|
export interface ScreenElement {
|
|
21
2
|
nativeTag: number | null;
|
|
22
3
|
name: string;
|