react-native-inapp-inspector 1.0.4 → 1.0.5

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 (46) hide show
  1. package/README.md +3 -3
  2. package/dist/commonjs/components/AnalyticsEventCard.js +10 -10
  3. package/dist/commonjs/components/CodeSnippet.js +233 -10
  4. package/dist/commonjs/components/ConsoleLogCard.js +55 -9
  5. package/dist/commonjs/components/CopyButton.js +2 -1
  6. package/dist/commonjs/components/ErrorBoundary.d.ts +20 -0
  7. package/dist/commonjs/components/ErrorBoundary.js +332 -0
  8. package/dist/commonjs/components/NetworkIcons.d.ts +5 -0
  9. package/dist/commonjs/components/NetworkIcons.js +45 -1
  10. package/dist/commonjs/customHooks/reduxLogger.d.ts +4 -0
  11. package/dist/commonjs/customHooks/reduxLogger.js +30 -0
  12. package/dist/commonjs/customHooks/webViewLogger.d.ts +2 -0
  13. package/dist/commonjs/customHooks/webViewLogger.js +281 -246
  14. package/dist/commonjs/helpers/index.js +2 -1
  15. package/dist/commonjs/index.d.ts +5 -3
  16. package/dist/commonjs/index.js +685 -911
  17. package/dist/commonjs/styles/AppColors.d.ts +29 -1
  18. package/dist/commonjs/styles/AppColors.js +38 -2
  19. package/dist/commonjs/styles/index.d.ts +438 -229
  20. package/dist/commonjs/styles/index.js +448 -209
  21. package/dist/commonjs/types/index.d.ts +2 -2
  22. package/dist/esm/components/AnalyticsEventCard.js +10 -10
  23. package/dist/esm/components/CodeSnippet.js +232 -12
  24. package/dist/esm/components/ConsoleLogCard.js +55 -9
  25. package/dist/esm/components/CopyButton.js +2 -1
  26. package/dist/esm/components/ErrorBoundary.d.ts +20 -0
  27. package/dist/esm/components/ErrorBoundary.js +295 -0
  28. package/dist/esm/components/NetworkIcons.d.ts +5 -0
  29. package/dist/esm/components/NetworkIcons.js +39 -0
  30. package/dist/esm/customHooks/reduxLogger.d.ts +4 -0
  31. package/dist/esm/customHooks/reduxLogger.js +23 -0
  32. package/dist/esm/customHooks/webViewLogger.d.ts +2 -0
  33. package/dist/esm/customHooks/webViewLogger.js +281 -246
  34. package/dist/esm/helpers/index.js +2 -1
  35. package/dist/esm/index.d.ts +5 -3
  36. package/dist/esm/index.js +683 -914
  37. package/dist/esm/styles/AppColors.d.ts +29 -1
  38. package/dist/esm/styles/AppColors.js +35 -1
  39. package/dist/esm/styles/index.d.ts +438 -229
  40. package/dist/esm/styles/index.js +412 -209
  41. package/dist/esm/types/index.d.ts +2 -2
  42. package/example/App.tsx +351 -127
  43. package/example/ios/Podfile.lock +26 -0
  44. package/example/package-lock.json +20 -4
  45. package/example/package.json +4 -3
  46. package/package.json +1 -1
