react-native-inapp-inspector 1.1.23 → 1.1.25

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 (79) hide show
  1. package/dist/commonjs/components/AnalyticsEventCard.js +94 -88
  2. package/dist/commonjs/components/ConsoleLogCard.js +49 -25
  3. package/dist/commonjs/components/Inspector/AnalyticsFilterModal.d.ts +7 -0
  4. package/dist/commonjs/components/Inspector/AnalyticsFilterModal.js +1002 -0
  5. package/dist/commonjs/components/Inspector/AnalyticsTab.js +637 -10
  6. package/dist/commonjs/components/Inspector/BundleTab.d.ts +1 -1
  7. package/dist/commonjs/components/Inspector/BundleTab.js +859 -402
  8. package/dist/commonjs/components/Inspector/InspectorContext.js +6 -1
  9. package/dist/commonjs/components/Inspector/InspectorHeader.js +13 -5
  10. package/dist/commonjs/components/Inspector/LogDetail.js +223 -111
  11. package/dist/commonjs/components/Inspector/MainScreen.js +1 -1
  12. package/dist/commonjs/components/Inspector/NetworkDetail.js +131 -81
  13. package/dist/commonjs/components/Inspector/PerformanceTab.js +20 -10
  14. package/dist/commonjs/components/NetworkIcons.d.ts +14 -0
  15. package/dist/commonjs/components/NetworkIcons.js +93 -1
  16. package/dist/commonjs/components/SegmentedTabs.js +31 -22
  17. package/dist/commonjs/components/TreeNode.js +13 -12
  18. package/dist/commonjs/constants/version.d.ts +1 -1
  19. package/dist/commonjs/constants/version.js +1 -1
  20. package/dist/commonjs/customHooks/bundleAnalyzer.d.ts +6 -2
  21. package/dist/commonjs/customHooks/bundleAnalyzer.js +552 -114
  22. package/dist/commonjs/customHooks/consoleLogger.js +83 -45
  23. package/dist/commonjs/customHooks/networkLogger.js +10 -1
  24. package/dist/commonjs/customHooks/performanceTracker.d.ts +8 -0
  25. package/dist/commonjs/customHooks/performanceTracker.js +44 -3
  26. package/dist/commonjs/decorators/index.d.ts +49 -0
  27. package/dist/commonjs/decorators/index.js +142 -0
  28. package/dist/commonjs/helpers/gaAnalyticsRegistry.d.ts +18 -0
  29. package/dist/commonjs/helpers/gaAnalyticsRegistry.js +174 -0
  30. package/dist/commonjs/helpers/index.d.ts +7 -4
  31. package/dist/commonjs/helpers/index.js +102 -64
  32. package/dist/commonjs/i18n/locales/en.json +53 -4
  33. package/dist/commonjs/index.d.ts +4 -0
  34. package/dist/commonjs/index.js +216 -8
  35. package/dist/commonjs/styles/index.d.ts +4 -1
  36. package/dist/commonjs/styles/index.js +22 -19
  37. package/dist/commonjs/types/enums.d.ts +115 -9
  38. package/dist/commonjs/types/enums.js +103 -2
  39. package/dist/commonjs/types/interfaces.d.ts +19 -0
  40. package/dist/esm/components/AnalyticsEventCard.js +95 -89
  41. package/dist/esm/components/ConsoleLogCard.js +49 -25
  42. package/dist/esm/components/Inspector/AnalyticsFilterModal.d.ts +7 -0
  43. package/dist/esm/components/Inspector/AnalyticsFilterModal.js +964 -0
  44. package/dist/esm/components/Inspector/AnalyticsTab.js +639 -12
  45. package/dist/esm/components/Inspector/BundleTab.d.ts +1 -1
  46. package/dist/esm/components/Inspector/BundleTab.js +860 -403
  47. package/dist/esm/components/Inspector/InspectorContext.js +1 -0
  48. package/dist/esm/components/Inspector/InspectorHeader.js +14 -6
  49. package/dist/esm/components/Inspector/LogDetail.js +223 -111
  50. package/dist/esm/components/Inspector/MainScreen.js +2 -2
  51. package/dist/esm/components/Inspector/NetworkDetail.js +132 -49
  52. package/dist/esm/components/Inspector/PerformanceTab.js +20 -10
  53. package/dist/esm/components/NetworkIcons.d.ts +14 -0
  54. package/dist/esm/components/NetworkIcons.js +78 -0
  55. package/dist/esm/components/SegmentedTabs.js +31 -22
  56. package/dist/esm/components/TreeNode.js +13 -12
  57. package/dist/esm/constants/version.d.ts +1 -1
  58. package/dist/esm/constants/version.js +1 -1
  59. package/dist/esm/customHooks/bundleAnalyzer.d.ts +6 -2
  60. package/dist/esm/customHooks/bundleAnalyzer.js +549 -114
  61. package/dist/esm/customHooks/consoleLogger.js +83 -45
  62. package/dist/esm/customHooks/networkLogger.js +10 -1
  63. package/dist/esm/customHooks/performanceTracker.d.ts +8 -0
  64. package/dist/esm/customHooks/performanceTracker.js +38 -1
  65. package/dist/esm/decorators/index.d.ts +49 -0
  66. package/dist/esm/decorators/index.js +137 -0
  67. package/dist/esm/helpers/gaAnalyticsRegistry.d.ts +18 -0
  68. package/dist/esm/helpers/gaAnalyticsRegistry.js +169 -0
  69. package/dist/esm/helpers/index.d.ts +7 -4
  70. package/dist/esm/helpers/index.js +100 -63
  71. package/dist/esm/i18n/locales/en.json +53 -4
  72. package/dist/esm/index.d.ts +4 -0
  73. package/dist/esm/index.js +190 -8
  74. package/dist/esm/styles/index.d.ts +4 -1
  75. package/dist/esm/styles/index.js +22 -19
  76. package/dist/esm/types/enums.d.ts +115 -9
  77. package/dist/esm/types/enums.js +102 -3
  78. package/dist/esm/types/interfaces.d.ts +19 -0
  79. package/package.json +1 -1
