@buoy-gg/highlight-updates 7.0.35 → 7.0.38

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 (107) hide show
  1. package/README.md +28 -6
  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 -466
  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 -446
  16. package/lib/commonjs/highlight-updates/utils/HighlightUpdatesController.js +1 -1920
  17. package/lib/commonjs/highlight-updates/utils/PerformanceLogger.js +1 -359
  18. package/lib/commonjs/highlight-updates/utils/ProfilerInterceptor.js +1 -371
  19. package/lib/commonjs/highlight-updates/utils/RenderCauseDetector.js +1 -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/renderExportFormatter.js +1 -58
  28. package/lib/commonjs/highlight-updates/utils/rendersExportFormatter.js +1 -485
  29. package/lib/commonjs/highlight-updates/utils/screenElements.js +1 -1046
  30. package/lib/commonjs/highlight-updates/utils/tapMatch.js +1 -58
  31. package/lib/commonjs/highlight-updates/utils/testIDs.js +1 -68
  32. package/lib/commonjs/highlight-updates/utils/touchCapture.js +1 -277
  33. package/lib/commonjs/index.js +1 -429
  34. package/lib/commonjs/preset.js +1 -278
  35. package/lib/commonjs/sync/highlightUpdatesSyncAdapter.js +1 -235
  36. package/lib/module/highlight-updates/HighlightUpdatesOverlay.js +1 -274
  37. package/lib/module/highlight-updates/components/HighlightFilterView.js +1 -1468
  38. package/lib/module/highlight-updates/components/HighlightUpdatesModal.js +1 -634
  39. package/lib/module/highlight-updates/components/IdentifierBadge.js +1 -265
  40. package/lib/module/highlight-updates/components/IsolatedRenderList.js +1 -183
  41. package/lib/module/highlight-updates/components/ModalHeaderContent.js +1 -288
  42. package/lib/module/highlight-updates/components/RenderCauseBadge.js +1 -499
  43. package/lib/module/highlight-updates/components/RenderDetailView.js +1 -840
  44. package/lib/module/highlight-updates/components/RenderHistoryViewer.js +1 -908
  45. package/lib/module/highlight-updates/components/RenderListItem.js +1 -230
  46. package/lib/module/highlight-updates/components/RendersCopySettingsView.js +1 -462
  47. package/lib/module/highlight-updates/components/StatsDisplay.js +1 -70
  48. package/lib/module/highlight-updates/types/copySettings.js +1 -102
  49. package/lib/module/highlight-updates/utils/CommitProfiler.js +1 -442
  50. package/lib/module/highlight-updates/utils/HighlightUpdatesController.js +1 -1916
  51. package/lib/module/highlight-updates/utils/PerformanceLogger.js +1 -353
  52. package/lib/module/highlight-updates/utils/ProfilerInterceptor.js +1 -358
  53. package/lib/module/highlight-updates/utils/RenderCauseDetector.js +1 -1830
  54. package/lib/module/highlight-updates/utils/RenderTracker.js +1 -949
  55. package/lib/module/highlight-updates/utils/ViewTypeMapper.js +1 -255
  56. package/lib/module/highlight-updates/utils/copySettingsStorage.js +1 -26
  57. package/lib/module/highlight-updates/utils/devtoolsComponentNames.js +1 -178
  58. package/lib/module/highlight-updates/utils/namedComposite.js +1 -36
  59. package/lib/module/highlight-updates/utils/ownStateChanged.js +1 -98
  60. package/lib/module/highlight-updates/utils/rawEventEmitter.js +1 -46
  61. package/lib/module/highlight-updates/utils/renderExportFormatter.js +1 -54
  62. package/lib/module/highlight-updates/utils/rendersExportFormatter.js +1 -478
  63. package/lib/module/highlight-updates/utils/screenElements.js +1 -1040
  64. package/lib/module/highlight-updates/utils/tapMatch.js +1 -52
  65. package/lib/module/highlight-updates/utils/testIDs.js +1 -60
  66. package/lib/module/highlight-updates/utils/touchCapture.js +1 -270
  67. package/lib/module/index.js +1 -130
  68. package/lib/module/preset.js +1 -272
  69. package/lib/module/sync/highlightUpdatesSyncAdapter.js +1 -230
  70. package/lib/typescript/highlight-updates/utils/screenElements.d.ts +52 -1
  71. package/lib/typescript/highlight-updates/utils/tapMatch.d.ts +11 -0
  72. package/lib/typescript/sync/highlightUpdatesSyncAdapter.d.ts +1 -1
  73. package/package.json +8 -8
  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/renderExportFormatter.d.ts.map +0 -1
  100. package/lib/typescript/highlight-updates/utils/rendersExportFormatter.d.ts.map +0 -1
  101. package/lib/typescript/highlight-updates/utils/screenElements.d.ts.map +0 -1
  102. package/lib/typescript/highlight-updates/utils/tapMatch.d.ts.map +0 -1
  103. package/lib/typescript/highlight-updates/utils/testIDs.d.ts.map +0 -1
  104. package/lib/typescript/highlight-updates/utils/touchCapture.d.ts.map +0 -1
  105. package/lib/typescript/index.d.ts.map +0 -1
  106. package/lib/typescript/preset.d.ts.map +0 -1
  107. package/lib/typescript/sync/highlightUpdatesSyncAdapter.d.ts.map +0 -1
