react-native-inapp-inspector 2.2.2 → 2.2.4

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 (159) hide show
  1. package/dist/commonjs/components/AnalyticsDetail.js +5 -1
  2. package/dist/commonjs/components/AnalyticsEventCard.js +2 -1
  3. package/dist/commonjs/components/DiffViewer.js +1 -1
  4. package/dist/commonjs/components/Inspector/BundleTab.js +22 -0
  5. package/dist/commonjs/components/Inspector/DeviceInfoTab.d.ts +3 -0
  6. package/dist/commonjs/components/Inspector/DeviceInfoTab.js +835 -0
  7. package/dist/commonjs/components/Inspector/InspectorHeader.js +12 -14
  8. package/dist/commonjs/components/Inspector/LogDetail.js +6 -3
  9. package/dist/commonjs/components/Inspector/MainScreen.js +7 -3
  10. package/dist/commonjs/components/Inspector/NetworkTab.js +92 -15
  11. package/dist/commonjs/components/Inspector/PerformanceTab.js +38 -12
  12. package/dist/commonjs/components/Inspector/SettingsPanel.js +440 -229
  13. package/dist/commonjs/components/Inspector/StorageTab.d.ts +3 -0
  14. package/dist/commonjs/components/Inspector/StorageTab.js +892 -0
  15. package/dist/commonjs/components/Inspector/TabBar.js +14 -0
  16. package/dist/commonjs/components/Inspector/TelemetryConsentModal.js +11 -2
  17. package/dist/commonjs/components/Inspector/UpdateAvailableModal.js +4 -1
  18. package/dist/commonjs/components/NetworkIcons.d.ts +6 -0
  19. package/dist/commonjs/components/NetworkIcons.js +30 -1
  20. package/dist/commonjs/constants/version.d.ts +1 -1
  21. package/dist/commonjs/constants/version.js +1 -1
  22. package/dist/commonjs/customHooks/bundleAnalyzer.js +44 -22
  23. package/dist/commonjs/customHooks/storageInspector.d.ts +67 -0
  24. package/dist/commonjs/customHooks/storageInspector.js +486 -0
  25. package/dist/commonjs/i18n/locales/en.json +8 -2
  26. package/dist/commonjs/index.d.ts +1 -0
  27. package/dist/commonjs/index.js +16 -1
  28. package/dist/commonjs/storage.d.ts +5 -0
  29. package/dist/commonjs/storage.js +18 -0
  30. package/dist/commonjs/types/enums.d.ts +5 -0
  31. package/dist/commonjs/types/enums.js +5 -0
  32. package/dist/esm/components/AnalyticsDetail.js +6 -2
  33. package/dist/esm/components/AnalyticsEventCard.js +2 -1
  34. package/dist/esm/components/DiffViewer.js +1 -1
  35. package/dist/esm/components/Inspector/BundleTab.js +22 -0
  36. package/dist/esm/components/Inspector/DeviceInfoTab.d.ts +3 -0
  37. package/dist/esm/components/Inspector/DeviceInfoTab.js +796 -0
  38. package/dist/esm/components/Inspector/InspectorHeader.js +13 -15
  39. package/dist/esm/components/Inspector/LogDetail.js +7 -4
  40. package/dist/esm/components/Inspector/MainScreen.js +7 -3
  41. package/dist/esm/components/Inspector/NetworkTab.js +93 -16
  42. package/dist/esm/components/Inspector/PerformanceTab.js +39 -13
  43. package/dist/esm/components/Inspector/SettingsPanel.js +441 -230
  44. package/dist/esm/components/Inspector/StorageTab.d.ts +3 -0
  45. package/dist/esm/components/Inspector/StorageTab.js +853 -0
  46. package/dist/esm/components/Inspector/TabBar.js +15 -1
  47. package/dist/esm/components/Inspector/TelemetryConsentModal.js +11 -2
  48. package/dist/esm/components/Inspector/UpdateAvailableModal.js +4 -1
  49. package/dist/esm/components/NetworkIcons.d.ts +6 -0
  50. package/dist/esm/components/NetworkIcons.js +23 -0
  51. package/dist/esm/constants/version.d.ts +1 -1
  52. package/dist/esm/constants/version.js +1 -1
  53. package/dist/esm/customHooks/bundleAnalyzer.js +44 -22
  54. package/dist/esm/customHooks/storageInspector.d.ts +67 -0
  55. package/dist/esm/customHooks/storageInspector.js +469 -0
  56. package/dist/esm/i18n/locales/en.json +8 -2
  57. package/dist/esm/index.d.ts +1 -0
  58. package/dist/esm/index.js +5 -0
  59. package/dist/esm/storage.d.ts +5 -0
  60. package/dist/esm/storage.js +5 -0
  61. package/dist/esm/types/enums.d.ts +5 -0
  62. package/dist/esm/types/enums.js +5 -0
  63. package/package.json +9 -1
  64. package/src/analytics.ts +35 -0
  65. package/src/bundle.ts +25 -0
  66. package/src/components/AnalyticsDetail.tsx +870 -0
  67. package/src/components/AnalyticsEventCard.tsx +442 -0
  68. package/src/components/AnalyticsGraph.tsx +583 -0
  69. package/src/components/AnimatedEntrance.tsx +64 -0
  70. package/src/components/AppHeaderLogo.tsx +109 -0
  71. package/src/components/BrandCircleIcon.tsx +144 -0
  72. package/src/components/BrandSquareIcon.tsx +144 -0
  73. package/src/components/CodeSnippet.tsx +725 -0
  74. package/src/components/ConsoleLogCard.tsx +628 -0
  75. package/src/components/CopyButton.tsx +87 -0
  76. package/src/components/DiffViewer.tsx +82 -0
  77. package/src/components/DomainHeader.tsx +237 -0
  78. package/src/components/EmptyState.tsx +73 -0
  79. package/src/components/EndOfListFooter.tsx +100 -0
  80. package/src/components/ErrorBoundary.tsx +688 -0
  81. package/src/components/HeadersSection.tsx +192 -0
  82. package/src/components/HighlightText.tsx +100 -0
  83. package/src/components/Inspector/AnalyticsFilterModal.tsx +1250 -0
  84. package/src/components/Inspector/AnalyticsTab.tsx +1336 -0
  85. package/src/components/Inspector/BundleTab.tsx +4760 -0
  86. package/src/components/Inspector/ConsoleTab.tsx +702 -0
  87. package/src/components/Inspector/CrashDetail.tsx +941 -0
  88. package/src/components/Inspector/CrashFilterModal.tsx +721 -0
  89. package/src/components/Inspector/CrashTab.tsx +871 -0
  90. package/src/components/Inspector/DeviceInfoTab.tsx +1204 -0
  91. package/src/components/Inspector/FabLauncher.tsx +80 -0
  92. package/src/components/Inspector/InspectorContext.tsx +28 -0
  93. package/src/components/Inspector/InspectorHeader.tsx +972 -0
  94. package/src/components/Inspector/LogDetail.tsx +1431 -0
  95. package/src/components/Inspector/MainScreen.tsx +262 -0
  96. package/src/components/Inspector/NavigationTracker.tsx +13 -0
  97. package/src/components/Inspector/NetworkDetail.tsx +794 -0
  98. package/src/components/Inspector/NetworkTab.tsx +1183 -0
  99. package/src/components/Inspector/NpmUpdateToast.tsx +392 -0
  100. package/src/components/Inspector/PerformanceTab.tsx +1928 -0
  101. package/src/components/Inspector/ReduxDetail.tsx +1651 -0
  102. package/src/components/Inspector/ReduxTab.tsx +954 -0
  103. package/src/components/Inspector/SettingsPanel.tsx +3447 -0
  104. package/src/components/Inspector/StorageTab.tsx +1048 -0
  105. package/src/components/Inspector/TabBar.tsx +207 -0
  106. package/src/components/Inspector/TelemetryConsentModal.tsx +416 -0
  107. package/src/components/Inspector/UpdateAvailableModal.tsx +557 -0
  108. package/src/components/JsonViewer.tsx +486 -0
  109. package/src/components/LogCard.tsx +491 -0
  110. package/src/components/LogSyntaxHighlighter.tsx +178 -0
  111. package/src/components/MetaAccordion.tsx +340 -0
  112. package/src/components/MiniBarChart.tsx +42 -0
  113. package/src/components/MiniLineChart.tsx +33 -0
  114. package/src/components/NetworkIcons.tsx +2221 -0
  115. package/src/components/SectionHeader.tsx +113 -0
  116. package/src/components/SegmentedTabs.tsx +83 -0
  117. package/src/components/Slider.tsx +300 -0
  118. package/src/components/SourcePageCard.tsx +148 -0
  119. package/src/components/Toast.tsx +131 -0
  120. package/src/components/TouchableScale.tsx +91 -0
  121. package/src/components/TreeNode.tsx +186 -0
  122. package/src/console.ts +24 -0
  123. package/src/constants/index.ts +38 -0
  124. package/src/constants/version.ts +3 -0
  125. package/src/crash.ts +32 -0
  126. package/src/customHooks/analyticsLogger.ts +336 -0
  127. package/src/customHooks/bundleAnalyzer.ts +1256 -0
  128. package/src/customHooks/consoleLogger.ts +497 -0
  129. package/src/customHooks/crashHandler.ts +944 -0
  130. package/src/customHooks/logFilters.ts +32 -0
  131. package/src/customHooks/networkLogger.ts +419 -0
  132. package/src/customHooks/performanceTracker.ts +1014 -0
  133. package/src/customHooks/reduxLogger.ts +406 -0
  134. package/src/customHooks/storageInspector.ts +509 -0
  135. package/src/customHooks/useAccordion.tsx +60 -0
  136. package/src/decorators/index.ts +184 -0
  137. package/src/helpers/gaAnalyticsRegistry.ts +204 -0
  138. package/src/helpers/index.ts +860 -0
  139. package/src/helpers/memoryManager.ts +138 -0
  140. package/src/helpers/searchQueryParser.ts +283 -0
  141. package/src/helpers/settingsStore.ts +171 -0
  142. package/src/helpers/telemetry.ts +505 -0
  143. package/src/helpers/toast.ts +17 -0
  144. package/src/i18n/index.ts +69 -0
  145. package/src/i18n/locales/en.json +1058 -0
  146. package/src/index.tsx +2356 -0
  147. package/src/native/NativeInspector.ts +397 -0
  148. package/src/native/NativeNetworkInspector.ts +24 -0
  149. package/src/network.ts +22 -0
  150. package/src/performance.ts +38 -0
  151. package/src/redux.ts +23 -0
  152. package/src/storage.ts +18 -0
  153. package/src/styles/AppColors.ts +408 -0
  154. package/src/styles/AppFonts.ts +8 -0
  155. package/src/styles/common.ts +209 -0
  156. package/src/styles/index.ts +1570 -0
  157. package/src/types/enums.ts +199 -0
  158. package/src/types/index.ts +34 -0
  159. package/src/types/interfaces.ts +515 -0
