@buoy-gg/highlight-updates 7.0.36 → 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 (104) 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 -1248
  30. package/lib/commonjs/highlight-updates/utils/tapMatch.js +1 -83
  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 -1242
  64. package/lib/module/highlight-updates/utils/tapMatch.js +1 -76
  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/package.json +8 -8
  71. package/lib/typescript/highlight-updates/HighlightUpdatesOverlay.d.ts.map +0 -1
  72. package/lib/typescript/highlight-updates/components/HighlightFilterView.d.ts.map +0 -1
  73. package/lib/typescript/highlight-updates/components/HighlightUpdatesModal.d.ts.map +0 -1
  74. package/lib/typescript/highlight-updates/components/IdentifierBadge.d.ts.map +0 -1
  75. package/lib/typescript/highlight-updates/components/IsolatedRenderList.d.ts.map +0 -1
  76. package/lib/typescript/highlight-updates/components/ModalHeaderContent.d.ts.map +0 -1
  77. package/lib/typescript/highlight-updates/components/RenderCauseBadge.d.ts.map +0 -1
  78. package/lib/typescript/highlight-updates/components/RenderDetailView.d.ts.map +0 -1
  79. package/lib/typescript/highlight-updates/components/RenderHistoryViewer.d.ts.map +0 -1
  80. package/lib/typescript/highlight-updates/components/RenderListItem.d.ts.map +0 -1
  81. package/lib/typescript/highlight-updates/components/RendersCopySettingsView.d.ts.map +0 -1
  82. package/lib/typescript/highlight-updates/components/StatsDisplay.d.ts.map +0 -1
  83. package/lib/typescript/highlight-updates/types/copySettings.d.ts.map +0 -1
  84. package/lib/typescript/highlight-updates/utils/CommitProfiler.d.ts.map +0 -1
  85. package/lib/typescript/highlight-updates/utils/HighlightUpdatesController.d.ts.map +0 -1
  86. package/lib/typescript/highlight-updates/utils/PerformanceLogger.d.ts.map +0 -1
  87. package/lib/typescript/highlight-updates/utils/ProfilerInterceptor.d.ts.map +0 -1
  88. package/lib/typescript/highlight-updates/utils/RenderCauseDetector.d.ts.map +0 -1
  89. package/lib/typescript/highlight-updates/utils/RenderTracker.d.ts.map +0 -1
  90. package/lib/typescript/highlight-updates/utils/ViewTypeMapper.d.ts.map +0 -1
  91. package/lib/typescript/highlight-updates/utils/copySettingsStorage.d.ts.map +0 -1
  92. package/lib/typescript/highlight-updates/utils/devtoolsComponentNames.d.ts.map +0 -1
  93. package/lib/typescript/highlight-updates/utils/namedComposite.d.ts.map +0 -1
  94. package/lib/typescript/highlight-updates/utils/ownStateChanged.d.ts.map +0 -1
  95. package/lib/typescript/highlight-updates/utils/rawEventEmitter.d.ts.map +0 -1
  96. package/lib/typescript/highlight-updates/utils/renderExportFormatter.d.ts.map +0 -1
  97. package/lib/typescript/highlight-updates/utils/rendersExportFormatter.d.ts.map +0 -1
  98. package/lib/typescript/highlight-updates/utils/screenElements.d.ts.map +0 -1
  99. package/lib/typescript/highlight-updates/utils/tapMatch.d.ts.map +0 -1
  100. package/lib/typescript/highlight-updates/utils/testIDs.d.ts.map +0 -1
  101. package/lib/typescript/highlight-updates/utils/touchCapture.d.ts.map +0 -1
  102. package/lib/typescript/index.d.ts.map +0 -1
  103. package/lib/typescript/preset.d.ts.map +0 -1
  104. package/lib/typescript/sync/highlightUpdatesSyncAdapter.d.ts.map +0 -1
