react-native-inapp-inspector 2.2.2 → 2.2.3

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 (97) hide show
  1. package/dist/commonjs/constants/version.d.ts +1 -1
  2. package/dist/commonjs/constants/version.js +1 -1
  3. package/dist/esm/constants/version.d.ts +1 -1
  4. package/dist/esm/constants/version.js +1 -1
  5. package/package.json +2 -1
  6. package/src/analytics.ts +35 -0
  7. package/src/bundle.ts +25 -0
  8. package/src/components/AnalyticsDetail.tsx +865 -0
  9. package/src/components/AnalyticsEventCard.tsx +441 -0
  10. package/src/components/AnalyticsGraph.tsx +583 -0
  11. package/src/components/AnimatedEntrance.tsx +64 -0
  12. package/src/components/AppHeaderLogo.tsx +109 -0
  13. package/src/components/BrandCircleIcon.tsx +144 -0
  14. package/src/components/BrandSquareIcon.tsx +144 -0
  15. package/src/components/CodeSnippet.tsx +725 -0
  16. package/src/components/ConsoleLogCard.tsx +628 -0
  17. package/src/components/CopyButton.tsx +87 -0
  18. package/src/components/DiffViewer.tsx +82 -0
  19. package/src/components/DomainHeader.tsx +237 -0
  20. package/src/components/EmptyState.tsx +73 -0
  21. package/src/components/EndOfListFooter.tsx +100 -0
  22. package/src/components/ErrorBoundary.tsx +688 -0
  23. package/src/components/HeadersSection.tsx +192 -0
  24. package/src/components/HighlightText.tsx +100 -0
  25. package/src/components/Inspector/AnalyticsFilterModal.tsx +1250 -0
  26. package/src/components/Inspector/AnalyticsTab.tsx +1336 -0
  27. package/src/components/Inspector/BundleTab.tsx +4731 -0
  28. package/src/components/Inspector/ConsoleTab.tsx +702 -0
  29. package/src/components/Inspector/CrashDetail.tsx +941 -0
  30. package/src/components/Inspector/CrashFilterModal.tsx +721 -0
  31. package/src/components/Inspector/CrashTab.tsx +871 -0
  32. package/src/components/Inspector/FabLauncher.tsx +80 -0
  33. package/src/components/Inspector/InspectorContext.tsx +28 -0
  34. package/src/components/Inspector/InspectorHeader.tsx +973 -0
  35. package/src/components/Inspector/LogDetail.tsx +1427 -0
  36. package/src/components/Inspector/MainScreen.tsx +258 -0
  37. package/src/components/Inspector/NavigationTracker.tsx +13 -0
  38. package/src/components/Inspector/NetworkDetail.tsx +794 -0
  39. package/src/components/Inspector/NetworkTab.tsx +1095 -0
  40. package/src/components/Inspector/NpmUpdateToast.tsx +392 -0
  41. package/src/components/Inspector/PerformanceTab.tsx +1894 -0
  42. package/src/components/Inspector/ReduxDetail.tsx +1651 -0
  43. package/src/components/Inspector/ReduxTab.tsx +954 -0
  44. package/src/components/Inspector/SettingsPanel.tsx +3181 -0
  45. package/src/components/Inspector/TabBar.tsx +187 -0
  46. package/src/components/Inspector/TelemetryConsentModal.tsx +392 -0
  47. package/src/components/Inspector/UpdateAvailableModal.tsx +545 -0
  48. package/src/components/JsonViewer.tsx +486 -0
  49. package/src/components/LogCard.tsx +491 -0
  50. package/src/components/LogSyntaxHighlighter.tsx +178 -0
  51. package/src/components/MetaAccordion.tsx +340 -0
  52. package/src/components/MiniBarChart.tsx +42 -0
  53. package/src/components/MiniLineChart.tsx +33 -0
  54. package/src/components/NetworkIcons.tsx +2118 -0
  55. package/src/components/SectionHeader.tsx +113 -0
  56. package/src/components/SegmentedTabs.tsx +83 -0
  57. package/src/components/Slider.tsx +300 -0
  58. package/src/components/SourcePageCard.tsx +148 -0
  59. package/src/components/Toast.tsx +131 -0
  60. package/src/components/TouchableScale.tsx +91 -0
  61. package/src/components/TreeNode.tsx +186 -0
  62. package/src/console.ts +24 -0
  63. package/src/constants/index.ts +38 -0
  64. package/src/constants/version.ts +3 -0
  65. package/src/crash.ts +32 -0
  66. package/src/customHooks/analyticsLogger.ts +336 -0
  67. package/src/customHooks/bundleAnalyzer.ts +1231 -0
  68. package/src/customHooks/consoleLogger.ts +497 -0
  69. package/src/customHooks/crashHandler.ts +944 -0
  70. package/src/customHooks/logFilters.ts +32 -0
  71. package/src/customHooks/networkLogger.ts +419 -0
  72. package/src/customHooks/performanceTracker.ts +1014 -0
  73. package/src/customHooks/reduxLogger.ts +406 -0
  74. package/src/customHooks/useAccordion.tsx +60 -0
  75. package/src/decorators/index.ts +184 -0
  76. package/src/helpers/gaAnalyticsRegistry.ts +204 -0
  77. package/src/helpers/index.ts +860 -0
  78. package/src/helpers/memoryManager.ts +138 -0
  79. package/src/helpers/searchQueryParser.ts +283 -0
  80. package/src/helpers/settingsStore.ts +171 -0
  81. package/src/helpers/telemetry.ts +505 -0
  82. package/src/helpers/toast.ts +17 -0
  83. package/src/i18n/index.ts +69 -0
  84. package/src/i18n/locales/en.json +1052 -0
  85. package/src/index.tsx +2336 -0
  86. package/src/native/NativeInspector.ts +397 -0
  87. package/src/native/NativeNetworkInspector.ts +24 -0
  88. package/src/network.ts +22 -0
  89. package/src/performance.ts +38 -0
  90. package/src/redux.ts +23 -0
  91. package/src/styles/AppColors.ts +408 -0
  92. package/src/styles/AppFonts.ts +8 -0
  93. package/src/styles/common.ts +209 -0
  94. package/src/styles/index.ts +1570 -0
  95. package/src/types/enums.ts +194 -0
  96. package/src/types/index.ts +34 -0
  97. package/src/types/interfaces.ts +515 -0