@@ -0,0 +1,113 @@
1
+ import React, {useRef, useEffect} from 'react';
2
+ import {Animated, View, Pressable, Text} from 'react-native';
3
+
4
+ // Stylesheet
5
+ import {AppColors} from '../styles/AppColors';
6
+
7
+ // Components
8
+ import CopyButton from './CopyButton';
9
+ import TouchableScale from './TouchableScale';
10
+
11
+ // Assets
12
+ import {
13
+ RequestIcon,
14
+ ResponseIcon,
15
+ HeadersIcon,
16
+ DiffIcon,
17
+ ChevronIcon,
18
+ SearchIcon,
19
+ } from './NetworkIcons';
20
+
21
+ // Stylesheet
22
+ import styles from '../styles';
23
+
24
+ // Type Definition
25
+ import {SectionHeaderProps} from '../types';
26
+
27
+ const SectionHeader = ({
28
+ title,
29
+ value,
30
+ expanded,
31
+ onToggleExpand,
32
+ showDiff,
33
+ isDiffing,
34
+ onToggleDiff,
35
+ showSearch,
36
+ isSearching,
37
+ onToggleSearch,
38
+ }: SectionHeaderProps) => {
39
+ const isOpen = expanded === undefined ? false : !!expanded;
40
+ const chevronAnim = useRef(new Animated.Value(isOpen ? 1 : 0)).current;
41
+ useEffect(() => {
42
+ Animated.timing(chevronAnim, {
43
+ toValue: isOpen ? 1 : 0,
44
+ duration: 220,
45
+ useNativeDriver: true,
46
+ }).start();
47
+ }, [isOpen]);
48
+ const chevronRotate = chevronAnim.interpolate({
49
+ inputRange: [0, 1],
50
+ outputRange: ['0deg', '180deg'],
51
+ });
52
+
53
+ return (
54
+ <View style={styles.sectionHeaderGradient}>
55
+ <View style={styles.sectionHeaderRow}>
56
+ <Pressable
57
+ style={styles.sectionTitleRow}
58
+ onPress={onToggleExpand}
59
+ hitSlop={12}>
60
+ {title === 'Request' || title === 'API' ? (
61
+ <RequestIcon color={AppColors.offerPurple} />
62
+ ) : title === 'Response' ? (
63
+ <ResponseIcon color={AppColors.greenColor} />
64
+ ) : (
65
+ <HeadersIcon color={AppColors.skyBlue} />
66
+ )}
67
+ <Text style={styles.sectionTitle}>{title}</Text>
68
+ </Pressable>
69
+ <View style={styles.sectionHeaderActions}>
70
+ {showSearch && (
71
+ <TouchableScale
72
+ onPress={onToggleSearch}
73
+ hitSlop={12}
74
+ style={[
75
+ styles.iconSquareBtn,
76
+ isSearching ? styles.iconSquareBtnActive : null,
77
+ ]}>
78
+ <SearchIcon
79
+ color={isSearching ? AppColors.skyBlue : AppColors.grayTextWeak}
80
+ size={14}
81
+ />
82
+ </TouchableScale>
83
+ )}
84
+ {showDiff && (
85
+ <TouchableScale
86
+ onPress={onToggleDiff}
87
+ hitSlop={12}
88
+ style={[
89
+ styles.iconSquareBtn,
90
+ isDiffing ? styles.iconSquareBtnActive : null,
91
+ ]}>
92
+ <DiffIcon
93
+ color={isDiffing ? AppColors.skyBlue : AppColors.grayTextWeak}
94
+ size={14}
95
+ />
96
+ </TouchableScale>
97
+ )}
98
+ <CopyButton value={value} label={title} />
99
+ <TouchableScale
100
+ onPress={onToggleExpand}
101
+ hitSlop={12}
102
+ style={styles.iconSquareBtn}>
103
+ <Animated.View style={{transform: [{rotate: chevronRotate}]}}>
104
+ <ChevronIcon color={AppColors.grayTextStrong} size={14} />
105
+ </Animated.View>
106
+ </TouchableScale>
107
+ </View>
108
+ </View>
109
+ </View>
110
+ );
111
+ };
112
+
113
+ export default SectionHeader;
@@ -0,0 +1,83 @@
1
+ import React from 'react';
2
+ import {Pressable, Text, View, ViewStyle} from 'react-native';
3
+ import {AppColors} from '../styles/AppColors';
4
+ import {AppFonts} from '../styles/AppFonts';
5
+
6
+ export interface SegmentedTab {
7
+ key: string;
8
+ label: string;
9
+ icon?: (isActive: boolean) => React.ReactNode;
10
+ }
11
+
12
+ interface SegmentedTabsProps {
13
+ tabs: SegmentedTab[];
14
+ activeKey: string;
15
+ onChange: (key: string) => void;
16
+ style?: ViewStyle | ViewStyle[];
17
+ }
18
+
19
+ const SegmentedTabs = React.memo(({tabs, activeKey, onChange, style}: SegmentedTabsProps) => (
20
+ <View
21
+ style={[
22
+ {
23
+ flexDirection: 'row',
24
+ borderRadius: 10,
25
+ backgroundColor: `${AppColors.slate200}80`,
26
+ padding: 3,
27
+ borderWidth: 1,
28
+ borderColor: AppColors.dividerColor,
29
+ gap: 3,
30
+ },
31
+ style,
32
+ ]}>
33
+ {tabs.map((tab) => {
34
+ const isActive = activeKey === tab.key;
35
+ return (
36
+ <Pressable
37
+ key={tab.key}
38
+ onPress={() => onChange(tab.key)}
39
+ style={({pressed}) => [
40
+ {
41
+ flex: 1,
42
+ paddingVertical: 7,
43
+ paddingHorizontal: 6,
44
+ borderRadius: 7,
45
+ backgroundColor: isActive
46
+ ? AppColors.brandPurple
47
+ : 'transparent',
48
+ alignItems: 'center',
49
+ justifyContent: 'center',
50
+ gap: 4.5,
51
+ flexDirection: 'row',
52
+ opacity: pressed ? 0.8 : 1,
53
+ },
54
+ isActive && {
55
+ shadowColor: AppColors.brandPurple,
56
+ shadowOffset: {width: 0, height: 1},
57
+ shadowOpacity: 0.25,
58
+ shadowRadius: 3,
59
+ elevation: 2,
60
+ },
61
+ ]}>
62
+ {tab.icon ? tab.icon(isActive) : null}
63
+ <Text
64
+ numberOfLines={1}
65
+ ellipsizeMode="tail"
66
+ style={{
67
+ flexShrink: 1,
68
+ fontFamily: AppFonts.interBold,
69
+ fontSize: 10.5,
70
+ color: isActive
71
+ ? AppColors.white
72
+ : AppColors.grayText,
73
+ letterSpacing: 0.2,
74
+ }}>
75
+ {tab.label}
76
+ </Text>
77
+ </Pressable>
78
+ );
79
+ })}
80
+ </View>
81
+ ));
82
+
83
+ export default SegmentedTabs;
@@ -0,0 +1,300 @@
1
+ import React, {useRef, useState, useCallback, useMemo} from 'react';
2
+ import {
3
+ View,
4
+ Text,
5
+ StyleSheet,
6
+ PanResponder,
7
+ LayoutChangeEvent,
8
+ GestureResponderEvent,
9
+ PanResponderGestureState,
10
+ } from 'react-native';
11
+ import {AppColors} from '../styles/AppColors';
12
+ import {AppFonts} from '../styles/AppFonts';
13
+ import TouchableScale from './TouchableScale';
14
+
15
+ export interface SliderProps {
16
+ value: number;
17
+ onValueChange: (value: number) => void;
18
+ min?: number;
19
+ max?: number;
20
+ step?: number;
21
+ formatLabel?: (value: number) => string;
22
+ quickPresets?: number[];
23
+ disabled?: boolean;
24
+ }
25
+
26
+ export const Slider: React.FC<SliderProps> = React.memo(
27
+ ({
28
+ value,
29
+ onValueChange,
30
+ min = 50,
31
+ max = 90,
32
+ step = 5,
33
+ formatLabel = val => `${Math.round(val)}%`,
34
+ quickPresets = [50, 60, 70, 80, 90],
35
+ disabled = false,
36
+ }) => {
37
+ const trackWidthRef = useRef<number>(0);
38
+ const [trackWidth, setTrackWidth] = useState<number>(0);
39
+ const [isDragging, setIsDragging] = useState<boolean>(false);
40
+
41
+ const clampedValue = Math.max(min, Math.min(max, value));
42
+ const percentage = (clampedValue - min) / (max - min || 1);
43
+
44
+ const updateValueFromPosition = useCallback(
45
+ (pageX: number, trackPageX: number) => {
46
+ if (trackWidthRef.current <= 0) return;
47
+ const relativeX = Math.max(
48
+ 0,
49
+ Math.min(trackWidthRef.current, pageX - trackPageX),
50
+ );
51
+ const rawRatio = relativeX / trackWidthRef.current;
52
+ let newValue = min + rawRatio * (max - min);
53
+
54
+ if (step > 0) {
55
+ newValue = Math.round(newValue / step) * step;
56
+ }
57
+ newValue = Math.max(min, Math.min(max, newValue));
58
+ onValueChange(newValue);
59
+ },
60
+ [min, max, step, onValueChange],
61
+ );
62
+
63
+ const trackContainerRef = useRef<View>(null);
64
+ const trackPageXRef = useRef<number>(0);
65
+
66
+ const measureTrack = useCallback(() => {
67
+ if (trackContainerRef.current) {
68
+ trackContainerRef.current.measure((_x, _y, _width, _height, pageX) => {
69
+ trackPageXRef.current = pageX;
70
+ });
71
+ }
72
+ }, []);
73
+
74
+ const panResponder = useMemo(
75
+ () =>
76
+ PanResponder.create({
77
+ onStartShouldSetPanResponder: () => !disabled,
78
+ onMoveShouldSetPanResponder: () => !disabled,
79
+ onPanResponderGrant: (evt: GestureResponderEvent) => {
80
+ setIsDragging(true);
81
+ measureTrack();
82
+ updateValueFromPosition(evt.nativeEvent.pageX, trackPageXRef.current);
83
+ },
84
+ onPanResponderMove: (
85
+ evt: GestureResponderEvent,
86
+ _gestureState: PanResponderGestureState,
87
+ ) => {
88
+ updateValueFromPosition(evt.nativeEvent.pageX, trackPageXRef.current);
89
+ },
90
+ onPanResponderRelease: () => {
91
+ setIsDragging(false);
92
+ },
93
+ onPanResponderTerminate: () => {
94
+ setIsDragging(false);
95
+ },
96
+ }),
97
+ [disabled, measureTrack, updateValueFromPosition],
98
+ );
99
+
100
+ const handleLayout = (e: LayoutChangeEvent) => {
101
+ const w = e.nativeEvent.layout.width;
102
+ trackWidthRef.current = w;
103
+ setTrackWidth(w);
104
+ measureTrack();
105
+ };
106
+
107
+ const thumbPosition = percentage * (trackWidth || 0);
108
+
109
+ return (
110
+ <View style={styles.container}>
111
+ {/* Value Display Row */}
112
+ <View style={styles.valueRow}>
113
+ <Text style={styles.rangeText}>{min}%</Text>
114
+ <View
115
+ style={[
116
+ styles.currentValueBadge,
117
+ isDragging && styles.currentValueBadgeActive,
118
+ ]}>
119
+ <Text style={styles.currentValueText}>{formatLabel(clampedValue)}</Text>
120
+ </View>
121
+ <Text style={styles.rangeText}>{max}%</Text>
122
+ </View>
123
+
124
+ {/* Interactive Track Area */}
125
+ <View
126
+ ref={trackContainerRef}
127
+ onLayout={handleLayout}
128
+ {...panResponder.panHandlers}
129
+ style={styles.touchArea}>
130
+ {/* Background Rail */}
131
+ <View style={styles.rail}>
132
+ {/* Active Filled Bar */}
133
+ <View
134
+ style={[
135
+ styles.fillBar,
136
+ {width: `${Math.round(percentage * 100)}%`},
137
+ ]}
138
+ />
139
+ </View>
140
+
141
+ {/* Draggable Thumb */}
142
+ <View
143
+ style={[
144
+ styles.thumb,
145
+ {
146
+ left: Math.max(
147
+ 0,
148
+ Math.min(
149
+ (trackWidth || 0) - 24,
150
+ thumbPosition - 12,
151
+ ),
152
+ ),
153
+ },
154
+ isDragging && styles.thumbActive,
155
+ ]}>
156
+ <View style={styles.thumbCenterDot} />
157
+ </View>
158
+ </View>
159
+
160
+ {/* Quick Presets */}
161
+ {quickPresets && quickPresets.length > 0 && (
162
+ <View style={styles.presetRow}>
163
+ {quickPresets.map(preset => {
164
+ const isSelected = Math.round(clampedValue) === preset;
165
+ return (
166
+ <TouchableScale
167
+ key={preset}
168
+ onPress={() => onValueChange(preset)}
169
+ style={[
170
+ styles.presetButton,
171
+ isSelected && styles.presetButtonActive,
172
+ ]}>
173
+ <Text
174
+ style={[
175
+ styles.presetText,
176
+ isSelected && styles.presetTextActive,
177
+ ]}>
178
+ {preset}%
179
+ </Text>
180
+ </TouchableScale>
181
+ );
182
+ })}
183
+ </View>
184
+ )}
185
+ </View>
186
+ );
187
+ },
188
+ );
189
+
190
+ const styles = StyleSheet.create({
191
+ container: {
192
+ paddingVertical: 4,
193
+ gap: 8,
194
+ },
195
+ valueRow: {
196
+ flexDirection: 'row',
197
+ alignItems: 'center',
198
+ justifyContent: 'space-between',
199
+ paddingHorizontal: 2,
200
+ },
201
+ rangeText: {
202
+ fontFamily: AppFonts.interMedium,
203
+ fontSize: 11,
204
+ color: AppColors.grayText,
205
+ },
206
+ currentValueBadge: {
207
+ backgroundColor: `${AppColors.purple}1A`,
208
+ borderColor: `${AppColors.purple}33`,
209
+ borderWidth: 1,
210
+ borderRadius: 8,
211
+ paddingHorizontal: 10,
212
+ paddingVertical: 2.5,
213
+ },
214
+ currentValueBadgeActive: {
215
+ backgroundColor: AppColors.purple,
216
+ borderColor: AppColors.purple,
217
+ transform: [{scale: 1.05}],
218
+ },
219
+ currentValueText: {
220
+ fontFamily: AppFonts.interBold,
221
+ fontSize: 12,
222
+ color: AppColors.purple,
223
+ },
224
+ touchArea: {
225
+ height: 36,
226
+ justifyContent: 'center',
227
+ position: 'relative',
228
+ },
229
+ rail: {
230
+ height: 8,
231
+ backgroundColor: `${AppColors.grayTextWeak}2B`,
232
+ borderRadius: 4,
233
+ overflow: 'hidden',
234
+ position: 'relative',
235
+ },
236
+ fillBar: {
237
+ height: '100%',
238
+ backgroundColor: AppColors.purple,
239
+ borderRadius: 4,
240
+ },
241
+ thumb: {
242
+ position: 'absolute',
243
+ width: 24,
244
+ height: 24,
245
+ borderRadius: 12,
246
+ backgroundColor: AppColors.white,
247
+ borderWidth: 2.5,
248
+ borderColor: AppColors.purple,
249
+ alignItems: 'center',
250
+ justifyContent: 'center',
251
+ shadowColor: AppColors.black,
252
+ shadowOffset: {width: 0, height: 2},
253
+ shadowOpacity: 0.18,
254
+ shadowRadius: 3.5,
255
+ elevation: 4,
256
+ },
257
+ thumbActive: {
258
+ transform: [{scale: 1.15}],
259
+ shadowOpacity: 0.28,
260
+ shadowRadius: 5,
261
+ elevation: 6,
262
+ borderColor: AppColors.purple,
263
+ },
264
+ thumbCenterDot: {
265
+ width: 6,
266
+ height: 6,
267
+ borderRadius: 3,
268
+ backgroundColor: AppColors.purple,
269
+ },
270
+ presetRow: {
271
+ flexDirection: 'row',
272
+ alignItems: 'center',
273
+ justifyContent: 'space-between',
274
+ gap: 8,
275
+ marginTop: 2,
276
+ },
277
+ presetButton: {
278
+ flex: 1,
279
+ paddingVertical: 5,
280
+ borderRadius: 7,
281
+ alignItems: 'center',
282
+ backgroundColor: AppColors.grayBackground,
283
+ borderWidth: 1,
284
+ borderColor: AppColors.dividerColor,
285
+ },
286
+ presetButtonActive: {
287
+ backgroundColor: `${AppColors.purple}20`,
288
+ borderColor: AppColors.purple,
289
+ },
290
+ presetText: {
291
+ fontFamily: AppFonts.interBold,
292
+ fontSize: 10.5,
293
+ color: AppColors.grayText,
294
+ },
295
+ presetTextActive: {
296
+ color: AppColors.purple,
297
+ },
298
+ });
299
+
300
+ export default Slider;
@@ -0,0 +1,148 @@
1
+ import React from 'react';
2
+ import {View, Pressable, Text, Animated} from 'react-native';
3
+ import Svg, {Rect, Path} from 'react-native-svg';
4
+
5
+ // Components
6
+ import CopyButton from './CopyButton';
7
+
8
+ // Custom Hooks
9
+ import useAccordion from '../customHooks/useAccordion';
10
+
11
+ // Assets
12
+ import {ChevronIcon} from './NetworkIcons';
13
+
14
+ // Type Definition
15
+ import {SourcePageCardProps} from '../types';
16
+
17
+ // Stylesheet
18
+ import {AppColors} from '../styles/AppColors';
19
+ import styles from '../styles';
20
+
21
+ const SourcePageCard = ({routeInfo}: SourcePageCardProps) => {
22
+ const main = useAccordion(true, 600, 280);
23
+ const params = useAccordion(false, 800, 260);
24
+
25
+ const hasParams =
26
+ routeInfo.params && Object.keys(routeInfo.params).length > 0;
27
+
28
+ return (
29
+ <View style={styles.sourcePageCard}>
30
+ <Pressable onPress={main.toggleOpen} hitSlop={12}>
31
+ <View style={styles.sourcePageAccordionHeader}>
32
+ <View style={styles.sourcePageTop}>
33
+ <View style={styles.sourcePageIcon}>
34
+ <Svg width={14} height={14} viewBox="0 0 24 24" fill="none">
35
+ <Rect
36
+ x="3"
37
+ y="3"
38
+ width="7"
39
+ height="7"
40
+ rx="1.5"
41
+ stroke={AppColors.purple}
42
+ strokeWidth="2"
43
+ />
44
+ <Rect
45
+ x="14"
46
+ y="3"
47
+ width="7"
48
+ height="7"
49
+ rx="1.5"
50
+ stroke={AppColors.purple}
51
+ strokeWidth="2"
52
+ />
53
+ <Rect
54
+ x="3"
55
+ y="14"
56
+ width="7"
57
+ height="7"
58
+ rx="1.5"
59
+ stroke={AppColors.purple}
60
+ strokeWidth="2"
61
+ />
62
+ <Path
63
+ d="M14 17.5h7M17.5 14v7"
64
+ stroke={AppColors.purple}
65
+ strokeWidth="2"
66
+ strokeLinecap="round"
67
+ />
68
+ </Svg>
69
+ </View>
70
+ <View style={{flex: 1}}>
71
+ <Text style={styles.sourcePageLabel}>Source Page</Text>
72
+ <Text style={styles.sourcePageValue} numberOfLines={1}>
73
+ {routeInfo.path}
74
+ </Text>
75
+ </View>
76
+ </View>
77
+ <View style={styles.sourcePageHeaderRight}>
78
+ <CopyButton value={routeInfo.path} label="Source Path" />
79
+ <View style={styles.iconSquareBtn}>
80
+ <Animated.View style={main.chevronStyle}>
81
+ <ChevronIcon color={AppColors.grayTextStrong} size={14} />
82
+ </Animated.View>
83
+ </View>
84
+ </View>
85
+ </View>
86
+ </Pressable>
87
+
88
+ <Animated.View style={main.bodyStyle}>
89
+ {hasParams && (
90
+ <View style={styles.sourceParamsBox}>
91
+ <Pressable onPress={params.toggleOpen} hitSlop={10}>
92
+ <View style={styles.paramsAccordionHeader}>
93
+ <View style={styles.paramsAccordionLeft}>
94
+ <Text style={styles.sourceParamsLabel}>Parameters</Text>
95
+ <View style={styles.headerCountBadge}>
96
+ <Text style={styles.headerCountText}>
97
+ {Object.keys(routeInfo.params).length}
98
+ </Text>
99
+ </View>
100
+ </View>
101
+ <View style={styles.paramsAccordionRight}>
102
+ <CopyButton value={routeInfo.params} label="Parameters" />
103
+ <View style={styles.iconSquareBtn}>
104
+ <Animated.View style={params.chevronStyle}>
105
+ <ChevronIcon color={AppColors.grayTextStrong} size={14} />
106
+ </Animated.View>
107
+ </View>
108
+ </View>
109
+ </View>
110
+ </Pressable>
111
+
112
+ <Animated.View style={params.bodyStyle}>
113
+ <View style={styles.paramsBody}>
114
+ {Object.entries(routeInfo.params).map(([key, val], i, arr) => (
115
+ <View
116
+ key={key}
117
+ style={[
118
+ styles.paramRow,
119
+ i < arr.length - 1 ? styles.paramRowBorder : null,
120
+ ]}>
121
+ <Text style={styles.paramKey}>{key}</Text>
122
+ <View style={styles.paramValueRow}>
123
+ <Text selectable style={styles.paramValue}>
124
+ {typeof val === 'object'
125
+ ? JSON.stringify(val)
126
+ : String(val)}
127
+ </Text>
128
+ <CopyButton
129
+ value={
130
+ typeof val === 'object'
131
+ ? JSON.stringify(val)
132
+ : String(val)
133
+ }
134
+ label={key}
135
+ />
136
+ </View>
137
+ </View>
138
+ ))}
139
+ </View>
140
+ </Animated.View>
141
+ </View>
142
+ )}
143
+ </Animated.View>
144
+ </View>
145
+ );
146
+ };
147
+
148
+ export default SourcePageCard;