@@ -0,0 +1,295 @@
1
+ import React, { Component } from 'react';
2
+ import { StyleSheet, Text, View, ScrollView, TouchableOpacity, Platform } from 'react-native';
3
+ import { AppColors } from '../styles/AppColors';
4
+ import { AppFonts } from '../styles/AppFonts';
5
+ import { copyToClipboard } from '../helpers';
6
+ function parseStackTrace(stack) {
7
+ if (!stack)
8
+ return null;
9
+ const lines = stack.split('\n');
10
+ for (const line of lines) {
11
+ if (line.includes('ErrorBoundary') ||
12
+ line.includes('getDerivedStateFromError') ||
13
+ line.includes('componentDidCatch')) {
14
+ continue;
15
+ }
16
+ // Matching ios format: method@url:line:col
17
+ const iosMatch = line.match(/^([^@]+)@(.*):(\d+):(\d+)$/);
18
+ if (iosMatch) {
19
+ const [, method, file, lineNum, colNum] = iosMatch;
20
+ const cleanFile = file.split('?')[0].split('/').pop() || file;
21
+ return { method: method.trim(), file: cleanFile, line: lineNum, column: colNum };
22
+ }
23
+ // Matching android format: at method (url:line:col) or at url:line:col
24
+ const androidMatch = line.match(/^\s*at\s+(.+)\s+\((.+):(\d+):(\d+)\)$/);
25
+ if (androidMatch) {
26
+ const [, method, file, lineNum, colNum] = androidMatch;
27
+ const cleanFile = file.split('?')[0].split('/').pop() || file;
28
+ return { method: method.trim(), file: cleanFile, line: lineNum, column: colNum };
29
+ }
30
+ const androidMatchSimple = line.match(/^\s*at\s+(.+):(\d+):(\d+)$/);
31
+ if (androidMatchSimple) {
32
+ const [, file, lineNum, colNum] = androidMatchSimple;
33
+ const cleanFile = file.split('?')[0].split('/').pop() || file;
34
+ return { method: 'anonymous', file: cleanFile, line: lineNum, column: colNum };
35
+ }
36
+ }
37
+ return null;
38
+ }
39
+ export class ErrorBoundary extends Component {
40
+ constructor() {
41
+ super(...arguments);
42
+ this.state = {
43
+ hasError: false,
44
+ error: null,
45
+ };
46
+ this.handleReset = () => {
47
+ this.setState({ hasError: false, error: null });
48
+ if (this.props.onReset) {
49
+ this.props.onReset();
50
+ }
51
+ };
52
+ this.handleCopyTrace = () => {
53
+ const error = this.state.error;
54
+ if (error) {
55
+ const isNativeCrash = error.message.includes('Native') || error.message.includes('native') || error.message.includes('Swift') || error.message.includes('Java');
56
+ const parsed = error.stack ? parseStackTrace(error.stack) : null;
57
+ const detailStr = `Crash Source: ${isNativeCrash ? 'Native Crash' : 'JavaScript Crash'}
58
+ Message: ${error.message}
59
+ ${parsed ? `Method: ${parsed.method}\nFile: ${parsed.file}\nLine: ${parsed.line}:${parsed.column}` : ''}
60
+ Stack Trace:
61
+ ${error.stack}`;
62
+ copyToClipboard(detailStr, 'Crash traceback');
63
+ }
64
+ };
65
+ }
66
+ static getDerivedStateFromError(error) {
67
+ return { hasError: true, error };
68
+ }
69
+ componentDidCatch(error, errorInfo) {
70
+ console.error('InAppInspector ErrorBoundary caught a crash:', error, errorInfo);
71
+ }
72
+ render() {
73
+ if (this.state.hasError) {
74
+ const isInline = this.props.fallbackType === 'inline';
75
+ if (isInline) {
76
+ return (<View style={styles.inlineContainer}>
77
+ <Text style={styles.inlineTitle}>⚠️ Inspector Crash</Text>
78
+ <TouchableOpacity style={styles.inlineResetBtn} onPress={this.handleReset}>
79
+ <Text style={styles.inlineResetText}>Reload</Text>
80
+ </TouchableOpacity>
81
+ </View>);
82
+ }
83
+ const error = this.state.error;
84
+ const isNativeCrash = error ? (error.message.includes('Native') || error.message.includes('native') || error.message.includes('Swift') || error.message.includes('Java')) : false;
85
+ const parsed = error && error.stack ? parseStackTrace(error.stack) : null;
86
+ return (<View style={styles.container}>
87
+ <View style={styles.card}>
88
+ <Text style={styles.emoji}>⚠️</Text>
89
+ <Text style={styles.title}>Something went wrong</Text>
90
+
91
+ <View style={{
92
+ flexDirection: 'row',
93
+ alignItems: 'center',
94
+ backgroundColor: isNativeCrash ? 'rgba(239, 68, 68, 0.1)' : 'rgba(245, 158, 11, 0.1)',
95
+ paddingHorizontal: 10,
96
+ paddingVertical: 4,
97
+ borderRadius: 20,
98
+ marginBottom: 12,
99
+ gap: 4
100
+ }}>
101
+ <Text style={{
102
+ fontSize: 10,
103
+ fontWeight: 'bold',
104
+ color: isNativeCrash ? '#EF4444' : '#F59E0B',
105
+ fontFamily: AppFonts.interBold || 'System'
106
+ }}>
107
+ {isNativeCrash ? '🔴 NATIVE CRASH' : '🟡 JAVASCRIPT CRASH'}
108
+ </Text>
109
+ </View>
110
+
111
+ <Text style={styles.subtitle}>
112
+ The In-App Inspector or active view encountered an error. Traceback details are parsed below:
113
+ </Text>
114
+
115
+ {parsed && (<View style={{
116
+ backgroundColor: '#F1F5F9',
117
+ borderRadius: 8,
118
+ padding: 10,
119
+ width: '100%',
120
+ marginBottom: 10,
121
+ borderWidth: 1,
122
+ borderColor: '#E2E8F0',
123
+ gap: 4
124
+ }}>
125
+ <Text style={{ fontSize: 11, color: '#475569', fontFamily: AppFonts.interMedium }} numberOfLines={1}>
126
+ <Text style={{ fontWeight: 'bold' }}>Method:</Text> {parsed.method}
127
+ </Text>
128
+ <Text style={{ fontSize: 11, color: '#475569', fontFamily: AppFonts.interMedium }} numberOfLines={1}>
129
+ <Text style={{ fontWeight: 'bold' }}>File:</Text> {parsed.file}
130
+ </Text>
131
+ <Text style={{ fontSize: 11, color: '#475569', fontFamily: AppFonts.interMedium }}>
132
+ <Text style={{ fontWeight: 'bold' }}>Line:</Text> {parsed.line} <Text style={{ fontWeight: 'bold' }}>Col:</Text> {parsed.column}
133
+ </Text>
134
+ </View>)}
135
+
136
+ {error && (<ScrollView style={styles.scroll} contentContainerStyle={styles.scrollContent}>
137
+ <Text style={styles.code}>
138
+ {error.message}
139
+ {'\n\n'}
140
+ {error.stack}
141
+ </Text>
142
+ </ScrollView>)}
143
+
144
+ <View style={{ width: '100%', gap: 8, marginBottom: 12 }}>
145
+ <TouchableOpacity style={{
146
+ backgroundColor: '#0F172A',
147
+ height: 38,
148
+ borderRadius: 8,
149
+ justifyContent: 'center',
150
+ alignItems: 'center',
151
+ flexDirection: 'row',
152
+ gap: 6
153
+ }} onPress={this.handleCopyTrace}>
154
+ <Text style={{ color: '#FFFFFF', fontSize: 12, fontWeight: 'bold', fontFamily: AppFonts.interBold || 'System' }}>
155
+ 📋 Copy Crash Traceback
156
+ </Text>
157
+ </TouchableOpacity>
158
+ </View>
159
+
160
+ <View style={styles.btnRow}>
161
+ <TouchableOpacity style={styles.resetBtn} onPress={this.handleReset}>
162
+ <Text style={styles.resetBtnText}>Retry / Reload</Text>
163
+ </TouchableOpacity>
164
+
165
+ {this.props.onClose && (<TouchableOpacity style={styles.closeBtn} onPress={this.props.onClose}>
166
+ <Text style={styles.closeBtnText}>Close Inspector</Text>
167
+ </TouchableOpacity>)}
168
+ </View>
169
+ </View>
170
+ </View>);
171
+ }
172
+ return this.props.children;
173
+ }
174
+ }
175
+ const monoFont = Platform.OS === 'ios' ? 'Menlo' : 'monospace';
176
+ const styles = StyleSheet.create({
177
+ container: {
178
+ flex: 1,
179
+ backgroundColor: 'rgba(0,0,0,0.3)',
180
+ justifyContent: 'center',
181
+ alignItems: 'center',
182
+ padding: 16,
183
+ },
184
+ card: {
185
+ width: '100%',
186
+ maxWidth: 400,
187
+ backgroundColor: '#FFFFFF',
188
+ borderRadius: 16,
189
+ padding: 20,
190
+ alignItems: 'center',
191
+ shadowColor: '#000000',
192
+ shadowOffset: { width: 0, height: 4 },
193
+ shadowOpacity: 0.1,
194
+ shadowRadius: 12,
195
+ elevation: 8,
196
+ },
197
+ emoji: {
198
+ fontSize: 40,
199
+ marginBottom: 12,
200
+ },
201
+ title: {
202
+ fontFamily: AppFonts.interBold || 'System',
203
+ fontSize: 18,
204
+ color: '#0F172A',
205
+ marginBottom: 8,
206
+ textAlign: 'center',
207
+ },
208
+ subtitle: {
209
+ fontFamily: AppFonts.interRegular || 'System',
210
+ fontSize: 12,
211
+ color: '#64748B',
212
+ lineHeight: 18,
213
+ textAlign: 'center',
214
+ marginBottom: 16,
215
+ },
216
+ scroll: {
217
+ width: '100%',
218
+ maxHeight: 180,
219
+ backgroundColor: '#F8FAFC',
220
+ borderRadius: 8,
221
+ borderWidth: 1,
222
+ borderColor: '#E2E8F0',
223
+ padding: 10,
224
+ marginBottom: 20,
225
+ },
226
+ scrollContent: {
227
+ paddingBottom: 10,
228
+ },
229
+ code: {
230
+ fontFamily: monoFont,
231
+ fontSize: 11,
232
+ color: '#E11D48',
233
+ },
234
+ btnRow: {
235
+ flexDirection: 'row',
236
+ gap: 12,
237
+ width: '100%',
238
+ },
239
+ resetBtn: {
240
+ flex: 1,
241
+ backgroundColor: AppColors.purple || '#684B9B',
242
+ height: 40,
243
+ borderRadius: 8,
244
+ justifyContent: 'center',
245
+ alignItems: 'center',
246
+ },
247
+ resetBtnText: {
248
+ fontFamily: AppFonts.interBold || 'System',
249
+ fontSize: 13,
250
+ color: '#FFFFFF',
251
+ },
252
+ closeBtn: {
253
+ flex: 1,
254
+ backgroundColor: '#F1F5F9',
255
+ borderWidth: 1,
256
+ borderColor: '#E2E8F0',
257
+ height: 40,
258
+ borderRadius: 8,
259
+ justifyContent: 'center',
260
+ alignItems: 'center',
261
+ },
262
+ closeBtnText: {
263
+ fontFamily: AppFonts.interBold || 'System',
264
+ fontSize: 13,
265
+ color: '#475569',
266
+ },
267
+ inlineContainer: {
268
+ padding: 8,
269
+ backgroundColor: '#FFE4E6',
270
+ borderWidth: 1,
271
+ borderColor: '#FCA5A5',
272
+ borderRadius: 8,
273
+ flexDirection: 'row',
274
+ alignItems: 'center',
275
+ justifyContent: 'space-between',
276
+ margin: 8,
277
+ },
278
+ inlineTitle: {
279
+ fontFamily: AppFonts.interBold || 'System',
280
+ fontSize: 11,
281
+ color: '#991B1B',
282
+ },
283
+ inlineResetBtn: {
284
+ backgroundColor: '#991B1B',
285
+ paddingHorizontal: 10,
286
+ paddingVertical: 4,
287
+ borderRadius: 4,
288
+ },
289
+ inlineResetText: {
290
+ fontFamily: AppFonts.interBold || 'System',
291
+ fontSize: 10,
292
+ color: '#FFFFFF',
293
+ },
294
+ });
295
+ export default ErrorBoundary;
@@ -29,3 +29,8 @@ export declare const FilterIcon: ({ color, size, }: any) => React.JSX.Element;
29
29
  export declare const DownloadIcon: ({ color, size, }: any) => React.JSX.Element;