package/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@buoy-gg/highlight-updates?style=flat-square&labelColor=1c1c1c&color=10B981)](https://www.npmjs.com/package/@buoy-gg/highlight-updates) [![npm downloads](https://img.shields.io/npm/dm/@buoy-gg/highlight-updates?style=flat-square&labelColor=1c1c1c&color=10B981)](https://www.npmjs.com/package/@buoy-gg/highlight-updates)
4
4
 
5
- **See exactly WHY your React Native components re-render — every render gets an overlay tagged with its cause: mount, state, props, or parent.**
5
+ Highlight observed React component updates in development builds and inspect the available render details.
6
6
 
7
- Part of [Buoy](https://github.com/Buoy-gg/buoy) — devtools that live inside your React Native app. Install it and it auto-appears in the floating menu from [`@buoy-gg/core`](https://www.npmjs.com/package/@buoy-gg/core).
7
+ Part of [Buoy](https://github.com/Buoy-gg/buoy). Install the package, complete account setup, and follow the integration steps below.
8
8
 
9
9
  ## Install
10
10
 
@@ -12,6 +12,24 @@ Part of [Buoy](https://github.com/Buoy-gg/buoy) — devtools that live inside yo
12
12
  npm install @buoy-gg/core @buoy-gg/highlight-updates
13
13
  ```
14
14
 
15
+ ## Before you start
16
+
17
+ Use a development build with `@buoy-gg/core` and a Free or Pro Buoy account key. From your app’s directory, sign in:
18
+
19
+ ```bash
20
+ npx --package=@buoy-gg/core buoy login
21
+ ```
22
+
23
+ For Expo, initialize Buoy before rendering the menu:
24
+
25
+ ```tsx
26
+ import { Buoy } from "@buoy-gg/core";
27
+
28
+ Buoy.init({ licenseKey: process.env.EXPO_PUBLIC_BUOY_KEY });
29
+ ```
30
+
31
+ The login command writes the Expo key to `.env.local`. For React Native CLI, pass the key from your app’s environment configuration; React Native does not load `.env.local` automatically. Mount `FloatingDevTools` inside the same providers as your screens and restart the development server after installation. The [Quick Start](https://buoy.gg/buoy/latest/docs/quick-start) shows the complete root component setup.
32
+
15
33
  ## Quick start
16
34
 
17
35
  ```tsx
@@ -37,9 +55,13 @@ import { HighlightUpdatesController } from "@buoy-gg/highlight-updates";
37
55
  HighlightUpdatesController.toggle();
38
56
  ```
39
57
 
58
+ ## Check the integration
59
+
60
+ In a development build, open the tool and update a visible component’s state. Confirm that an update is highlighted. Capture depends on React’s development hooks; Pro does not make those hooks available in a release build.
61
+
40
62
  ## What you get
41
63
 
42
- - **Render overlays with the cause** — every render flashes a bounding box tagged mount / state change / prop change / parent re-render. No more guessing why a component updated.
64
+ - **Render overlays with the cause** — observed updates flash a bounding box with the available mount, state, props, or parent-update classification.
43
65
  - **Hook value tracking** — when state caused the render, see the before → after values of the exact `useState` or `useReducer` that changed.
44
66
  - **Overlay mode** — lightweight real-time highlights while you interact with the app; perfect for spotting unnecessary re-renders.
45
67
  - **Modal mode** — full inspector with render history, filtering, and detailed per-render cause breakdowns for deep debugging sessions.
@@ -48,11 +70,11 @@ HighlightUpdatesController.toggle();
48
70
 
49
71
  ## Desktop & AI
50
72
 
51
- The same live session streams to [Buoy Desktop](https://github.com/Buoy-gg/Buoy-Desktop) (free, macOS/Windows/Linux) and to Claude Code or Cursor via the [Buoy MCP server](https://buoy.gg/buoy/latest/docs/mcp).
73
+ To connect a React Native app to [Buoy Desktop](https://github.com/Buoy-gg/Buoy-Desktop) or MCP, install `@buoy-gg/external-sync` and follow the [Desktop connection guide](https://buoy.gg/buoy/latest/docs/desktop). Sign in to Desktop separately. [MCP setup](https://buoy.gg/buoy/latest/docs/mcp) also requires a process account and Pro access. Available remote actions depend on the tool and app integration.
52
74
 
53
- ## Free vs Pro
75
+ ## Account and plan requirements
54
76
 
55
- Every tool is free. [Pro](https://buoy.gg/pricing) unlocks production builds, the MCP server, and unlimited capture. Every weekend, Pro features unlock free for anyone holding a key — including a free one (`npx buoy login`).
77
+ Use a Free or Pro Buoy account. History limits and paid features vary by tool; see [pricing](https://buoy.gg/pricing). Production access requires Pro where supported. Development-only hooks and actions remain unavailable in release builds.
56
78
 
57
79
  ---
58
80
 
@@ -1,281 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.HighlightUpdatesOverlay = HighlightUpdatesOverlay;
7
- exports.default = void 0;
8
- var _react = _interopRequireWildcard(require("react"));
9
- var _reactNative = require("react-native");
10
- var _sharedUi = require("@buoy-gg/shared-ui");
11
- var _HighlightUpdatesController = _interopRequireDefault(require("./utils/HighlightUpdatesController"));
12
- var _PerformanceLogger = require("./utils/PerformanceLogger");
13
- var _RenderTracker = require("./utils/RenderTracker");
14
- var _jsxRuntime = require("react/jsx-runtime");
15
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
16
- 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); }
17
- /**
18
- * HighlightUpdatesOverlay
19
- *
20
- * Renders colored highlight rectangles for components that have updated.
21
- * Uses View-based rendering (similar to debug-borders) instead of the
22
- * native DebuggingOverlay component for better compatibility.
23
- */
24
-
25
- // Declare performance API available in React Native's JavaScript environment
26
-
27
- // How long highlights stay visible (ms)
28
- const HIGHLIGHT_DURATION = 1000;
29
- function HighlightUpdatesOverlay({
30
- onBadgePress
31
- } = {}) {
32
- const [highlights, setHighlights] = (0, _react.useState)([]);
33
- const [isFrozen, setIsFrozen] = (0, _react.useState)(() => _HighlightUpdatesController.default.getFrozen());
34
- const [spotlightTag, setSpotlightTag] = (0, _react.useState)(null);
35
- const cleanupTimerRef = (0, _react.useRef)(null);
36
- const renderStartTimeRef = (0, _react.useRef)(0);
37
- const highlightCountRef = (0, _react.useRef)(0);
38
- const frozenRef = (0, _react.useRef)(isFrozen);
39
-
40
- // Keep ref in sync with state for use in interval callback
41
- frozenRef.current = isFrozen;
42
-
43
- // Track render start time
44
- if (_PerformanceLogger.PerformanceLogger.isEnabled()) {
45
- renderStartTimeRef.current = performance.now();
46
- highlightCountRef.current = highlights.length;
47
- }
48
-
49
- // Measure render completion time using useLayoutEffect (runs after DOM mutations)
50
- (0, _react.useLayoutEffect)(() => {
51
- if (_PerformanceLogger.PerformanceLogger.isEnabled() && renderStartTimeRef.current > 0 && highlightCountRef.current > 0) {
52
- const renderTime = performance.now() - renderStartTimeRef.current;
53
- // Mark end-to-end timing (for benchmark recording only - no console logs)
54
- (0, _PerformanceLogger.markOverlayRendered)(highlightCountRef.current, renderTime);
55
- }
56
- });
57
-
58
- // Subscribe to freeze state changes
59
- (0, _react.useEffect)(() => {
60
- const unsubscribe = _HighlightUpdatesController.default.subscribeToFreeze(frozen => {
61
- setIsFrozen(frozen);
62
- });
63
- return unsubscribe;
64
- }, []);
65
-
66
- // Subscribe to filter changes - refresh frozen highlights when filters change
67
- (0, _react.useEffect)(() => {
68
- const unsubscribe = _RenderTracker.RenderTracker.subscribeToFilters(() => {
69
- // When filters change, filter out highlights that no longer match
70
- setHighlights(prev => {
71
- return prev.filter(highlight => {
72
- // Look up the render by nativeTag
73
- const render = _RenderTracker.RenderTracker.getRender(String(highlight.id));
74
- if (!render) {
75
- // If render not found, keep the highlight (it might be from a different source)
76
- return true;
77
- }
78
- // Check if the render should still be shown based on new filters
79
- return _RenderTracker.RenderTracker.shouldShowRender(render);
80
- });
81
- });
82
- });
83
- return unsubscribe;
84
- }, []);
85
-
86
- // Subscribe to spotlight changes - show which component is being viewed in detail
87
- (0, _react.useEffect)(() => {
88
- _HighlightUpdatesController.default.setSpotlightCallback(tag => {
89
- setSpotlightTag(tag);
90
- });
91
- return () => {
92
- _HighlightUpdatesController.default.setSpotlightCallback(null);
93
- };
94
- }, []);
95
-
96
- // Callback to add new highlights
97
- const addHighlights = (0, _react.useCallback)(newRects => {
98
- const now = Date.now();
99
- const timestampedRects = newRects.map(rect => ({
100
- ...rect,
101
- timestamp: now
102
- }));
103
- setHighlights(prev => {
104
- // Merge new highlights, replacing any with same id
105
- const updated = [...prev];
106
- for (const newRect of timestampedRects) {
107
- const existingIndex = updated.findIndex(r => r.id === newRect.id);
108
- if (existingIndex >= 0) {
109
- updated[existingIndex] = newRect;
110
- } else {
111
- updated.push(newRect);
112
- }
113
- }
114
- return updated;
115
- });
116
- }, []);
117
-
118
- // Register the callback with the controller
119
- (0, _react.useEffect)(() => {
120
- _HighlightUpdatesController.default.setHighlightCallback(addHighlights);
121
-
122
- // Cleanup timer to remove old highlights
123
- // When frozen, skip cleanup to keep highlights visible indefinitely
124
- cleanupTimerRef.current = setInterval(() => {
125
- // Check frozen state via ref (doesn't cause re-subscription)
126
- if (frozenRef.current) {
127
- return; // Skip cleanup when frozen
128
- }
129
- const now = Date.now();
130
- setHighlights(prev => prev.filter(rect => now - rect.timestamp < HIGHLIGHT_DURATION));
131
- }, 50);
132
- return () => {
133
- _HighlightUpdatesController.default.setHighlightCallback(null);
134
- if (cleanupTimerRef.current) {
135
- clearInterval(cleanupTimerRef.current);
136
- }
137
- };
138
- }, [addHighlights]);
139
-
140
- // Check if badge press handling is enabled (via props or controller)
141
- const hasBadgePressHandler = onBadgePress || _HighlightUpdatesController.default.getBadgePressCallback();
142
-
143
- // Handle badge press - navigate to detail view for this component
144
- const handleBadgePress = (0, _react.useCallback)(nativeTag => {
145
- // First try the prop callback
146
- if (onBadgePress) {
147
- onBadgePress(nativeTag);
148
- } else {
149
- // Fall back to controller callback
150
- _HighlightUpdatesController.default.handleBadgePress(nativeTag);
151
- }
152
- }, [onBadgePress]);
153
-
154
- // Get spotlight render info if we have a spotlight active
155
- const spotlightRender = spotlightTag ? _RenderTracker.RenderTracker.getRender(String(spotlightTag)) : null;
156
-
157
- // Render nothing if no highlights and no spotlight
158
- if (highlights.length === 0 && !spotlightRender?.measurements) {
159
- return null;
160
- }
161
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
162
- style: styles.overlay,
163
- pointerEvents: "box-none",
164
- nativeID: "highlight-updates-overlay",
165
- children: [spotlightRender?.measurements && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
166
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
167
- pointerEvents: "none",
168
- nativeID: "__spotlight_highlight__",
169
- style: [styles.spotlightHighlight, {
170
- // Offset by border width so border renders outside the component bounds
171
- left: spotlightRender.measurements.x - 3,
172
- top: spotlightRender.measurements.y - 3,
173
- width: spotlightRender.measurements.width + 6,
174
- height: spotlightRender.measurements.height + 6
175
- }]
176
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
177
- pointerEvents: "none",
178
- style: [styles.spotlightLabel, {
179
- left: spotlightRender.measurements.x,
180
- top: spotlightRender.measurements.y + spotlightRender.measurements.height + 4
181
- }],
182
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
183
- style: styles.spotlightLabelText,
184
- children: spotlightRender.componentName || spotlightRender.displayName || spotlightRender.viewType
185
- })
186
- })]
187
- }), highlights.map(rect => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
188
- pointerEvents: "box-none",
189
- nativeID: `__highlight_rect_${rect.id}__`,
190
- style: [styles.highlight, {
191
- left: rect.x,
192
- top: rect.y,
193
- width: rect.width,
194
- height: rect.height,
195
- borderColor: rect.color
196
- }],
197
- children: rect.count > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
198
- style: [styles.badge, {
199
- backgroundColor: rect.color
200
- }],
201
- nativeID: `__highlight_badge_${rect.id}__`,
202
- pointerEvents: hasBadgePressHandler ? "auto" : "none",
203
- hitSlop: {
204
- top: 8,
205
- bottom: 8,
206
- left: 8,
207
- right: 8
208
- },
209
- onStartShouldSetResponder: () => !!hasBadgePressHandler
210
- // Fire on touch-DOWN: on churning screens the badge views are
211
- // torn down and recreated between finger-down and finger-up
212
- // (every highlight event rebuilds the boxes), which kills the
213
- // responder before a release can fire. Grant fires immediately.
214
- ,
215
- onResponderGrant: () => handleBadgePress(rect.id),
216
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
217
- style: styles.badgeText,
218
- nativeID: `__highlight_text_${rect.id}__`,
219
- children: rect.count
220
- })
221
- })
222
- }, `highlight-${rect.id}`))]
223
- });
224
- }
225
- const styles = _reactNative.StyleSheet.create({
226
- overlay: {
227
- position: "absolute",
228
- top: 0,
229
- left: 0,
230
- right: 0,
231
- bottom: 0,
232
- zIndex: 999999,
233
- elevation: 999999,
234
- borderWidth: 0
235
- },
236
- highlight: {
237
- position: "absolute",
238
- borderWidth: 2,
239
- borderStyle: "solid",
240
- backgroundColor: "transparent"
241
- },
242
- badge: {
243
- position: "absolute",
244
- top: 0,
245
- right: 0,
246
- height: 14,
247
- borderRadius: 0,
248
- justifyContent: "center",
249
- alignItems: "center",
250
- paddingHorizontal: 2
251
- },
252
- badgeText: {
253
- color: "#000",
254
- fontSize: 9,
255
- fontWeight: "bold"
256
- },
257
- // Spotlight highlight styles
258
- spotlightHighlight: {
259
- position: "absolute",
260
- borderWidth: 2,
261
- borderStyle: "dashed",
262
- borderColor: _sharedUi.night.color.accent,
263
- backgroundColor: "transparent"
264
- },
265
- spotlightLabel: {
266
- position: "absolute",
267
- backgroundColor: _sharedUi.night.color.surface,
268
- borderWidth: 1,
269
- borderColor: _sharedUi.night.color.accent,
270
- paddingHorizontal: 8,
271
- paddingVertical: 3,
272
- borderRadius: 4
273
- },
274
- spotlightLabelText: {
275
- color: _sharedUi.night.color.accent,
276
- fontSize: 11,
277
- fontWeight: "600",
278
- fontFamily: _sharedUi.monoFont
279
- }
280
- });
281
- var _default = exports.default = HighlightUpdatesOverlay;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.HighlightUpdatesOverlay=HighlightUpdatesOverlay,exports.default=void 0;var _react=_interopRequireWildcard(require("react")),_reactNative=require("react-native"),_sharedUi=require("@buoy-gg/shared-ui"),_HighlightUpdatesController=_interopRequireDefault(require("./utils/HighlightUpdatesController")),_PerformanceLogger=require("./utils/PerformanceLogger"),_RenderTracker=require("./utils/RenderTracker"),_jsxRuntime=require("react/jsx-runtime");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _interopRequireWildcard(e,t){if("function"==typeof WeakMap)var r=new WeakMap,i=new WeakMap;return(_interopRequireWildcard=function(e,t){if(!t&&e&&e.__esModule)return e;var n,o,a={__proto__:null,default:e};if(null===e||"object"!=typeof e&&"function"!=typeof e)return a;if(n=t?i:r){if(n.has(e))return n.get(e);n.set(e,a)}for(const t in e)"default"!==t&&{}.hasOwnProperty.call(e,t)&&((o=(n=Object.defineProperty)&&Object.getOwnPropertyDescriptor(e,t))&&(o.get||o.set)?n(a,t,o):a[t]=e[t]);return a})(e,t)}const HIGHLIGHT_DURATION=1e3;function HighlightUpdatesOverlay({onBadgePress:e}={}){const[t,r]=(0,_react.useState)([]),[i,n]=(0,_react.useState)(()=>_HighlightUpdatesController.default.getFrozen()),[o,a]=(0,_react.useState)(null),l=(0,_react.useRef)(null),s=(0,_react.useRef)(0),c=(0,_react.useRef)(0),d=(0,_react.useRef)(i);d.current=i,_PerformanceLogger.PerformanceLogger.isEnabled()&&(s.current=performance.now(),c.current=t.length),(0,_react.useLayoutEffect)(()=>{if(_PerformanceLogger.PerformanceLogger.isEnabled()&&s.current>0&&c.current>0){const e=performance.now()-s.current;(0,_PerformanceLogger.markOverlayRendered)(c.current,e)}}),(0,_react.useEffect)(()=>_HighlightUpdatesController.default.subscribeToFreeze(e=>{n(e)}),[]),(0,_react.useEffect)(()=>_RenderTracker.RenderTracker.subscribeToFilters(()=>{r(e=>e.filter(e=>{const t=_RenderTracker.RenderTracker.getRender(String(e.id));return!t||_RenderTracker.RenderTracker.shouldShowRender(t)}))}),[]),(0,_react.useEffect)(()=>(_HighlightUpdatesController.default.setSpotlightCallback(e=>{a(e)}),()=>{_HighlightUpdatesController.default.setSpotlightCallback(null)}),[]);const u=(0,_react.useCallback)(e=>{const t=Date.now(),i=e.map(e=>({...e,timestamp:t}));r(e=>{const t=[...e];for(const e of i){const r=t.findIndex(t=>t.id===e.id);r>=0?t[r]=e:t.push(e)}return t})},[]);(0,_react.useEffect)(()=>(_HighlightUpdatesController.default.setHighlightCallback(u),l.current=setInterval(()=>{if(d.current)return;const e=Date.now();r(t=>t.filter(t=>e-t.timestamp<HIGHLIGHT_DURATION))},50),()=>{_HighlightUpdatesController.default.setHighlightCallback(null),l.current&&clearInterval(l.current)}),[u]);const h=e||_HighlightUpdatesController.default.getBadgePressCallback(),g=(0,_react.useCallback)(t=>{e?e(t):_HighlightUpdatesController.default.handleBadgePress(t)},[e]),_=o?_RenderTracker.RenderTracker.getRender(String(o)):null;return 0!==t.length||_?.measurements?(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.overlay,pointerEvents:"box-none",nativeID:"highlight-updates-overlay",children:[_?.measurements&&(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_reactNative.View,{pointerEvents:"none",nativeID:"__spotlight_highlight__",style:[styles.spotlightHighlight,{left:_.measurements.x-3,top:_.measurements.y-3,width:_.measurements.width+6,height:_.measurements.height+6}]}),(0,_jsxRuntime.jsx)(_reactNative.View,{pointerEvents:"none",style:[styles.spotlightLabel,{left:_.measurements.x,top:_.measurements.y+_.measurements.height+4}],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.spotlightLabelText,children:_.componentName||_.displayName||_.viewType})})]}),t.map(e=>(0,_jsxRuntime.jsx)(_reactNative.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&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.badge,{backgroundColor:e.color}],nativeID:`__highlight_badge_${e.id}__`,pointerEvents:h?"auto":"none",hitSlop:{top:8,bottom:8,left:8,right:8},onStartShouldSetResponder:()=>!!h,onResponderGrant:()=>g(e.id),children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.badgeText,nativeID:`__highlight_text_${e.id}__`,children:e.count})})},`highlight-${e.id}`))]}):null}const styles=_reactNative.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:_sharedUi.night.color.accent,backgroundColor:"transparent"},spotlightLabel:{position:"absolute",backgroundColor:_sharedUi.night.color.surface,borderWidth:1,borderColor:_sharedUi.night.color.accent,paddingHorizontal:8,paddingVertical:3,borderRadius:4},spotlightLabelText:{color:_sharedUi.night.color.accent,fontSize:11,fontWeight:"600",fontFamily:_sharedUi.monoFont}});var _default=exports.default=HighlightUpdatesOverlay;