@@ -0,0 +1,187 @@
1
+ import React from 'react';
2
+ import {Animated, ScrollView, Text, TouchableOpacity, View} from 'react-native';
3
+ import {useInspector} from './InspectorContext';
4
+ import styles from '../../styles';
5
+ import {AppColors} from '../../styles/AppColors';
6
+ import TouchableScale from '../TouchableScale';
7
+ import {
8
+ SignalIcon,
9
+ TerminalIcon,
10
+ AnalyticsIcon,
11
+ PackageIcon,
12
+ ReduxIcon,
13
+ PerformanceIcon,
14
+ CrashIcon,
15
+ } from '../NetworkIcons';
16
+
17
+ import {isReduxConnected} from '../../customHooks/reduxLogger';
18
+ import {isAnalyticsConnected} from '../../customHooks/analyticsLogger';
19
+ import {triggerNativeHaptic} from '../../native/NativeInspector';
20
+
21
+ const TabBar = React.memo(() => {
22
+ const {
23
+ activeTab,
24
+ switchActiveTab,
25
+ tabVisibility,
26
+ logs,
27
+ consoleLogs,
28
+ analyticsEvents,
29
+ crashRecords,
30
+ lastReadApisCount,
31
+ lastReadLogsCount,
32
+ lastReadCrashesCount,
33
+ unreadPulseAnim,
34
+ } = useInspector();
35
+
36
+ const isReduxAvail = isReduxConnected();
37
+ const isAnalyticsAvail = isAnalyticsConnected();
38
+
39
+ return (
40
+ <View style={styles.tabBarContainer}>
41
+ <ScrollView
42
+ horizontal
43
+ showsHorizontalScrollIndicator={false}
44
+ contentContainerStyle={{paddingRight: 16}}>
45
+ {(
46
+ [
47
+ {
48
+ key: 'apis',
49
+ label: 'APIs',
50
+ count: logs.length,
51
+ icon: 'apis',
52
+ },
53
+ {
54
+ key: 'logs',
55
+ label: 'Logs',
56
+ count: consoleLogs.length,
57
+ icon: 'logs',
58
+ },
59
+ {
60
+ key: 'analytics',
61
+ label: 'Analytics',
62
+ count: analyticsEvents.length,
63
+ icon: 'analytics',
64
+ },
65
+ {
66
+ key: 'redux',
67
+ label: 'Redux',
68
+ count: 0,
69
+ icon: 'redux',
70
+ },
71
+ {
72
+ key: 'bundle',
73
+ label: 'Bundle',
74
+ count: 0,
75
+ icon: 'bundle',
76
+ },
77
+ {
78
+ key: 'performance',
79
+ label: 'Performance',
80
+ count: 0,
81
+ icon: 'performance',
82
+ },
83
+ {
84
+ key: 'crash',
85
+ label: 'Crash',
86
+ count: crashRecords?.length || 0,
87
+ icon: 'crash',
88
+ },
89
+ ] as const
90
+ )
91
+ .filter(tab => {
92
+ if (!tabVisibility?.[tab.key]) return false;
93
+ if (tab.key === 'redux' && !isReduxAvail) return false;
94
+ if (tab.key === 'analytics' && !isAnalyticsAvail) return false;
95
+ return true;
96
+ })
97
+ .map(tab => {
98
+ const isActive = activeTab === tab.key;
99
+ const iconColor = isActive
100
+ ? AppColors.white
101
+ : tab.key === 'crash' && tab.count > 0
102
+ ? AppColors.errorColor
103
+ : AppColors.grayText;
104
+ const countLabel =
105
+ tab.count > 9 ? '9+' : String(tab.count);
106
+ const hasUnreadApis =
107
+ activeTab !== 'apis' &&
108
+ logs.length > lastReadApisCount;
109
+ const hasUnreadLogs =
110
+ activeTab !== 'logs' &&
111
+ consoleLogs.length > lastReadLogsCount;
112
+ const hasUnreadCrashes =
113
+ activeTab !== 'crash' &&
114
+ (crashRecords?.length || 0) > (lastReadCrashesCount || 0);
115
+ return (
116
+ <TouchableScale
117
+ key={tab.key}
118
+ onPress={() => {
119
+ switchActiveTab(tab.key);
120
+ }}
121
+ style={[
122
+ styles.contentTabButton,
123
+ isActive && styles.contentTabButtonActive,
124
+ ]}>
125
+ <View
126
+ style={{
127
+ flexDirection: 'row',
128
+ alignItems: 'center',
129
+ gap: 6,
130
+ }}>
131
+ {tab.icon === 'apis' && (
132
+ <SignalIcon color={iconColor} size={14} />
133
+ )}
134
+ {tab.icon === 'logs' && (
135
+ <TerminalIcon color={iconColor} size={14} />
136
+ )}
137
+ {tab.icon === 'analytics' && (
138
+ <AnalyticsIcon color={iconColor} size={14} />
139
+ )}
140
+ {tab.icon === 'redux' && (
141
+ <ReduxIcon color={iconColor} size={14} />
142
+ )}
143
+ {tab.icon === 'bundle' && (
144
+ <PackageIcon color={iconColor} size={14} />
145
+ )}
146
+ {tab.icon === 'performance' && (
147
+ <PerformanceIcon color={iconColor} size={14} />
148
+ )}
149
+ {tab.icon === 'crash' && (
150
+ <CrashIcon color={iconColor} size={14} />
151
+ )}
152
+ <Text
153
+ numberOfLines={1}
154
+ ellipsizeMode="tail"
155
+ style={[
156
+ styles.contentTabButtonText,
157
+ isActive &&
158
+ styles.contentTabButtonTextActive,
159
+ ]}>
160
+ {tab.label}{' '}
161
+ {tab.count > 0 ? `(${countLabel})` : ''}
162
+ </Text>
163
+ {((tab.key === 'apis' && hasUnreadApis) ||
164
+ (tab.key === 'logs' && hasUnreadLogs) ||
165
+ (tab.key === 'crash' && hasUnreadCrashes)) && (
166
+ <Animated.View
167
+ style={{
168
+ width: 6,
169
+ height: 6,
170
+ borderRadius: 3,
171
+ backgroundColor: AppColors.errorColor,
172
+ marginLeft: 4,
173
+ alignSelf: 'center',
174
+ transform: [{scale: unreadPulseAnim}],
175
+ }}
176
+ />
177
+ )}
178
+ </View>
179
+ </TouchableScale>
180
+ );
181
+ })}
182
+ </ScrollView>
183
+ </View>
184
+ );
185
+ });
186
+
187
+ export default TabBar;
@@ -0,0 +1,392 @@
1
+ import React, {useState, useEffect} from 'react';
2
+ import {
3
+ Modal,
4
+ View,
5
+ Text,
6
+ TouchableOpacity,
7
+ StyleSheet,
8
+ Animated,
9
+ Platform,
10
+ } from 'react-native';
11
+ import Svg, {Path} from 'react-native-svg';
12
+ import {BrandSquareIcon} from '../BrandSquareIcon';
13
+ import {
14
+ getTelemetryConsentStatus,
15
+ setTelemetryConsent,
16
+ sendSessionTelemetryPing,
17
+ } from '../../helpers/telemetry';
18
+
19
+ // ─── Inline Crisp SVG Icons ───────────────────────────────────────────────────
20
+
21
+ const ShieldCheckSvg = ({size = 15, color = '#7C3AED'}: {size?: number; color?: string}) => (
22
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
23
+ <Path
24
+ d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"
25
+ stroke={color}
26
+ strokeWidth="2"
27
+ strokeLinecap="round"
28
+ strokeLinejoin="round"
29
+ />
30
+ <Path
31
+ d="M9 12l2 2 4-4"
32
+ stroke={color}
33
+ strokeWidth="2"
34
+ strokeLinecap="round"
35
+ strokeLinejoin="round"
36
+ />
37
+ </Svg>
38
+ );
39
+
40
+ const CheckSvg = ({size = 14, color = '#FFFFFF'}: {size?: number; color?: string}) => (
41
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
42
+ <Path
43
+ d="M20 6L9 17l-5-5"
44
+ stroke={color}
45
+ strokeWidth="2.4"
46
+ strokeLinecap="round"
47
+ strokeLinejoin="round"
48
+ />
49
+ </Svg>
50
+ );
51
+
52
+ const CloseSvg = ({size = 13, color = '#64748B'}: {size?: number; color?: string}) => (
53
+ <Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
54
+ <Path
55
+ d="M18 6L6 18M6 6l12 12"
56
+ stroke={color}
57
+ strokeWidth="2.2"
58
+ strokeLinecap="round"
59
+ strokeLinejoin="round"
60
+ />
61
+ </Svg>
62
+ );
63
+
64
+ export const TelemetryConsentModal = () => {
65
+ const [visible, setVisible] = useState(false);
66
+ const fadeAnim = useState(new Animated.Value(0))[0];
67
+ const scaleAnim = useState(new Animated.Value(0.92))[0];
68
+
69
+ useEffect(() => {
70
+ let isMounted = true;
71
+ getTelemetryConsentStatus().then(status => {
72
+ if (isMounted && status === 'undetermined') {
73
+ setVisible(true);
74
+ Animated.parallel([
75
+ Animated.timing(fadeAnim, {
76
+ toValue: 1,
77
+ duration: 250,
78
+ useNativeDriver: true,
79
+ }),
80
+ Animated.spring(scaleAnim, {
81
+ toValue: 1,
82
+ friction: 8,
83
+ tension: 45,
84
+ useNativeDriver: true,
85
+ }),
86
+ ]).start();
87
+ }
88
+ });
89
+ return () => {
90
+ isMounted = false;
91
+ };
92
+ }, [fadeAnim, scaleAnim]);
93
+
94
+ const handleDecision = async (granted: boolean) => {
95
+ Animated.parallel([
96
+ Animated.timing(fadeAnim, {
97
+ toValue: 0,
98
+ duration: 180,
99
+ useNativeDriver: true,
100
+ }),
101
+ Animated.timing(scaleAnim, {
102
+ toValue: 0.92,
103
+ duration: 180,
104
+ useNativeDriver: true,
105
+ }),
106
+ ]).start(async () => {
107
+ setVisible(false);
108
+ await setTelemetryConsent(granted);
109
+ if (granted) {
110
+ // Immediately trigger the session initialization ping
111
+ sendSessionTelemetryPing({force: true});
112
+ }
113
+ });
114
+ };
115
+
116
+ if (!visible) return null;
117
+
118
+ return (
119
+ <Modal
120
+ transparent
121
+ visible={visible}
122
+ animationType="none"
123
+ statusBarTranslucent>
124
+ <View style={styles.overlay}>
125
+ <Animated.View
126
+ style={[
127
+ styles.card,
128
+ {
129
+ opacity: fadeAnim,
130
+ transform: [{scale: scaleAnim}],
131
+ },
132
+ ]}>
133
+ {/* Top-Right Dismiss Icon Button */}
134
+ <TouchableOpacity
135
+ style={styles.topCloseButton}
136
+ onPress={() => handleDecision(false)}
137
+ hitSlop={10}
138
+ activeOpacity={0.7}>
139
+ <CloseSvg size={13} color="#64748B" />
140
+ </TouchableOpacity>
141
+
142
+ {/* Centered Enlarged Square Brand Icon Header */}
143
+ <View style={styles.headerSection}>
144
+ <View style={styles.iconHaloRing}>
145
+ <BrandSquareIcon size={54} />
146
+ </View>
147
+
148
+ <Text style={styles.title}>Help Improve In-App Inspector</Text>
149
+ <Text style={styles.subtitle}>Anonymous Diagnostic Insights</Text>
150
+
151
+ {/* Subheading instruction hint badge */}
152
+ <View style={styles.hintBadge}>
153
+ <Text style={styles.hintBadgeText}>
154
+ ⚙️ You can enable or disable this anytime in Settings
155
+ </Text>
156
+ </View>
157
+ </View>
158
+
159
+ {/* Description */}
160
+ <Text style={styles.description}>
161
+ To help us continually enhance tooling performance and compatibility,
162
+ would you mind sharing anonymous diagnostics (such as React Native
163
+ version, JavaScript engine, and device architecture)?
164
+ </Text>
165
+
166
+ {/* Privacy Callout Box */}
167
+ <View style={styles.privacyBadge}>
168
+ <View style={styles.privacyShieldWrapper}>
169
+ <ShieldCheckSvg size={15} color="#7C3AED" />
170
+ </View>
171
+ <Text style={styles.privacyText}>
172
+ <Text style={styles.privacyHighlight}>Privacy Guaranteed:</Text> We
173
+ strictly collect non-identifiable technical metrics. No user data,
174
+ passwords, tokens, or network payload bodies are ever captured.
175
+ </Text>
176
+ </View>
177
+
178
+ {/* Enhanced Action Buttons with Icons */}
179
+ <View style={styles.buttonRow}>
180
+ <TouchableOpacity
181
+ style={styles.declineButton}
182
+ onPress={() => handleDecision(false)}
183
+ activeOpacity={0.7}>
184
+ <CloseSvg size={12} color="#64748B" />
185
+ <Text style={styles.declineText}>Not Now</Text>
186
+ </TouchableOpacity>
187
+
188
+ <TouchableOpacity
189
+ style={styles.allowButton}
190
+ onPress={() => handleDecision(true)}
191
+ activeOpacity={0.85}>
192
+ <CheckSvg size={13} color="#FFFFFF" />
193
+ <Text style={styles.allowText}>Allow & Share</Text>
194
+ </TouchableOpacity>
195
+ </View>
196
+ </Animated.View>
197
+ </View>
198
+ </Modal>
199
+ );
200
+ };
201
+
202
+ const fontStack = Platform.select({
203
+ ios: {
204
+ fontFamily: 'System',
205
+ },
206
+ android: {
207
+ fontFamily: 'sans-serif',
208
+ },
209
+ default: {},
210
+ });
211
+
212
+ const styles = StyleSheet.create({
213
+ overlay: {
214
+ flex: 1,
215
+ backgroundColor: 'rgba(15, 23, 42, 0.56)',
216
+ justifyContent: 'center',
217
+ alignItems: 'center',
218
+ paddingHorizontal: 20,
219
+ zIndex: 999999,
220
+ },
221
+ card: {
222
+ width: '100%',
223
+ maxWidth: 356,
224
+ backgroundColor: '#FFFFFF',
225
+ borderRadius: 24,
226
+ borderWidth: 1,
227
+ borderColor: '#E2E8F0',
228
+ paddingHorizontal: 20,
229
+ paddingTop: 22,
230
+ paddingBottom: 20,
231
+ alignItems: 'center',
232
+ shadowColor: '#0F172A',
233
+ shadowOffset: {width: 0, height: 16},
234
+ shadowOpacity: 0.22,
235
+ shadowRadius: 32,
236
+ elevation: 24,
237
+ },
238
+ topCloseButton: {
239
+ position: 'absolute',
240
+ top: 14,
241
+ right: 14,
242
+ width: 28,
243
+ height: 28,
244
+ borderRadius: 14,
245
+ backgroundColor: '#F8FAFC',
246
+ justifyContent: 'center',
247
+ alignItems: 'center',
248
+ borderWidth: 1,
249
+ borderColor: '#E2E8F0',
250
+ zIndex: 10,
251
+ },
252
+ headerSection: {
253
+ alignItems: 'center',
254
+ width: '100%',
255
+ marginBottom: 4,
256
+ },
257
+ iconHaloRing: {
258
+ width: 66,
259
+ height: 66,
260
+ borderRadius: 20,
261
+ backgroundColor: '#FAF5FF',
262
+ justifyContent: 'center',
263
+ alignItems: 'center',
264
+ borderWidth: 1.5,
265
+ borderColor: '#F3E8FF',
266
+ marginBottom: 8,
267
+ shadowColor: '#7C3AED',
268
+ shadowOffset: {width: 0, height: 4},
269
+ shadowOpacity: 0.16,
270
+ shadowRadius: 10,
271
+ elevation: 4,
272
+ },
273
+ title: {
274
+ fontSize: 17,
275
+ fontWeight: '800',
276
+ color: '#0F172A',
277
+ letterSpacing: -0.4,
278
+ textAlign: 'center',
279
+ lineHeight: 22,
280
+ marginBottom: 2,
281
+ ...fontStack,
282
+ },
283
+ subtitle: {
284
+ fontSize: 11.5,
285
+ fontWeight: '600',
286
+ color: '#7C3AED',
287
+ textAlign: 'center',
288
+ letterSpacing: 0.2,
289
+ marginBottom: 6,
290
+ ...fontStack,
291
+ },
292
+ hintBadge: {
293
+ backgroundColor: '#EDE9FE80',
294
+ borderWidth: 1,
295
+ borderColor: '#DDD6FE',
296
+ borderRadius: 7,
297
+ paddingHorizontal: 8,
298
+ paddingVertical: 2.5,
299
+ marginBottom: 8,
300
+ },
301
+ hintBadgeText: {
302
+ fontSize: 10,
303
+ fontWeight: '600',
304
+ color: '#6D28D9',
305
+ textAlign: 'center',
306
+ ...fontStack,
307
+ },
308
+ description: {
309
+ fontSize: 12,
310
+ lineHeight: 17.5,
311
+ color: '#475569',
312
+ textAlign: 'center',
313
+ marginBottom: 12,
314
+ paddingHorizontal: 2,
315
+ ...fontStack,
316
+ },
317
+ privacyBadge: {
318
+ flexDirection: 'row',
319
+ alignItems: 'flex-start',
320
+ backgroundColor: '#F8FAFC',
321
+ borderRadius: 12,
322
+ paddingVertical: 8,
323
+ paddingHorizontal: 10,
324
+ borderWidth: 1,
325
+ borderColor: '#E2E8F0',
326
+ marginBottom: 14,
327
+ width: '100%',
328
+ },
329
+ privacyShieldWrapper: {
330
+ marginRight: 7,
331
+ marginTop: 1,
332
+ },
333
+ privacyText: {
334
+ flex: 1,
335
+ fontSize: 10.8,
336
+ lineHeight: 15,
337
+ color: '#475569',
338
+ ...fontStack,
339
+ },
340
+ privacyHighlight: {
341
+ fontWeight: '700',
342
+ color: '#1E293B',
343
+ },
344
+ buttonRow: {
345
+ flexDirection: 'row',
346
+ justifyContent: 'space-between',
347
+ alignItems: 'center',
348
+ gap: 10,
349
+ width: '100%',
350
+ },
351
+ declineButton: {
352
+ flex: 1,
353
+ flexDirection: 'row',
354
+ alignItems: 'center',
355
+ justifyContent: 'center',
356
+ gap: 5,
357
+ paddingVertical: 11,
358
+ borderRadius: 12,
359
+ backgroundColor: '#F1F5F9',
360
+ borderWidth: 1,
361
+ borderColor: '#E2E8F0',
362
+ },
363
+ declineText: {
364
+ fontSize: 13,
365
+ fontWeight: '600',
366
+ color: '#475569',
367
+ ...fontStack,
368
+ },
369
+ allowButton: {
370
+ flex: 1,
371
+ flexDirection: 'row',
372
+ alignItems: 'center',
373
+ justifyContent: 'center',
374
+ gap: 5,
375
+ paddingVertical: 11,
376
+ borderRadius: 12,
377
+ backgroundColor: '#7C3AED',
378
+ shadowColor: '#7C3AED',
379
+ shadowOffset: {width: 0, height: 3},
380
+ shadowOpacity: 0.28,
381
+ shadowRadius: 6,
382
+ elevation: 4,
383
+ },
384
+ allowText: {
385
+ fontSize: 13,
386
+ fontWeight: '700',
387
+ color: '#FFFFFF',
388
+ ...fontStack,
389
+ },
390
+ });
391
+
392
+ export default TelemetryConsentModal;