30
30
  export declare const CloseWhite: ({ color, size }: any) => React.JSX.Element;
31
31
  export declare const WhiteBackNavigation: ({ color, size }: any) => React.JSX.Element;
32
+ export declare const AnalyticsIcon: ({ color, size, }: any) => React.JSX.Element;
33
+ export declare const InsightsIcon: ({ color, size, }: any) => React.JSX.Element;
34
+ export declare const DebugIcon: ({ color, size }: any) => React.JSX.Element;
35
+ export declare const SunIcon: ({ color, size }: any) => React.JSX.Element;
36
+ export declare const MoonIcon: ({ color, size }: any) => React.JSX.Element;
@@ -174,3 +174,42 @@ export const WhiteBackNavigation = ({ color = '#FFFFFF', size = 20 }) => {
174
174
  <Path d="M19 12H5M12 19l-7-7 7-7" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
175
175
  </Svg>);
176
176
  };
177
+ export const AnalyticsIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
178
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
179
+ <Path d="M18 20V10M12 20V4M6 20v-6" stroke={color} strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"/>
180
+ </Svg>);
181
+ };
182
+ export const InsightsIcon = ({ color = AppColors.grayTextWeak, size = 14, }) => {
183
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
184
+ <Path d="M2 17l6-6 4 4 10-10M22 12V7h-5" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
185
+ </Svg>);
186
+ };
187
+ export const DebugIcon = ({ color = '#FFFFFF', size = 18 }) => {
188
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
189
+ {/* Hammer: diagonal from bottom-left to top-right */}
190
+ {/* Handle */}
191
+ <Path d="M6 18l8-8" stroke={color} strokeWidth="2.5" strokeLinecap="round"/>
192
+ {/* Head */}
193
+ <Path d="M13.5 10.5l2-2 1.5 1.5-2 2-1.5-1.5z" fill={color}/>
194
+ <Path d="M15.5 8.5L19 5c.5-.5 1.2-.5 1.7 0s.5 1.2 0 1.7L17.2 10.2" stroke={color} strokeWidth="2" strokeLinecap="round"/>
195
+
196
+ {/* Screwdriver: diagonal from bottom-right to top-left */}
197
+ {/* Handle */}
198
+ <Path d="M15 15l4 4" stroke={color} strokeWidth="3.5" strokeLinecap="round"/>
199
+ {/* Shaft */}
200
+ <Path d="M15 15L8.5 8.5" stroke={color} strokeWidth="2" strokeLinecap="round"/>
201
+ {/* Flat tip */}
202
+ <Path d="M9 9L5 5M4.5 6.5l2-2" stroke={color} strokeWidth="2" strokeLinecap="round"/>
203
+ </Svg>);
204
+ };
205
+ export const SunIcon = ({ color = '#FFFFFF', size = 16 }) => {
206
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
207
+ <Circle cx="12" cy="12" r="5" stroke={color} strokeWidth="2"/>
208
+ <Path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" stroke={color} strokeWidth="2" strokeLinecap="round"/>
209
+ </Svg>);
210
+ };
211
+ export const MoonIcon = ({ color = '#FFFFFF', size = 16 }) => {
212
+ return (<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
213
+ <Path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" fill={color} stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
214
+ </Svg>);
215
+ };
@@ -0,0 +1,4 @@
1
+ export declare const getReduxState: () => any;
2
+ export declare const setReduxState: (state: any) => void;
3
+ export declare const subscribeReduxState: (cb: () => void) => () => void;
4
+ export declare const connectReduxStore: (store: any) => void;
@@ -0,0 +1,23 @@
1
+ let currentReduxState = null;
2
+ const listeners = new Set();
3
+ export const getReduxState = () => currentReduxState;
4
+ export const setReduxState = (state) => {
5
+ currentReduxState = state;
6
+ listeners.forEach(cb => cb());
7
+ };
8
+ export const subscribeReduxState = (cb) => {
9
+ listeners.add(cb);
10
+ return () => {
11
+ listeners.delete(cb);
12
+ };
13
+ };
14
+ export const connectReduxStore = (store) => {
15
+ if (!store || typeof store.getState !== 'function' || typeof store.subscribe !== 'function') {
16
+ console.warn('[NetworkInspector] Invalid Redux store passed to connectReduxStore.');
17
+ return;
18
+ }
19
+ setReduxState(store.getState());
20
+ store.subscribe(() => {
21
+ setReduxState(store.getState());
22
+ });
23
+ };
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  export interface WebViewLog {
2
3
  id: number;
3
4
  type: 'log' | 'info' | 'warn' | 'error';
@@ -9,6 +10,7 @@ export interface WebViewNavState {
9
10
  title?: string;
10
11
  timestamp: number;
11
12
  }
13
+ export declare const WebView: React.ForwardRefExoticComponent<Omit<any, "ref"> & React.RefAttributes<unknown>>;
12
14
  export declare const addWebViewLog: (type: "log" | "info" | "warn" | "error", message: string) => void;
13
15
  export declare const addWebViewNav: (url: string, title?: string) => void;
14
16
  export declare const addWebViewHtml: (url: string, html: string, css?: string, js?: string) => void;