@@ -1,265 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * IdentifierBadge
5
- *
6
- * Shared badge component for displaying component identifiers.
7
- * Used throughout the highlight-updates package for consistent styling.
8
- */
9
-
10
- import React from "react";
11
- import { View, Text, StyleSheet } from "react-native";
12
- import { Box, Hash, Layers, Eye, Search, FileCode, buoyColors, night, monoFont } from "@buoy-gg/shared-ui";
13
-
14
- // All possible identifier types
15
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
16
- // Badge configuration for each identifier type
17
- export const IDENTIFIER_CONFIG = {
18
- viewType: {
19
- label: "ViewType",
20
- shortLabel: "View",
21
- color: night.color.accent,
22
- icon: Box
23
- },
24
- testID: {
25
- label: "testID",
26
- shortLabel: "test",
27
- color: buoyColors.success,
28
- icon: Hash
29
- },
30
- nativeID: {
31
- label: "nativeID",
32
- shortLabel: "native",
33
- color: "#f59e0b",
34
- // amber
35
- icon: Hash
36
- },
37
- component: {
38
- label: "Component",
39
- shortLabel: "Comp",
40
- color: "#a855f7",
41
- // purple
42
- icon: FileCode
43
- },
44
- accessibilityLabel: {
45
- label: "a11y",
46
- shortLabel: "a11y",
47
- color: "#ec4899",
48
- // pink
49
- icon: Eye
50
- },
51
- nativeTag: {
52
- label: "tag",
53
- shortLabel: "tag",
54
- color: buoyColors.textMuted,
55
- icon: Layers
56
- },
57
- any: {
58
- label: "Any",
59
- shortLabel: "Any",
60
- color: buoyColors.warning,
61
- icon: Search
62
- }
63
- };
64
- export function IdentifierBadge({
65
- type,
66
- value,
67
- compact = false,
68
- badgeOnly = false,
69
- valueOnly = false,
70
- shortLabel = false,
71
- showIcon = false,
72
- testID
73
- }) {
74
- const config = IDENTIFIER_CONFIG[type];
75
- const IconComponent = config.icon;
76
- const label = shortLabel ? config.shortLabel : config.label;
77
- if (valueOnly) {
78
- return /*#__PURE__*/_jsx(Text, {
79
- testID: testID ? `${testID}-value` : undefined,
80
- style: [styles.valueOnly, compact && styles.valueOnlyCompact, {
81
- color: config.color
82
- }],
83
- numberOfLines: 1,
84
- children: value
85
- });
86
- }
87
- if (badgeOnly) {
88
- return /*#__PURE__*/_jsxs(View, {
89
- testID: testID,
90
- style: [styles.badgeOnly, compact && styles.badgeOnlyCompact, {
91
- backgroundColor: config.color + "20",
92
- borderColor: config.color + "40"
93
- }],
94
- children: [showIcon && /*#__PURE__*/_jsx(IconComponent, {
95
- size: compact ? 10 : 12,
96
- color: config.color
97
- }), /*#__PURE__*/_jsx(Text, {
98
- style: [styles.badgeOnlyText, compact && styles.badgeOnlyTextCompact, {
99
- color: config.color
100
- }],
101
- children: label
102
- })]
103
- });
104
- }
105
- return /*#__PURE__*/_jsxs(View, {
106
- testID: testID,
107
- accessibilityLabel: `${config.label} ${value}`,
108
- style: [styles.container, compact && styles.containerCompact],
109
- children: [/*#__PURE__*/_jsxs(View, {
110
- style: [styles.badge, compact && styles.badgeCompact, {
111
- backgroundColor: config.color + "20"
112
- }],
113
- children: [showIcon && /*#__PURE__*/_jsx(IconComponent, {
114
- size: compact ? 8 : 10,
115
- color: config.color
116
- }), /*#__PURE__*/_jsx(Text, {
117
- style: [styles.badgeText, compact && styles.badgeTextCompact, {
118
- color: config.color
119
- }],
120
- children: label
121
- })]
122
- }), /*#__PURE__*/_jsx(Text, {
123
- testID: testID ? `${testID}-value` : undefined,
124
- style: [styles.value, compact && styles.valueCompact],
125
- numberOfLines: 1,
126
- children: value
127
- })]
128
- });
129
- }
130
-
131
- // Standalone badge (no value) for category selection
132
-
133
- export function CategoryBadge({
134
- type,
135
- count,
136
- isSelected = false,
137
- showIcon = true
138
- }) {
139
- const config = IDENTIFIER_CONFIG[type];
140
- const IconComponent = config.icon;
141
- return /*#__PURE__*/_jsxs(View, {
142
- style: [styles.categoryBadge, {
143
- backgroundColor: config.color + "15",
144
- borderColor: isSelected ? config.color : config.color + "40",
145
- borderWidth: isSelected ? 2 : 1
146
- }],
147
- children: [showIcon && /*#__PURE__*/_jsx(IconComponent, {
148
- size: 12,
149
- color: config.color
150
- }), /*#__PURE__*/_jsx(Text, {
151
- style: [styles.categoryBadgeText, {
152
- color: config.color
153
- }],
154
- children: config.label
155
- }), count !== undefined && /*#__PURE__*/_jsx(View, {
156
- style: [styles.categoryBadgeCount, {
157
- backgroundColor: config.color + "25"
158
- }],
159
- children: /*#__PURE__*/_jsx(Text, {
160
- style: [styles.categoryBadgeCountText, {
161
- color: config.color
162
- }],
163
- children: count
164
- })
165
- })]
166
- });
167
- }
168
- const styles = StyleSheet.create({
169
- // Full badge with value
170
- container: {
171
- flexDirection: "row",
172
- alignItems: "center",
173
- gap: 6
174
- },
175
- containerCompact: {
176
- gap: 4
177
- },
178
- badge: {
179
- flexDirection: "row",
180
- alignItems: "center",
181
- paddingVertical: 3,
182
- paddingHorizontal: 6,
183
- borderRadius: 4,
184
- gap: 4
185
- },
186
- badgeCompact: {
187
- paddingVertical: 2,
188
- paddingHorizontal: 5,
189
- gap: 3
190
- },
191
- badgeText: {
192
- fontSize: 10,
193
- fontWeight: "700"
194
- },
195
- badgeTextCompact: {
196
- fontSize: 9
197
- },
198
- value: {
199
- fontSize: 12,
200
- color: night.color.text,
201
- fontFamily: monoFont,
202
- flex: 1
203
- },
204
- valueCompact: {
205
- fontSize: 11
206
- },
207
- // Badge only (no value)
208
- badgeOnly: {
209
- flexDirection: "row",
210
- alignItems: "center",
211
- paddingVertical: 4,
212
- paddingHorizontal: 8,
213
- borderRadius: 6,
214
- borderWidth: 1,
215
- gap: 5
216
- },
217
- badgeOnlyCompact: {
218
- paddingVertical: 2,
219
- paddingHorizontal: 6,
220
- borderRadius: 4,
221
- gap: 4
222
- },
223
- badgeOnlyText: {
224
- fontSize: 11,
225
- fontWeight: "600"
226
- },
227
- badgeOnlyTextCompact: {
228
- fontSize: 9,
229
- fontWeight: "700"
230
- },
231
- // Value only
232
- valueOnly: {
233
- fontSize: 12,
234
- fontFamily: monoFont
235
- },
236
- valueOnlyCompact: {
237
- fontSize: 11
238
- },
239
- // Category badge (for filter selection)
240
- categoryBadge: {
241
- flexDirection: "row",
242
- alignItems: "center",
243
- paddingVertical: 8,
244
- paddingLeft: 10,
245
- paddingRight: 6,
246
- borderRadius: 8,
247
- gap: 6
248
- },
249
- categoryBadgeText: {
250
- fontSize: 11,
251
- fontWeight: "600"
252
- },
253
- categoryBadgeCount: {
254
- paddingHorizontal: 6,
255
- paddingVertical: 2,
256
- borderRadius: 10,
257
- minWidth: 20,
258
- alignItems: "center"
259
- },
260
- categoryBadgeCountText: {
261
- fontSize: 10,
262
- fontWeight: "600"
263
- }
264
- });
265
- export default IdentifierBadge;
1
+ "use strict";import React from"react";import{View,Text,StyleSheet}from"react-native";import{Box,Hash,Layers,Eye,Search,FileCode,buoyColors,night,monoFont}from"@buoy-gg/shared-ui";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";export const IDENTIFIER_CONFIG={viewType:{label:"ViewType",shortLabel:"View",color:night.color.accent,icon:Box},testID:{label:"testID",shortLabel:"test",color:buoyColors.success,icon:Hash},nativeID:{label:"nativeID",shortLabel:"native",color:"#f59e0b",icon:Hash},component:{label:"Component",shortLabel:"Comp",color:"#a855f7",icon:FileCode},accessibilityLabel:{label:"a11y",shortLabel:"a11y",color:"#ec4899",icon:Eye},nativeTag:{label:"tag",shortLabel:"tag",color:buoyColors.textMuted,icon:Layers},any:{label:"Any",shortLabel:"Any",color:buoyColors.warning,icon:Search}};export function IdentifierBadge({type:e,value:o,compact:t=!1,badgeOnly:l=!1,valueOnly:a=!1,shortLabel:r=!1,showIcon:n=!1,testID:i}){const s=IDENTIFIER_CONFIG[e],c=s.icon,d=r?s.shortLabel:s.label;return a?_jsx(Text,{testID:i?`${i}-value`:void 0,style:[styles.valueOnly,t&&styles.valueOnlyCompact,{color:s.color}],numberOfLines:1,children:o}):_jsxs(View,l?{testID:i,style:[styles.badgeOnly,t&&styles.badgeOnlyCompact,{backgroundColor:s.color+"20",borderColor:s.color+"40"}],children:[n&&_jsx(c,{size:t?10:12,color:s.color}),_jsx(Text,{style:[styles.badgeOnlyText,t&&styles.badgeOnlyTextCompact,{color:s.color}],children:d})]}:{testID:i,accessibilityLabel:`${s.label} ${o}`,style:[styles.container,t&&styles.containerCompact],children:[_jsxs(View,{style:[styles.badge,t&&styles.badgeCompact,{backgroundColor:s.color+"20"}],children:[n&&_jsx(c,{size:t?8:10,color:s.color}),_jsx(Text,{style:[styles.badgeText,t&&styles.badgeTextCompact,{color:s.color}],children:d})]}),_jsx(Text,{testID:i?`${i}-value`:void 0,style:[styles.value,t&&styles.valueCompact],numberOfLines:1,children:o})]})}export function CategoryBadge({type:e,count:o,isSelected:t=!1,showIcon:l=!0}){const a=IDENTIFIER_CONFIG[e],r=a.icon;return _jsxs(View,{style:[styles.categoryBadge,{backgroundColor:a.color+"15",borderColor:t?a.color:a.color+"40",borderWidth:t?2:1}],children:[l&&_jsx(r,{size:12,color:a.color}),_jsx(Text,{style:[styles.categoryBadgeText,{color:a.color}],children:a.label}),void 0!==o&&_jsx(View,{style:[styles.categoryBadgeCount,{backgroundColor:a.color+"25"}],children:_jsx(Text,{style:[styles.categoryBadgeCountText,{color:a.color}],children:o})})]})}const styles=StyleSheet.create({container:{flexDirection:"row",alignItems:"center",gap:6},containerCompact:{gap:4},badge:{flexDirection:"row",alignItems:"center",paddingVertical:3,paddingHorizontal:6,borderRadius:4,gap:4},badgeCompact:{paddingVertical:2,paddingHorizontal:5,gap:3},badgeText:{fontSize:10,fontWeight:"700"},badgeTextCompact:{fontSize:9},value:{fontSize:12,color:night.color.text,fontFamily:monoFont,flex:1},valueCompact:{fontSize:11},badgeOnly:{flexDirection:"row",alignItems:"center",paddingVertical:4,paddingHorizontal:8,borderRadius:6,borderWidth:1,gap:5},badgeOnlyCompact:{paddingVertical:2,paddingHorizontal:6,borderRadius:4,gap:4},badgeOnlyText:{fontSize:11,fontWeight:"600"},badgeOnlyTextCompact:{fontSize:9,fontWeight:"700"},valueOnly:{fontSize:12,fontFamily:monoFont},valueOnlyCompact:{fontSize:11},categoryBadge:{flexDirection:"row",alignItems:"center",paddingVertical:8,paddingLeft:10,paddingRight:6,borderRadius:8,gap:6},categoryBadgeText:{fontSize:11,fontWeight:"600"},categoryBadgeCount:{paddingHorizontal:6,paddingVertical:2,borderRadius:10,minWidth:20,alignItems:"center"},categoryBadgeCountText:{fontSize:10,fontWeight:"600"}});export default IdentifierBadge;
@@ -1,183 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * IsolatedRenderList
5
- *
6
- * Performance-optimized component that isolates the render tracking subscription
7
- * to prevent parent re-renders. Only this component re-renders when new renders
8
- * are tracked, keeping the modal UI stable.
9
- *
10
- * Following the optimization guide: move subscriptions to child components to
11
- * prevent parent re-renders.
12
- */
13
-
14
- import React, { useState, useEffect, useRef, useCallback, memo, useMemo } from "react";
15
- import { View, Text, FlatList, StyleSheet } from "react-native";
16
- import { RenderTracker } from "../utils/RenderTracker";
17
- import { RenderListItem } from "./RenderListItem";
18
- import { Lock, night, useLimit, ToolEmptyState, resolveListEmptyState } from "@buoy-gg/shared-ui";
19
-
20
- // Free tier limit for tracked components
21
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
22
- /**
23
- * Isolated list component that owns the render subscription.
24
- * Parent component does NOT re-render when renders change.
25
- */
26
- function IsolatedRenderListInner({
27
- searchText,
28
- filters,
29
- onSelectRender,
30
- onStatsChange,
31
- onRendersChange,
32
- isTracking,
33
- isPro = false
34
- }) {
35
- // Initialize with current data to avoid flash of empty state
36
- const [renders, setRenders] = useState(() => RenderTracker.getFilteredRenders(searchText));
37
- const flatListRef = useRef(null);
38
-
39
- // Subscribe to RenderTracker updates - ONLY this component re-renders
40
- useEffect(() => {
41
- const unsubscribe = RenderTracker.subscribe(() => {
42
- const newRenders = RenderTracker.getFilteredRenders(searchText);
43
- setRenders(newRenders);
44
- // Notify parent of stats via callback (parent uses ref, no re-render)
45
- onStatsChange(RenderTracker.getStats());
46
- // Notify parent of renders list for navigation
47
- onRendersChange?.(newRenders);
48
- });
49
- return unsubscribe;
50
- }, [searchText, onStatsChange, onRendersChange]);
51
-
52
- // Update filtered renders when search or filters change
53
- useEffect(() => {
54
- const newRenders = RenderTracker.getFilteredRenders(searchText);
55
- setRenders(newRenders);
56
- onRendersChange?.(newRenders);
57
- }, [searchText, filters, onRendersChange]);
58
-
59
- // Limit visible components for free tier
60
- // `isPro` stays a prop so callers can force the unlimited view; the tier cap
61
- // applies otherwise. useLimit() already returns Infinity for Pro, so the two
62
- // agree — this only preserves the prop contract for cross-package callers.
63
- const tierLimit = useLimit("highlightUpdates.components");
64
- const componentLimit = isPro ? Infinity : tierLimit;
65
- const visibleRenders = useMemo(() => {
66
- return renders.slice(0, componentLimit);
67
- }, [renders, componentLimit]);
68
-
69
- // Calculate locked component count
70
- const lockedComponentCount = useMemo(() => {
71
- return Math.max(0, renders.length - componentLimit);
72
- }, [renders.length, componentLimit]);
73
-
74
- // Stable keyExtractor - moved outside to avoid recreation
75
- const keyExtractor = useCallback(item => item.id, []);
76
-
77
- // Stable renderItem - uses stable onSelectRender callback
78
- const renderItem = useCallback(({
79
- item,
80
- index
81
- }) => /*#__PURE__*/_jsx(RenderListItem, {
82
- render: item,
83
- onPress: () => onSelectRender(item, index, visibleRenders)
84
- }), [onSelectRender, visibleRenders]);
85
-
86
- // Locked banner footer
87
- const renderFooter = useCallback(() => {
88
- if (lockedComponentCount <= 0) return null;
89
- return /*#__PURE__*/_jsxs(View, {
90
- testID: "buoy-highlight-locked",
91
- style: styles.lockedBanner,
92
- children: [/*#__PURE__*/_jsx(Lock, {
93
- size: 14,
94
- color: night.color.warning
95
- }), /*#__PURE__*/_jsxs(Text, {
96
- testID: "buoy-highlight-locked-text",
97
- style: styles.lockedBannerText,
98
- children: [lockedComponentCount, " more ", lockedComponentCount === 1 ? 'component' : 'components', " locked"]
99
- }), /*#__PURE__*/_jsx(Text, {
100
- style: styles.lockedBannerSubtext,
101
- children: "Upgrade to Pro"
102
- })]
103
- });
104
- }, [lockedComponentCount]);
105
-
106
- // Show empty state when no renders
107
- if (renders.length === 0) {
108
- const term = searchText.trim();
109
-
110
- // Read straight off the tracker rather than held in state: this runs only
111
- // on the empty branch, so it costs nothing on the hot path, and it is
112
- // always the current truth. `totalTracked` is every component the tracker
113
- // holds; `unsearched` is what the settings and filters allow BEFORE the
114
- // search box.
115
- const totalTracked = RenderTracker.getStats().totalComponents;
116
- const unsearched = term ? RenderTracker.getFilteredRenders("").length : 0;
117
- const content = resolveListEmptyState({
118
- subject: "components",
119
- verb: "tracked",
120
- search: searchText,
121
- // The denominator is what the FILTERS left, not the raw tracker count —
122
- // "clear the search to see them" has to be true of what you get back.
123
- total: term ? unsearched : totalTracked,
124
- capturing: isTracking,
125
- blocked: term && unsearched === 0 && totalTracked > 0 ? "The active filters hide everything tracked, so there is nothing to search." : undefined,
126
- waiting: {
127
- // stare = "watching for a specific event; recording armed".
128
- otto: "stare",
129
- title: "No renders tracked",
130
- message: "Component renders will appear here"
131
- },
132
- paused: {
133
- title: "No renders tracked",
134
- message: "Enable tracking to start capturing"
135
- }
136
- });
137
- return /*#__PURE__*/_jsx(ToolEmptyState, {
138
- ...content,
139
- testID: "buoy-highlight-empty"
140
- });
141
- }
142
- return /*#__PURE__*/_jsx(FlatList, {
143
- testID: "buoy-highlight-list",
144
- ref: flatListRef,
145
- data: visibleRenders,
146
- renderItem: renderItem,
147
- keyExtractor: keyExtractor,
148
- contentContainerStyle: styles.listContent,
149
- showsVerticalScrollIndicator: true,
150
- initialNumToRender: 10,
151
- maxToRenderPerBatch: 10,
152
- windowSize: 10,
153
- scrollEnabled: false,
154
- ListFooterComponent: renderFooter
155
- });
156
- }
157
-
158
- // Memoize to prevent re-renders from parent state changes
159
- export const IsolatedRenderList = /*#__PURE__*/memo(IsolatedRenderListInner);
160
- const styles = StyleSheet.create({
161
- listContent: {
162
- paddingTop: 8
163
- },
164
- lockedBanner: {
165
- flexDirection: "row",
166
- alignItems: "center",
167
- justifyContent: "center",
168
- paddingVertical: 12,
169
- paddingHorizontal: 16,
170
- marginTop: 8,
171
- gap: 8
172
- },
173
- lockedBannerText: {
174
- color: night.color.warning,
175
- fontSize: 13,
176
- fontWeight: "500"
177
- },
178
- lockedBannerSubtext: {
179
- color: night.color.textTertiary,
180
- fontSize: 12
181
- }
182
- });
183
- export default IsolatedRenderList;
1
+ "use strict";import React,{useState,useEffect,useRef,useCallback,memo,useMemo}from"react";import{View,Text,FlatList,StyleSheet}from"react-native";import{RenderTracker}from"../utils/RenderTracker";import{RenderListItem}from"./RenderListItem";import{Lock,night,useLimit,ToolEmptyState,resolveListEmptyState}from"@buoy-gg/shared-ui";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";function IsolatedRenderListInner({searchText:e,filters:t,onSelectRender:r,onStatsChange:n,onRendersChange:s,isTracking:o,isPro:i=!1}){const[a,l]=useState(()=>RenderTracker.getFilteredRenders(e)),c=useRef(null);useEffect(()=>RenderTracker.subscribe(()=>{const t=RenderTracker.getFilteredRenders(e);l(t),n(RenderTracker.getStats()),s?.(t)}),[e,n,s]),useEffect(()=>{const t=RenderTracker.getFilteredRenders(e);l(t),s?.(t)},[e,t,s]);const d=useLimit("highlightUpdates.components"),m=i?1/0:d,g=useMemo(()=>a.slice(0,m),[a,m]),h=useMemo(()=>Math.max(0,a.length-m),[a.length,m]),u=useCallback(e=>e.id,[]),p=useCallback(({item:e,index:t})=>_jsx(RenderListItem,{render:e,onPress:()=>r(e,t,g)}),[r,g]),k=useCallback(()=>h<=0?null:_jsxs(View,{testID:"buoy-highlight-locked",style:styles.lockedBanner,children:[_jsx(Lock,{size:14,color:night.color.warning}),_jsxs(Text,{testID:"buoy-highlight-locked-text",style:styles.lockedBannerText,children:[h," more ",1===h?"component":"components"," locked"]}),_jsx(Text,{style:styles.lockedBannerSubtext,children:"Upgrade to Pro"})]}),[h]);if(0===a.length){const t=e.trim(),r=RenderTracker.getStats().totalComponents,n=t?RenderTracker.getFilteredRenders("").length:0,s=resolveListEmptyState({subject:"components",verb:"tracked",search:e,total:t?n:r,capturing:o,blocked:t&&0===n&&r>0?"The active filters hide everything tracked, so there is nothing to search.":void 0,waiting:{otto:"stare",title:"No renders tracked",message:"Component renders will appear here"},paused:{title:"No renders tracked",message:"Enable tracking to start capturing"}});return _jsx(ToolEmptyState,{...s,testID:"buoy-highlight-empty"})}return _jsx(FlatList,{testID:"buoy-highlight-list",ref:c,data:g,renderItem:p,keyExtractor:u,contentContainerStyle:styles.listContent,showsVerticalScrollIndicator:!0,initialNumToRender:10,maxToRenderPerBatch:10,windowSize:10,scrollEnabled:!1,ListFooterComponent:k})}export const IsolatedRenderList=memo(IsolatedRenderListInner);const styles=StyleSheet.create({listContent:{paddingTop:8},lockedBanner:{flexDirection:"row",alignItems:"center",justifyContent:"center",paddingVertical:12,paddingHorizontal:16,marginTop:8,gap:8},lockedBannerText:{color:night.color.warning,fontSize:13,fontWeight:"500"},lockedBannerSubtext:{color:night.color.textTertiary,fontSize:12}});export default IsolatedRenderList;