@buoy-gg/highlight-updates 7.0.41 → 7.0.43

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.
Files changed (108) hide show
  1. package/README.md +11 -71
  2. package/lib/commonjs/highlight-updates/HighlightUpdatesOverlay.js +1 -281
  3. package/lib/commonjs/highlight-updates/components/HighlightFilterView.js +1 -1474
  4. package/lib/commonjs/highlight-updates/components/HighlightUpdatesModal.js +1 -641
  5. package/lib/commonjs/highlight-updates/components/IdentifierBadge.js +1 -273
  6. package/lib/commonjs/highlight-updates/components/IsolatedRenderList.js +1 -188
  7. package/lib/commonjs/highlight-updates/components/ModalHeaderContent.js +1 -293
  8. package/lib/commonjs/highlight-updates/components/RenderCauseBadge.js +1 -508
  9. package/lib/commonjs/highlight-updates/components/RenderDetailView.js +1 -846
  10. package/lib/commonjs/highlight-updates/components/RenderHistoryViewer.js +1 -915
  11. package/lib/commonjs/highlight-updates/components/RenderListItem.js +1 -235
  12. package/lib/commonjs/highlight-updates/components/RendersCopySettingsView.js +1 -469
  13. package/lib/commonjs/highlight-updates/components/StatsDisplay.js +1 -73
  14. package/lib/commonjs/highlight-updates/types/copySettings.js +1 -107
  15. package/lib/commonjs/highlight-updates/utils/CommitProfiler.js +1 -455
  16. package/lib/commonjs/highlight-updates/utils/HighlightUpdatesController.js +1 -1929
  17. package/lib/commonjs/highlight-updates/utils/PerformanceLogger.js +26 -359
  18. package/lib/commonjs/highlight-updates/utils/ProfilerInterceptor.js +1 -371
  19. package/lib/commonjs/highlight-updates/utils/RenderCauseDetector.js +5 -1840
  20. package/lib/commonjs/highlight-updates/utils/RenderTracker.js +1 -952
  21. package/lib/commonjs/highlight-updates/utils/ViewTypeMapper.js +1 -264
  22. package/lib/commonjs/highlight-updates/utils/copySettingsStorage.js +1 -32
  23. package/lib/commonjs/highlight-updates/utils/devtoolsComponentNames.js +1 -188
  24. package/lib/commonjs/highlight-updates/utils/namedComposite.js +1 -41
  25. package/lib/commonjs/highlight-updates/utils/ownStateChanged.js +1 -103
  26. package/lib/commonjs/highlight-updates/utils/rawEventEmitter.js +1 -50
  27. package/lib/commonjs/highlight-updates/utils/rawEventEmitter.web.js +1 -12
  28. package/lib/commonjs/highlight-updates/utils/renderExportFormatter.js +1 -58
  29. package/lib/commonjs/highlight-updates/utils/rendersExportFormatter.js +1 -485
  30. package/lib/commonjs/highlight-updates/utils/screenElements.js +1 -1269
  31. package/lib/commonjs/highlight-updates/utils/tapMatch.js +1 -83
  32. package/lib/commonjs/highlight-updates/utils/testIDs.js +1 -68
  33. package/lib/commonjs/highlight-updates/utils/touchCapture.js +1 -277
  34. package/lib/commonjs/index.js +1 -429
  35. package/lib/commonjs/preset.js +1 -278
  36. package/lib/commonjs/sync/highlightUpdatesSyncAdapter.js +1 -235
  37. package/lib/module/highlight-updates/HighlightUpdatesOverlay.js +1 -274
  38. package/lib/module/highlight-updates/components/HighlightFilterView.js +1 -1468
  39. package/lib/module/highlight-updates/components/HighlightUpdatesModal.js +1 -634
  40. package/lib/module/highlight-updates/components/IdentifierBadge.js +1 -265
  41. package/lib/module/highlight-updates/components/IsolatedRenderList.js +1 -183
  42. package/lib/module/highlight-updates/components/ModalHeaderContent.js +1 -288
  43. package/lib/module/highlight-updates/components/RenderCauseBadge.js +1 -499
  44. package/lib/module/highlight-updates/components/RenderDetailView.js +1 -840
  45. package/lib/module/highlight-updates/components/RenderHistoryViewer.js +1 -908
  46. package/lib/module/highlight-updates/components/RenderListItem.js +1 -230
  47. package/lib/module/highlight-updates/components/RendersCopySettingsView.js +1 -465
  48. package/lib/module/highlight-updates/components/StatsDisplay.js +1 -70
  49. package/lib/module/highlight-updates/types/copySettings.js +1 -102
  50. package/lib/module/highlight-updates/utils/CommitProfiler.js +1 -451
  51. package/lib/module/highlight-updates/utils/HighlightUpdatesController.js +1 -1925
  52. package/lib/module/highlight-updates/utils/PerformanceLogger.js +26 -353
  53. package/lib/module/highlight-updates/utils/ProfilerInterceptor.js +1 -358
  54. package/lib/module/highlight-updates/utils/RenderCauseDetector.js +5 -1830
  55. package/lib/module/highlight-updates/utils/RenderTracker.js +1 -949
  56. package/lib/module/highlight-updates/utils/ViewTypeMapper.js +1 -255
  57. package/lib/module/highlight-updates/utils/copySettingsStorage.js +1 -26
  58. package/lib/module/highlight-updates/utils/devtoolsComponentNames.js +1 -178
  59. package/lib/module/highlight-updates/utils/namedComposite.js +1 -36
  60. package/lib/module/highlight-updates/utils/ownStateChanged.js +1 -98
  61. package/lib/module/highlight-updates/utils/rawEventEmitter.js +1 -46
  62. package/lib/module/highlight-updates/utils/rawEventEmitter.web.js +1 -3
  63. package/lib/module/highlight-updates/utils/renderExportFormatter.js +1 -54
  64. package/lib/module/highlight-updates/utils/rendersExportFormatter.js +1 -478
  65. package/lib/module/highlight-updates/utils/screenElements.js +1 -1263
  66. package/lib/module/highlight-updates/utils/tapMatch.js +1 -76
  67. package/lib/module/highlight-updates/utils/testIDs.js +1 -60
  68. package/lib/module/highlight-updates/utils/touchCapture.js +1 -270
  69. package/lib/module/index.js +1 -130
  70. package/lib/module/preset.js +1 -272
  71. package/lib/module/sync/highlightUpdatesSyncAdapter.js +1 -230
  72. package/lib/web/index.mjs +28 -29
  73. package/package.json +7 -11
  74. package/lib/typescript/highlight-updates/HighlightUpdatesOverlay.d.ts.map +0 -1
  75. package/lib/typescript/highlight-updates/components/HighlightFilterView.d.ts.map +0 -1
  76. package/lib/typescript/highlight-updates/components/HighlightUpdatesModal.d.ts.map +0 -1
  77. package/lib/typescript/highlight-updates/components/IdentifierBadge.d.ts.map +0 -1
  78. package/lib/typescript/highlight-updates/components/IsolatedRenderList.d.ts.map +0 -1
  79. package/lib/typescript/highlight-updates/components/ModalHeaderContent.d.ts.map +0 -1
  80. package/lib/typescript/highlight-updates/components/RenderCauseBadge.d.ts.map +0 -1
  81. package/lib/typescript/highlight-updates/components/RenderDetailView.d.ts.map +0 -1
  82. package/lib/typescript/highlight-updates/components/RenderHistoryViewer.d.ts.map +0 -1
  83. package/lib/typescript/highlight-updates/components/RenderListItem.d.ts.map +0 -1
  84. package/lib/typescript/highlight-updates/components/RendersCopySettingsView.d.ts.map +0 -1
  85. package/lib/typescript/highlight-updates/components/StatsDisplay.d.ts.map +0 -1
  86. package/lib/typescript/highlight-updates/types/copySettings.d.ts.map +0 -1
  87. package/lib/typescript/highlight-updates/utils/CommitProfiler.d.ts.map +0 -1
  88. package/lib/typescript/highlight-updates/utils/HighlightUpdatesController.d.ts.map +0 -1
  89. package/lib/typescript/highlight-updates/utils/PerformanceLogger.d.ts.map +0 -1
  90. package/lib/typescript/highlight-updates/utils/ProfilerInterceptor.d.ts.map +0 -1
  91. package/lib/typescript/highlight-updates/utils/RenderCauseDetector.d.ts.map +0 -1
  92. package/lib/typescript/highlight-updates/utils/RenderTracker.d.ts.map +0 -1
  93. package/lib/typescript/highlight-updates/utils/ViewTypeMapper.d.ts.map +0 -1
  94. package/lib/typescript/highlight-updates/utils/copySettingsStorage.d.ts.map +0 -1
  95. package/lib/typescript/highlight-updates/utils/devtoolsComponentNames.d.ts.map +0 -1
  96. package/lib/typescript/highlight-updates/utils/namedComposite.d.ts.map +0 -1
  97. package/lib/typescript/highlight-updates/utils/ownStateChanged.d.ts.map +0 -1
  98. package/lib/typescript/highlight-updates/utils/rawEventEmitter.d.ts.map +0 -1
  99. package/lib/typescript/highlight-updates/utils/rawEventEmitter.web.d.ts.map +0 -1
  100. package/lib/typescript/highlight-updates/utils/renderExportFormatter.d.ts.map +0 -1
  101. package/lib/typescript/highlight-updates/utils/rendersExportFormatter.d.ts.map +0 -1
  102. package/lib/typescript/highlight-updates/utils/screenElements.d.ts.map +0 -1
  103. package/lib/typescript/highlight-updates/utils/tapMatch.d.ts.map +0 -1
  104. package/lib/typescript/highlight-updates/utils/testIDs.d.ts.map +0 -1
  105. package/lib/typescript/highlight-updates/utils/touchCapture.d.ts.map +0 -1
  106. package/lib/typescript/index.d.ts.map +0 -1
  107. package/lib/typescript/preset.d.ts.map +0 -1
  108. package/lib/typescript/sync/highlightUpdatesSyncAdapter.d.ts.map +0 -1
@@ -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)}};