@@ -1,7 +1,6 @@
1
1
  import React from 'react';
2
2
  import { useTranslation } from '../../i18n';
3
3
  import { Image, Linking, Pressable, ScrollView, Text, TextInput, View, } from 'react-native';
4
- import Svg, { Circle } from 'react-native-svg';
5
4
  import { animateNextLayout, useInspector } from './InspectorContext';
6
5
  import TouchableScale from '../TouchableScale';
7
6
  import SegmentedTabs from '../SegmentedTabs';
@@ -17,7 +16,7 @@ import { AppColors } from '../../styles/AppColors';
17
16
  import { AppFonts } from '../../styles/AppFonts';
18
17
  import { METHOD_COLORS } from '../../constants';
19
18
  import { getStatusColor, getSize, formatDateTime, getFetchCommand, getCurlCommand, } from '../../helpers';
20
- import { FailIcon, GlobeIcon, StatusIcon, HeadersIcon, RequestIcon, ResponseIcon, DownloadIcon, ClearIcon, SizeIcon, } from '../NetworkIcons';
19
+ import { FailIcon, StatusIcon, HeadersIcon, RequestIcon, ResponseIcon, DownloadIcon, ClearIcon, SizeIcon, ExternalLinkIcon, ClockIcon, } from '../NetworkIcons';
21
20
  const NetworkDetail = React.memo(() => {
22
21
  const { t } = useTranslation();
23
22
  const { selected, detailDisplayUrl, apiDetailActiveTab, setApiDetailActiveTab, detailSearch, setDetailSearch, reqExpanded, setReqExpanded, resExpanded, setResExpanded, showReqDiff, setShowReqDiff, showResDiff, setShowResDiff, prevRequestData, prevResponseData, logRouteMapRef, } = useInspector();
@@ -73,70 +72,122 @@ const NetworkDetail = React.memo(() => {
73
72
  <View style={{
74
73
  flexDirection: 'row',
75
74
  alignItems: 'center',
76
- gap: 8,
75
+ gap: 6,
76
+ flexWrap: 'wrap',
77
+ flex: 1,
77
78
  }}>
79
+ {/* Method Chip */}
78
80
  <View style={[
79
81
  styles.methodBadge,
80
82
  {
81
83
  backgroundColor: METHOD_COLORS[selected.method] ?? METHOD_COLORS.ALL,
84
+ paddingHorizontal: 8,
85
+ paddingVertical: 4,
86
+ borderRadius: 7,
82
87
  },
83
88
  ]}>
84
89
  <Text style={[
85
90
  styles.methodBadgeText,
86
91
  {
87
92
  color: AppColors.white,
93
+ fontSize: 10.5,
88
94
  },
89
95
  ]}>
90
96
  {selected.method}
91
97
  </Text>
92
98
  </View>
93
99
 
100
+ {/* Status Pill */}
94
101
  {selected.status != null && (<View style={[
95
102
  styles.chip,
96
103
  {
97
104
  backgroundColor: selected.status === 0
98
- ? `${AppColors.errorColor}15`
99
- : `${getStatusColor(selected.status)}15`,
105
+ ? `${AppColors.errorColor}18`
106
+ : `${getStatusColor(selected.status)}18`,
100
107
  borderColor: selected.status === 0
101
108
  ? `${AppColors.errorColor}40`
102
109
  : `${getStatusColor(selected.status)}40`,
110
+ paddingHorizontal: 7,
111
+ paddingVertical: 3.5,
112
+ borderRadius: 7,
103
113
  },
104
114
  ]}>
105
- {selected.status === 0 ? (<FailIcon size={8} color={AppColors.errorColor}/>) : (<Svg width={6} height={6} viewBox="0 0 10 10" fill="none">
106
- <Circle cx="5" cy="5" r="5" fill={getStatusColor(selected.status)}/>
107
- </Svg>)}
115
+ {selected.status === 0 ? (<FailIcon size={8} color={AppColors.errorColor}/>) : (<View style={{
116
+ width: 6,
117
+ height: 6,
118
+ borderRadius: 3,
119
+ backgroundColor: getStatusColor(selected.status),
120
+ }}/>)}
108
121
  <Text style={[
109
122
  styles.chipText,
110
123
  {
111
124
  color: selected.status === 0
112
125
  ? AppColors.errorColor
113
126
  : getStatusColor(selected.status),
127
+ fontFamily: AppFonts.interBold,
128
+ fontSize: 10.5,
114
129
  },
115
130
  ]}>
116
131
  {selected.status === 0
117
132
  ? 'Failed'
118
- : String(selected.status)}
133
+ : `${selected.status} ${selected.status === 200 ? 'OK' : ''}`}
119
134
  </Text>
120
135
  </View>)}
121
136
 
137
+ {/* Duration Pill */}
122
138
  {selected.duration != null && (<View style={[
123
139
  styles.chip,
124
140
  {
125
- backgroundColor: `${AppColors.purple}14`,
126
- borderColor: `${AppColors.purple}2E`,
141
+ backgroundColor: `${AppColors.brandPurple}14`,
142
+ borderColor: `${AppColors.brandPurple}30`,
143
+ paddingHorizontal: 7,
144
+ paddingVertical: 3.5,
145
+ borderRadius: 7,
146
+ gap: 4,
127
147
  },
128
148
  ]}>
149
+ <ClockIcon color={AppColors.brandPurple} size={10}/>
129
150
  <Text style={[
130
151
  styles.chipText,
131
- { color: AppColors.purple },
152
+ {
153
+ color: AppColors.brandPurple,
154
+ fontFamily: AppFonts.interBold,
155
+ fontSize: 10.5,
156
+ },
132
157
  ]}>
133
158
  {selected.duration}ms
134
159
  </Text>
135
160
  </View>)}
161
+
162
+ {/* Size Pill */}
163
+ {selected.response != null && (<View style={[
164
+ styles.chip,
165
+ {
166
+ backgroundColor: `${AppColors.sky600}14`,
167
+ borderColor: `${AppColors.sky600}30`,
168
+ paddingHorizontal: 7,
169
+ paddingVertical: 3.5,
170
+ borderRadius: 7,
171
+ gap: 4,
172
+ },
173
+ ]}>
174
+ <SizeIcon color={AppColors.sky600} size={10}/>
175
+ <Text style={[
176
+ styles.chipText,
177
+ {
178
+ color: AppColors.sky600,
179
+ fontFamily: AppFonts.interBold,
180
+ fontSize: 10.5,
181
+ },
182
+ ]}>
183
+ {getSize(selected.response)}
184
+ </Text>
185
+ </View>)}
136
186
  </View>
187
+
137
188
  <View style={styles.detailInfoRight}>
138
- <TouchableScale style={styles.iconSquareBtn} onPress={() => Linking.openURL(detailDisplayUrl)} hitSlop={12}>
139
- <GlobeIcon color={AppColors.grayTextWeak} size={14}/>
189
+ <TouchableScale style={[styles.iconSquareBtn, { backgroundColor: `${AppColors.sky600}15` }]} onPress={() => Linking.openURL(detailDisplayUrl)} hitSlop={12}>
190
+ <ExternalLinkIcon color={AppColors.sky600} size={14}/>
140
191
  </TouchableScale>
141
192
  <CopyButton value={getFetchCommand(selected)} label="fetch()" iconType="fetch"/>
142
193
  <CopyButton value={getCurlCommand(selected)} label="cURL" iconType="terminal"/>
@@ -144,67 +195,99 @@ const NetworkDetail = React.memo(() => {
144
195
  </View>
145
196
  </View>
146
197
 
198
+ {/* Full Live URL Analysis Card */}
147
199
  <Pressable style={{
148
200
  backgroundColor: AppColors.grayBackground,
149
201
  borderRadius: 10,
150
202
  borderWidth: 1,
151
203
  borderColor: AppColors.dividerColor,
152
204
  padding: 10,
153
- marginTop: 6,
205
+ marginTop: 8,
206
+ gap: 6,
154
207
  }} onPress={() => Linking.openURL(detailDisplayUrl)}>
155
208
  <View style={{
156
209
  flexDirection: 'row',
157
210
  alignItems: 'center',
158
211
  justifyContent: 'space-between',
159
- marginBottom: 2,
160
212
  }}>
161
- <Text style={{
162
- fontFamily: AppFonts.interMedium,
163
- fontSize: 10,
164
- color: AppColors.grayTextWeak,
165
- flex: 1,
166
- }} numberOfLines={1}>
167
- {schemeStr ? (<>
213
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
214
+ {schemeStr ? (<View style={{
215
+ backgroundColor: schemeStr.startsWith('https')
216
+ ? `${AppColors.green600}18`
217
+ : `${AppColors.amber500}18`,
218
+ paddingHorizontal: 6,
219
+ paddingVertical: 2,
220
+ borderRadius: 4,
221
+ }}>
168
222
  <Text style={{
169
- color: AppColors.slate400,
170
- fontFamily: AppFonts.interRegular,
223
+ fontFamily: AppFonts.interBold,
224
+ fontSize: 9,
225
+ color: schemeStr.startsWith('https')
226
+ ? AppColors.green600
227
+ : AppColors.amber500,
171
228
  }}>
172
- {schemeStr}
229
+ {schemeStr.replace('://', '').toUpperCase()}
173
230
  </Text>
174
- {hostStr}
175
- </>) : (hostStr || 'API Endpoint')}
176
- </Text>
177
- {queryStr ? (<View style={{
231
+ </View>) : null}
232
+
233
+ <Text style={{
234
+ fontFamily: AppFonts.interBold,
235
+ fontSize: 10,
236
+ color: AppColors.grayTextWeak,
237
+ letterSpacing: 0.4,
238
+ textTransform: 'uppercase',
239
+ }}>
240
+ ENDPOINT URL ↗
241
+ </Text>
242
+ </View>
243
+
244
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 4 }}>
245
+ {queryStr ? (<View style={{
178
246
  backgroundColor: `${AppColors.purple}14`,
179
- paddingHorizontal: 5,
180
- paddingVertical: 1,
247
+ paddingHorizontal: 6,
248
+ paddingVertical: 2,
181
249
  borderRadius: 4,
182
250
  }}>
183
- <Text style={{
251
+ <Text style={{
184
252
  fontFamily: AppFonts.interBold,
185
253
  fontSize: 8.5,
186
254
  color: AppColors.purple,
187
255
  }}>
188
- {t('network.queryParams')}
256
+ {t('network.queryParams')}
257
+ </Text>
258
+ </View>) : null}
259
+
260
+ <View style={{
261
+ flexDirection: 'row',
262
+ alignItems: 'center',
263
+ gap: 3,
264
+ backgroundColor: `${AppColors.sky600}14`,
265
+ paddingHorizontal: 6,
266
+ paddingVertical: 2,
267
+ borderRadius: 4,
268
+ }}>
269
+ <ExternalLinkIcon color={AppColors.sky600} size={10}/>
270
+ <Text style={{
271
+ fontFamily: AppFonts.interBold,
272
+ fontSize: 9,
273
+ color: AppColors.sky600,
274
+ }}>
275
+ Open ↗
189
276
  </Text>
190
- </View>) : null}
277
+ </View>
278
+ </View>
191
279
  </View>
280
+
281
+ {/* Full Clickable Hyperlink */}
192
282
  <Text selectable={true} style={{
193
- fontFamily: AppFonts.interBold,
194
- fontSize: 12,
195
- color: AppColors.primaryBlack,
196
- marginTop: 2,
197
- }} numberOfLines={2}>
198
- {pathStr}
283
+ fontFamily: AppFonts.interMedium,
284
+ fontSize: 12.5,
285
+ color: AppColors.skyBlue,
286
+ textDecorationLine: 'underline',
287
+ lineHeight: 18,
288
+ }}>
289
+ {detailDisplayUrl}
199
290
  </Text>
200
- {queryStr ? (<Text selectable={true} style={{
201
- fontFamily: AppFonts.interRegular,
202
- fontSize: 10,
203
- color: AppColors.grayTextWeak,
204
- marginTop: 4,
205
- }} numberOfLines={1}>
206
- {queryStr}
207
- </Text>) : null}
208
291
  </Pressable>
209
292
  </>);
210
293
  })()}
@@ -9,6 +9,7 @@ import { AppFonts } from '../../styles/AppFonts';
9
9
  import { useTranslation } from '../../i18n';
10
10
  import { getRuntimeDiagnostics } from '../../helpers';
11
11
  import { SearchIcon, CircleXIcon, PerformanceIcon, BoltIcon, LightbulbIcon, WarningTriangleIcon, MapIcon, AtomIcon, BrainIcon, GlobeIcon, } from '../NetworkIcons';
12
+ import { INITIAL_EVENTS, subscribePerformanceEvents, logPerformanceEvent, clearPerformanceEvents, } from '../../customHooks/performanceTracker';
12
13
  const PerformanceTab = React.memo(() => {
13
14
  const { t } = useTranslation();
14
15
  // ─── Real-Time FPS Tracking ────────────────────────────────────────────────
@@ -34,10 +35,16 @@ const PerformanceTab = React.memo(() => {
34
35
  const [fpsHistory, setFpsHistory] = useState([
35
36
  60, 59, 60, 60, 58, 60, 59, 60, 60, 60, 57, 60, 59, 60, 60, 58, 60, 60, 59, 60,
36
37
  ]);
37
- // Performance Log Events
38
- const [events, setEvents] = useState([]);
38
+ // Performance Log Events (Initialized with benchmark & diagnostics events)
39
+ const [events, setEvents] = useState(INITIAL_EVENTS);
39
40
  const [filterCategory, setFilterCategory] = useState('ALL');
40
41
  const [search, setSearch] = useState('');
42
+ useEffect(() => {
43
+ const unsub = subscribePerformanceEvents(liveEvents => {
44
+ setEvents(liveEvents);
45
+ });
46
+ return unsub;
47
+ }, []);
41
48
  // ─── Live Frame Measurement Loop (1-Second Batch Interval) ────────────────
42
49
  const lastFrameTimeRef = useRef(Date.now());
43
50
  const rafIdRef = useRef(null);
@@ -81,9 +88,7 @@ const PerformanceTab = React.memo(() => {
81
88
  // Trigger log if noticeable frame drop
82
89
  if (measuredFps < 50) {
83
90
  const durationStr = (1000 / measuredFps).toFixed(1);
84
- const newEvent = {
85
- id: `drop-${Date.now()}`,
86
- timestamp: Date.now(),
91
+ logPerformanceEvent({
87
92
  type: 'fps_drop',
88
93
  category: 'render',
89
94
  fps: measuredFps,
@@ -97,8 +102,7 @@ const PerformanceTab = React.memo(() => {
97
102
  },
98
103
  advice: t('performance.liveFpsDipAdvice'),
99
104
  severity: measuredFps < 30 ? 'critical' : 'warning',
100
- };
101
- setEvents(prev => [newEvent, ...prev.slice(0, 49)]);
105
+ });
102
106
  }
103
107
  frameCount = 0;
104
108
  maxLagInSecond = 0;
@@ -208,7 +212,7 @@ const PerformanceTab = React.memo(() => {
208
212
  };
209
213
  }, [avgFps, jsLagMs]);
210
214
  const clearEvents = () => {
211
- setEvents([]);
215
+ clearPerformanceEvents();
212
216
  };
213
217
  return (<View style={perfStyles.container}>
214
218
  {/* Search & Live Control Header */}
@@ -253,9 +257,9 @@ const PerformanceTab = React.memo(() => {
253
257
  </View>
254
258
  </View>
255
259
 
256
- {/* Filter Tabs */}
260
+ {/* ─── Frozen Interactive Filter Tabs Under Search Component ─── */}
257
261
  <View style={perfStyles.filterRow}>
258
- <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={{ gap: 6, paddingHorizontal: 12, paddingVertical: 4 }}>
262
+ <ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={perfStyles.filterScrollContent}>
259
263
  {[
260
264
  { key: 'ALL', label: t('performance.allLogs'), Icon: BoltIcon, count: events.length },
261
265
  {
@@ -652,6 +656,12 @@ const perfStyles = StyleSheet.create({
652
656
  backgroundColor: AppColors.white,
653
657
  borderBottomWidth: 1,
654
658
  borderBottomColor: AppColors.dividerColor,
659
+ paddingVertical: 5,
660
+ },
661
+ filterScrollContent: {
662
+ gap: 6,
663
+ paddingHorizontal: 12,
664
+ paddingVertical: 2,
655
665
  },
656
666
  filterPill: {
657
667
  flexDirection: 'row',
@@ -62,6 +62,7 @@ export declare const ForwardChevronIcon: ({ color, size, }: any) => React.JSX.El
62
62
  export declare const BundleIcon: ({ color, size, }: any) => React.JSX.Element;
63
63
  export declare const LiveStateIcon: ({ color, size, }: any) => React.JSX.Element;
64
64
  export declare const TimelineIcon: ({ color, size, }: any) => React.JSX.Element;
65
+ export declare const RefreshCcwIcon: ({ color, size, }: any) => React.JSX.Element;
65
66
  export declare const StorageIcon: ({ color, size, }: any) => React.JSX.Element;
66
67
  export declare const MetadataIcon: ({ color, size, }: any) => React.JSX.Element;
67
68
  export declare const ReduxIcon: ({ color, size, }: any) => React.JSX.Element;
@@ -78,3 +79,16 @@ export declare const BrainIcon: ({ color, size }: any) => React.JSX.Element;
78
79
  export declare const TextAaIcon: ({ color, size }: any) => React.JSX.Element;
79
80
  export declare const CartIcon: ({ color, size }: any) => React.JSX.Element;
80
81
  export declare const MoneyIcon: ({ color, size }: any) => React.JSX.Element;
82
+ export declare const ExternalLinkIcon: ({ color, size, }: any) => React.JSX.Element;
83
+ export declare const PackageBoxIcon: ({ color, size, }: any) => React.JSX.Element;
84
+ export declare const GitHubIcon: ({ color, size, }: any) => React.JSX.Element;
85
+ export declare const LinkChainIcon: ({ color, size, }: any) => React.JSX.Element;
86
+ export declare const AppleIcon: ({ color, size, }: any) => React.JSX.Element;
87
+ export declare const AndroidIcon: ({ color, size, }: any) => React.JSX.Element;
88
+ export declare const CodeBracketsIcon: ({ color, size, }: any) => React.JSX.Element;
89
+ export declare const FlameIcon: ({ color, size, }: any) => React.JSX.Element;
90
+ export declare const HourglassIcon: ({ color, size, }: any) => React.JSX.Element;
91
+ export declare const PinIcon: ({ color, size, }: any) => React.JSX.Element;
92
+ export declare const RepeatIcon: ({ color, size, }: any) => React.JSX.Element;
93
+ export declare const TargetGoalIcon: ({ color, size, }: any) => React.JSX.Element;
94
+ export declare const UserCheckIcon: ({ color, size, }: any) => React.JSX.Element;
@@ -373,6 +373,11 @@ export const TimelineIcon = ({ color = AppColors.purple, size = 14, }) => {
373
373
  <Path d="M12 7.5v4.5l3 2" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
374
374
  </Svg>);
375
375
  };
376
+ export const RefreshCcwIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
377
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
378
+ <Path d="M3 12a9 9 0 0 1 15-6.7L21 8M21 3v5h-5M21 12a9 9 0 0 1-15 6.7L3 16M3 21v-5h5" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
379
+ </Svg>);
380
+ };
376
381
  export const StorageIcon = ({ color = AppColors.purple, size = 14, }) => {
377
382
  return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
378
383
  <Ellipse cx="12" cy="6" rx="8" ry="2.8" stroke={color} strokeWidth="1.8"/>
@@ -481,3 +486,76 @@ export const MoneyIcon = ({ color = AppColors.emerald500, size = 14 }) => {
481
486
  <Path d="M12 7v10M14.5 9.5c-.6-1-1.5-1.5-2.5-1.5-1.5 0-2.5.9-2.5 2s1 1.8 2.5 2 2.5.8 2.5 2-1 2-2.5 2c-1 0-1.9-.5-2.5-1.5" stroke={color} strokeWidth="1.8" strokeLinecap="round"/>
482
487
  </Svg>);
483
488
  };
489
+ export const ExternalLinkIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
490
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
491
+ <Path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
492
+ <Path d="M15 3h6v6M10 14L21 3" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
493
+ </Svg>);
494
+ };
495
+ export const PackageBoxIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
496
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
497
+ <Path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
498
+ <Path d="M3.27 6.96L12 12.01l8.73-5.05M12 22.08V12" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
499
+ </Svg>);
500
+ };
501
+ export const GitHubIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
502
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
503
+ <Path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
504
+ </Svg>);
505
+ };
506
+ export const LinkChainIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
507
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
508
+ <Path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
509
+ <Path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
510
+ </Svg>);
511
+ };
512
+ export const AppleIcon = ({ color = AppColors.white, size = 12, }) => {
513
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill={color}>
514
+ <Path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M15.97 6.37c.61-.75 1.04-1.8 0.92-2.87-.9.04-1.99.6-2.63 1.35-.56.65-1.06 1.71-.93 2.74 1.01.08 2.03-.47 2.64-1.22z"/>
515
+ </Svg>);
516
+ };
517
+ export const AndroidIcon = ({ color = AppColors.white, size = 12, }) => {
518
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill={color}>
519
+ <Path d="M6 18c0 .55.45 1 1 1h1v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h2v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h1c.55 0 1-.45 1-1V8H6v10zM3.5 8C2.67 8 2 8.67 2 9.5v6c0 .83.67 1.5 1.5 1.5S5 16.33 5 15.5v-6C5 8.67 4.33 8 3.5 8zm17 0c-.83 0-1.5.67-1.5 1.5v6c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5v-6c0-.83-.67-1.5-1.5-1.5zm-4.97-4.84l1.3-1.3c.2-.2.2-.51 0-.71-.2-.2-.51-.2-.71 0l-1.48 1.48C13.85 2.23 12.95 2 12 2c-.96 0-1.86.23-2.66.63L7.85 1.15c-.2-.2-.51-.2-.71 0-.2.2-.2.51 0 .71l1.31 1.31C6.73 4.26 5.54 6 5.16 8h13.68c-.38-2-1.57-3.74-3.31-4.84zM9 6c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm6 0c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z"/>
520
+ </Svg>);
521
+ };
522
+ export const CodeBracketsIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
523
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
524
+ <Path d="M16 18l6-6-6-6M8 6l-6 6 6 6" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
525
+ </Svg>);
526
+ };
527
+ export const FlameIcon = ({ color = AppColors.darkOrange, size = 14, }) => {
528
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
529
+ <Path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 3z" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
530
+ </Svg>);
531
+ };
532
+ export const HourglassIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
533
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
534
+ <Path d="M5 22h14M5 2h14M17 22v-4.172a2 2 0 0 0-.586-1.414L12 12l-4.414 4.414A2 2 0 0 0 7 17.828V22M7 2v4.172a2 2 0 0 0 .586 1.414L12 12l4.414-4.414A2 2 0 0 0 17 6.172V2" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
535
+ </Svg>);
536
+ };
537
+ export const PinIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
538
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
539
+ <Path d="M12 21s-6-5.333-6-10a6 6 0 0 1 12 0c0 4.667-6 10-6 10z" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
540
+ <Circle cx="12" cy="11" r="2" fill={color}/>
541
+ </Svg>);
542
+ };
543
+ export const RepeatIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
544
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
545
+ <Path d="M17 2l4 4-4 4M3 11v-1a4 4 0 0 1 4-4h14M7 22l-4-4 4-4M21 13v1a4 4 0 0 1-4 4H3" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
546
+ </Svg>);
547
+ };
548
+ export const TargetGoalIcon = ({ color = AppColors.brandPurple, size = 14, }) => {
549
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
550
+ <Circle cx="12" cy="12" r="10" stroke={color} strokeWidth="1.8"/>
551
+ <Circle cx="12" cy="12" r="6" stroke={color} strokeWidth="1.8"/>
552
+ <Circle cx="12" cy="12" r="2" fill={color}/>
553
+ </Svg>);
554
+ };
555
+ export const UserCheckIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
556
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
557
+ <Path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
558
+ <Circle cx="9" cy="7" r="4" stroke={color} strokeWidth="1.8"/>
559
+ <Path d="M16 11l2 2 4-4" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
560
+ </Svg>);
561
+ };
@@ -5,39 +5,48 @@ import { AppFonts } from '../styles/AppFonts';
5
5
  const SegmentedTabs = React.memo(({ tabs, activeKey, onChange, style }) => (<View style={[
6
6
  {
7
7
  flexDirection: 'row',
8
- borderRadius: 8,
9
- overflow: 'hidden',
8
+ borderRadius: 10,
9
+ backgroundColor: `${AppColors.slate200}80`,
10
+ padding: 3,
10
11
  borderWidth: 1,
11
12
  borderColor: AppColors.dividerColor,
12
- backgroundColor: AppColors.primaryLight,
13
+ gap: 3,
13
14
  },
14
15
  style,
15
16
  ]}>
16
- {tabs.map((tab, index) => {
17
+ {tabs.map((tab) => {
17
18
  const isActive = activeKey === tab.key;
18
- return (<Pressable key={tab.key} onPress={() => onChange(tab.key)} style={{
19
- flex: 1,
20
- paddingVertical: 8,
21
- paddingHorizontal: 8,
22
- backgroundColor: isActive
23
- ? AppColors.brandPurple
24
- : AppColors.primaryLight,
25
- borderRightWidth: index < tabs.length - 1 ? 1 : 0,
26
- borderRightColor: AppColors.dividerColor,
27
- alignItems: 'center',
28
- justifyContent: 'center',
29
- gap: 4,
30
- flexDirection: 'row',
31
- }}>
19
+ return (<Pressable key={tab.key} onPress={() => onChange(tab.key)} style={({ pressed }) => [
20
+ {
21
+ flex: 1,
22
+ paddingVertical: 7,
23
+ paddingHorizontal: 6,
24
+ borderRadius: 7,
25
+ backgroundColor: isActive
26
+ ? AppColors.brandPurple
27
+ : 'transparent',
28
+ alignItems: 'center',
29
+ justifyContent: 'center',
30
+ gap: 4.5,
31
+ flexDirection: 'row',
32
+ opacity: pressed ? 0.8 : 1,
33
+ },
34
+ isActive && {
35
+ shadowColor: AppColors.brandPurple,
36
+ shadowOffset: { width: 0, height: 1 },
37
+ shadowOpacity: 0.25,
38
+ shadowRadius: 3,
39
+ elevation: 2,
40
+ },
41
+ ]}>
32
42
  {tab.icon ? tab.icon(isActive) : null}
33
43
  <Text style={{
34
44
  fontFamily: AppFonts.interBold,
35
- fontSize: 10,
45
+ fontSize: 10.5,
36
46
  color: isActive
37
47
  ? AppColors.white
38
- : AppColors.grayTextWeak,
39
- textTransform: 'capitalize',
40
- letterSpacing: 0.3,
48
+ : AppColors.grayText,
49
+ letterSpacing: 0.2,
41
50
  }}>
42
51
  {tab.label}
43
52
  </Text>
@@ -12,6 +12,19 @@ const TreeNode = React.memo(function TreeNode({ data, name, level = 0, search, f
12
12
  const open = localOpen;
13
13
  const isObject = typeof data === 'object' && data !== null;
14
14
  const isArray = Array.isArray(data);
15
+ // Declare all hooks at the top unconditionally (prevents "Rendered fewer hooks than expected" error)
16
+ const treeChevronAnim = useRef(new Animated.Value(open ? 1 : 0)).current;
17
+ useEffect(() => {
18
+ Animated.timing(treeChevronAnim, {
19
+ toValue: open ? 1 : 0,
20
+ duration: 160,
21
+ useNativeDriver: true,
22
+ }).start();
23
+ }, [open]);
24
+ const treeChevronRotate = treeChevronAnim.interpolate({
25
+ inputRange: [0, 1],
26
+ outputRange: ['0deg', '180deg'],
27
+ });
15
28
  function renderHighlighted(text) {
16
29
  if (text === 'null' || text === 'undefined') {
17
30
  return [
@@ -68,18 +81,6 @@ const TreeNode = React.memo(function TreeNode({ data, name, level = 0, search, f
68
81
  ? data.map((v, i) => [i, v])
69
82
  : Object.entries(data);
70
83
  const countLabel = isArray ? `[${entries.length}]` : `{${entries.length}}`;
71
- const treeChevronAnim = useRef(new Animated.Value(open ? 1 : 0)).current;
72
- useEffect(() => {
73
- Animated.timing(treeChevronAnim, {
74
- toValue: open ? 1 : 0,
75
- duration: 160,
76
- useNativeDriver: true,
77
- }).start();
78
- }, [open]);
79
- const treeChevronRotate = treeChevronAnim.interpolate({
80
- inputRange: [0, 1],
81
- outputRange: ['0deg', '180deg'],
82
- });
83
84
  return (<View style={indentStyle}>
84
85
  <Pressable style={styles.treeRow} onPress={() => setLocalOpen(v => !v)} hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}>
85
86
  <Animated.View style={{ transform: [{ rotate: treeChevronRotate }], marginRight: 6 }}>
@@ -1 +1 @@
1
- export declare const LIB_VERSION = "1.1.23";
1
+ export declare const LIB_VERSION = "1.1.25";
@@ -1,3 +1,3 @@
1
1
  // AUTO-GENERATED FILE — do not edit by hand.
2
2
  // Regenerated from package.json on every build by scripts/gen-version.js.
3
- export const LIB_VERSION = '1.1.23';
3
+ export const LIB_VERSION = '1.1.25';
@@ -104,12 +104,16 @@ export interface HostBundleAnalysisResult {
104
104
  };
105
105
  }
106
106
  export declare const getHostScriptURL: () => string;
107
+ export declare const trackRuntimeModuleExecution: () => void;
108
+ export declare const trackRuntimeDefine: () => void;
107
109
  /**
108
110
  * Parses raw Metro bundle source code to discover real modules and packages in the host app.
109
111
  */
110
- export declare const parseBundleSource: (bundleText: string, totalBytes: number, scriptURL: string) => HostBundleAnalysisResult;
112
+ export declare const parseBundleSource: (bundleText: string, totalBytes: number, scriptURL: string, isLive?: boolean) => HostBundleAnalysisResult;
111
113
  /**
112
114
  * Automatically fetch and analyze the real running bundle for the host app.
115
+ * Supports dynamic port detection (8081, 8082, 8083, etc.) and parallel dev server probing.
113
116
  */
114
- export declare const analyzeHostAppBundle: () => Promise<HostBundleAnalysisResult>;
117
+ export declare const analyzeHostAppBundle: (forceRefresh?: boolean) => Promise<HostBundleAnalysisResult>;
118
+ export declare const clearCachedBundleAnalysis: () => void;
115
119
  export declare const getCachedBundleAnalysis: () => HostBundleAnalysisResult | null;