@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.
- package/README.md +28 -6
- 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 -466
- 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 +1 -359
- package/lib/commonjs/highlight-updates/utils/ProfilerInterceptor.js +1 -371
- package/lib/commonjs/highlight-updates/utils/RenderCauseDetector.js +1 -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/renderExportFormatter.js +1 -58
- package/lib/commonjs/highlight-updates/utils/rendersExportFormatter.js +1 -485
- package/lib/commonjs/highlight-updates/utils/screenElements.js +1 -1046
- package/lib/commonjs/highlight-updates/utils/tapMatch.js +1 -58
- 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 -462
- 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 +1 -353
- package/lib/module/highlight-updates/utils/ProfilerInterceptor.js +1 -358
- package/lib/module/highlight-updates/utils/RenderCauseDetector.js +1 -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/renderExportFormatter.js +1 -54
- package/lib/module/highlight-updates/utils/rendersExportFormatter.js +1 -478
- package/lib/module/highlight-updates/utils/screenElements.js +1 -1040
- package/lib/module/highlight-updates/utils/tapMatch.js +1 -52
- 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/screenElements.d.ts +52 -1
- package/lib/typescript/highlight-updates/utils/tapMatch.d.ts +11 -0
- package/lib/typescript/sync/highlightUpdatesSyncAdapter.d.ts +1 -1
- package/package.json +8 -8
- 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/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@buoy-gg/highlight-updates) [](https://www.npmjs.com/package/@buoy-gg/highlight-updates)
|
|
4
4
|
|
|
5
|
-
|
|
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)
|
|
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** —
|
|
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
|
-
|
|
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
|
-
##
|
|
75
|
+
## Account and plan requirements
|
|
54
76
|
|
|
55
|
-
|
|
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;
|