react-native-inapp-inspector 1.1.12 → 1.1.13

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 (45) hide show
  1. package/dist/commonjs/components/AnalyticsDetail.js +64 -21
  2. package/dist/commonjs/components/HighlightText.js +1 -1
  3. package/dist/commonjs/components/JsonViewer.d.ts +3 -1
  4. package/dist/commonjs/components/JsonViewer.js +327 -9
  5. package/dist/commonjs/components/MetaAccordion.d.ts +10 -1
  6. package/dist/commonjs/components/MetaAccordion.js +121 -24
  7. package/dist/commonjs/components/NetworkIcons.d.ts +1 -0
  8. package/dist/commonjs/components/NetworkIcons.js +8 -1
  9. package/dist/commonjs/components/ReduxTreeView.d.ts +12 -3
  10. package/dist/commonjs/components/ReduxTreeView.js +1096 -278
  11. package/dist/commonjs/components/SectionHeader.d.ts +1 -1
  12. package/dist/commonjs/components/SectionHeader.js +7 -1
  13. package/dist/commonjs/constants/version.d.ts +1 -1
  14. package/dist/commonjs/constants/version.js +1 -1
  15. package/dist/commonjs/customHooks/reduxLogger.d.ts +2 -0
  16. package/dist/commonjs/customHooks/reduxLogger.js +2 -0
  17. package/dist/commonjs/helpers/index.d.ts +1 -0
  18. package/dist/commonjs/helpers/index.js +15 -1
  19. package/dist/commonjs/helpers/settingsStore.d.ts +1 -0
  20. package/dist/commonjs/helpers/settingsStore.js +4 -0
  21. package/dist/commonjs/index.js +110 -91
  22. package/dist/commonjs/types/index.d.ts +3 -0
  23. package/dist/esm/components/AnalyticsDetail.js +64 -21
  24. package/dist/esm/components/HighlightText.js +3 -3
  25. package/dist/esm/components/JsonViewer.d.ts +3 -1
  26. package/dist/esm/components/JsonViewer.js +295 -10
  27. package/dist/esm/components/MetaAccordion.d.ts +10 -1
  28. package/dist/esm/components/MetaAccordion.js +90 -26
  29. package/dist/esm/components/NetworkIcons.d.ts +1 -0
  30. package/dist/esm/components/NetworkIcons.js +6 -0
  31. package/dist/esm/components/ReduxTreeView.d.ts +12 -3
  32. package/dist/esm/components/ReduxTreeView.js +1095 -279
  33. package/dist/esm/components/SectionHeader.d.ts +1 -1
  34. package/dist/esm/components/SectionHeader.js +8 -2
  35. package/dist/esm/constants/version.d.ts +1 -1
  36. package/dist/esm/constants/version.js +1 -1
  37. package/dist/esm/customHooks/reduxLogger.d.ts +2 -0
  38. package/dist/esm/customHooks/reduxLogger.js +2 -0
  39. package/dist/esm/helpers/index.d.ts +1 -0
  40. package/dist/esm/helpers/index.js +14 -1
  41. package/dist/esm/helpers/settingsStore.d.ts +1 -0
  42. package/dist/esm/helpers/settingsStore.js +3 -0
  43. package/dist/esm/index.js +111 -92
  44. package/dist/esm/types/index.d.ts +3 -0
  45. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import { SectionHeaderProps } from '../types';
3
- declare const SectionHeader: ({ title, value, expanded, onToggleExpand, showDiff, isDiffing, onToggleDiff, }: SectionHeaderProps) => React.JSX.Element;
3
+ declare const SectionHeader: ({ title, value, expanded, onToggleExpand, showDiff, isDiffing, onToggleDiff, showSearch, isSearching, onToggleSearch, }: SectionHeaderProps) => React.JSX.Element;
4
4
  export default SectionHeader;
@@ -47,7 +47,7 @@ const TouchableScale_1 = __importDefault(require("./TouchableScale"));
47
47
  const NetworkIcons_1 = require("./NetworkIcons");
48
48
  // Stylesheet
49
49
  const styles_1 = __importDefault(require("../styles"));
50
- const SectionHeader = ({ title, value, expanded, onToggleExpand, showDiff, isDiffing, onToggleDiff, }) => {
50
+ const SectionHeader = ({ title, value, expanded, onToggleExpand, showDiff, isDiffing, onToggleDiff, showSearch, isSearching, onToggleSearch, }) => {
51
51
  const isOpen = expanded === undefined ? false : !!expanded;
52
52
  const chevronAnim = (0, react_1.useRef)(new react_native_1.Animated.Value(isOpen ? 1 : 0)).current;
53
53
  (0, react_1.useEffect)(() => {
@@ -68,6 +68,12 @@ const SectionHeader = ({ title, value, expanded, onToggleExpand, showDiff, isDif
68
68
  <react_native_1.Text style={styles_1.default.sectionTitle}>{title}</react_native_1.Text>
69
69
  </react_native_1.Pressable>
70
70
  <react_native_1.View style={styles_1.default.sectionHeaderActions}>
71
+ {showSearch && (<TouchableScale_1.default onPress={onToggleSearch} hitSlop={12} style={[
72
+ styles_1.default.iconSquareBtn,
73
+ isSearching ? styles_1.default.iconSquareBtnActive : null,
74
+ ]}>
75
+ <NetworkIcons_1.SearchIcon color={isSearching ? AppColors_1.AppColors.skyBlue : AppColors_1.AppColors.grayTextWeak} size={14}/>
76
+ </TouchableScale_1.default>)}
71
77
  {showDiff && (<TouchableScale_1.default onPress={onToggleDiff} hitSlop={12} style={[
72
78
  styles_1.default.iconSquareBtn,
73
79
  isDiffing ? styles_1.default.iconSquareBtnActive : null,
@@ -1 +1 @@
1
- export declare const LIB_VERSION = "1.1.12";
1
+ export declare const LIB_VERSION = "1.1.13";
@@ -3,4 +3,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LIB_VERSION = void 0;
4
4
  // AUTO-GENERATED FILE — do not edit by hand.
5
5
  // Regenerated from package.json on every build by scripts/gen-version.js.
6
- exports.LIB_VERSION = '1.1.12';
6
+ exports.LIB_VERSION = '1.1.13';
@@ -4,6 +4,8 @@ export interface ReduxHistoryEntry {
4
4
  payload: any;
5
5
  timestamp: string;
6
6
  affectedSlices: string[];
7
+ prevState?: any;
8
+ nextState?: any;
7
9
  }
8
10
  export declare const getReduxState: () => any;
9
11
  export declare const setReduxAutoRefresh: (val: boolean) => void;
@@ -98,6 +98,8 @@ function recordAction(action, prevState, nextState) {
98
98
  payload,
99
99
  timestamp,
100
100
  affectedSlices,
101
+ prevState,
102
+ nextState,
101
103
  });
102
104
  if (actionHistory.length > MAX_HISTORY) {
103
105
  actionHistory.length = MAX_HISTORY;
@@ -21,3 +21,4 @@ export declare const isAllValuesEmpty: (obj: Record<string, any>) => boolean;
21
21
  export declare const formatDateTimeToAnalytics: (ts: number) => string;
22
22
  export declare const getBundleIdentifier: () => string;
23
23
  export declare const getAppName: () => string;
24
+ export declare const handleOpenExternalLink: (url: string) => void;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getAppName = exports.getBundleIdentifier = exports.formatDateTimeToAnalytics = exports.isAllValuesEmpty = exports.getLocalizedFilePathWithSlash = exports.getLocalizedFilePath = exports.formatDisplayUrl = exports.getDiff = exports.flattenObject = exports.getNavigationInfo = exports.escapeRegex = exports.deduplicateLogs = exports.getFetchCommand = exports.getCurlCommand = exports.getBaseUrl = exports.getPath = exports.copyToClipboard = exports.getSize = exports.getDurationColor = exports.getStatusColor = exports.formatDateTime = exports.getDomainColor = void 0;
3
+ exports.handleOpenExternalLink = exports.getAppName = exports.getBundleIdentifier = exports.formatDateTimeToAnalytics = exports.isAllValuesEmpty = exports.getLocalizedFilePathWithSlash = exports.getLocalizedFilePath = exports.formatDisplayUrl = exports.getDiff = exports.flattenObject = exports.getNavigationInfo = exports.escapeRegex = exports.deduplicateLogs = exports.getFetchCommand = exports.getCurlCommand = exports.getBaseUrl = exports.getPath = exports.copyToClipboard = exports.getSize = exports.getDurationColor = exports.getStatusColor = exports.formatDateTime = exports.getDomainColor = void 0;
4
4
  const react_native_1 = require("react-native");
5
5
  // Stylesheet
6
6
  const AppColors_1 = require("../styles/AppColors");
@@ -327,3 +327,17 @@ const getAppName = () => {
327
327
  return 'App';
328
328
  };
329
329
  exports.getAppName = getAppName;
330
+ const handleOpenExternalLink = (url) => {
331
+ if (!url)
332
+ return;
333
+ react_native_1.Alert.alert('Open Link', `Do you want to open this link in your web browser?\n\n${url}`, [
334
+ { text: 'Cancel', style: 'cancel' },
335
+ {
336
+ text: 'Open',
337
+ onPress: () => {
338
+ react_native_1.Linking.openURL(url).catch(() => { });
339
+ },
340
+ },
341
+ ]);
342
+ };
343
+ exports.handleOpenExternalLink = handleOpenExternalLink;
@@ -27,3 +27,4 @@ export declare function loadSettings(): Promise<PersistedSettings>;
27
27
  export declare function saveSettings(settings: PersistedSettings): void;
28
28
  export declare function clearPersistedSettings(): Promise<void>;
29
29
  export declare const isPersistentStorageAvailable: () => boolean;
30
+ export declare function getCustomStorage(): InspectorStorage | null;
@@ -9,6 +9,7 @@ exports.setCustomStorage = setCustomStorage;
9
9
  exports.loadSettings = loadSettings;
10
10
  exports.saveSettings = saveSettings;
11
11
  exports.clearPersistedSettings = clearPersistedSettings;
12
+ exports.getCustomStorage = getCustomStorage;
12
13
  const react_native_1 = require("react-native");
13
14
  // In-memory fallback (settings survive for the app session only).
14
15
  const memory = new Map();
@@ -90,3 +91,6 @@ const isPersistentStorageAvailable = () => {
90
91
  return customStorage !== null || react_native_1.Platform.OS === 'ios';
91
92
  };
92
93
  exports.isPersistentStorageAvailable = isPersistentStorageAvailable;
94
+ function getCustomStorage() {
95
+ return customStorage;
96
+ }
@@ -193,6 +193,7 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
193
193
  const [sectionFilters, setSectionFilters] = (0, react_1.useState)({});
194
194
  const [collapsedSections, setCollapsedSections] = (0, react_1.useState)(new Set());
195
195
  const [showNetworkMenu, setShowNetworkMenu] = (0, react_1.useState)(false);
196
+ const [showHeaderInfo, setShowHeaderInfo] = (0, react_1.useState)(false);
196
197
  const [showUiMenu, setShowUiMenu] = (0, react_1.useState)(false);
197
198
  const [sortOrder, setSortOrder] = (0, react_1.useState)('newest');
198
199
  // #7 — sort order for the Logs (console) tab
@@ -3750,16 +3751,16 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
3750
3751
  <NetworkIcons_1.WhiteBackNavigation />
3751
3752
  </TouchableScale_1.default>
3752
3753
 
3753
- {selected == null && selectedEvent == null ? (<react_native_1.View style={{
3754
+ {selected == null && selectedEvent == null ? (<TouchableScale_1.default onPress={() => setShowHeaderInfo(prev => !prev)} style={{
3754
3755
  flexDirection: 'row',
3755
3756
  alignItems: 'center',
3756
- gap: 14,
3757
+ gap: 10,
3757
3758
  flex: 1,
3758
3759
  }}>
3759
3760
  <react_native_1.View style={{
3760
- width: 50,
3761
- height: 50,
3762
- borderRadius: 10,
3761
+ width: 38,
3762
+ height: 38,
3763
+ borderRadius: 19,
3763
3764
  backgroundColor: 'rgba(255,255,255,0.13)',
3764
3765
  borderWidth: 1.5,
3765
3766
  borderColor: 'rgba(255,255,255,0.25)',
@@ -3770,17 +3771,13 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
3770
3771
  shadowRadius: 4,
3771
3772
  shadowOffset: { width: 0, height: 2 },
3772
3773
  }}>
3773
- <NetworkIcons_1.BrandSquareIcon size={45}/>
3774
+ <NetworkIcons_1.BrandCircleIcon size={34}/>
3774
3775
  </react_native_1.View>
3775
3776
  <react_native_1.View style={{ gap: 2, flex: 1 }}>
3776
3777
  <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
3777
3778
  <react_native_1.Text style={[styles_1.default.headerTitle]} numberOfLines={1}>
3778
- {(0, helpers_1.getAppName)()}{' '}
3779
- <react_native_1.Text style={{ fontFamily: AppFonts_1.AppFonts.interRegular, fontSize: 13, color: 'rgba(255,255,255,0.6)' }}>
3780
- (Inspector)
3781
- </react_native_1.Text>
3779
+ {(0, helpers_1.getAppName)()}
3782
3780
  </react_native_1.Text>
3783
- {/* #1 — pulsing dot when a newer version is on NPM */}
3784
3781
  {updateAvailable && (<react_native_1.Pressable hitSlop={10} onPress={() => react_native_1.Alert.alert('Update Available', `react-native-inapp-inspector v${latestNpmVersion} is available on NPM (installed: v${constants_1.LIB_VERSION}).`, [
3785
3782
  { text: 'Later', style: 'cancel' },
3786
3783
  {
@@ -3803,98 +3800,120 @@ const NetworkInspector = ({ enabled = true, storage, navigationRef, }) => {
3803
3800
  }}/>
3804
3801
  </react_native_1.Pressable>)}
3805
3802
  </react_native_1.View>
3806
- <react_native_1.Text style={{
3807
- fontFamily: AppFonts_1.AppFonts.interRegular,
3808
- fontSize: 10.5,
3809
- color: 'rgba(255, 255, 255, 0.6)',
3810
- marginTop: 1,
3811
- }} selectable={true} numberOfLines={1}>
3812
- {(0, helpers_1.getBundleIdentifier)()}
3813
- </react_native_1.Text>
3814
3803
  <react_native_1.View style={{
3815
3804
  flexDirection: 'row',
3816
3805
  alignItems: 'center',
3817
- gap: 6,
3818
- marginTop: 4,
3819
- }}>
3820
- {/* OS chip */}
3821
- <react_native_1.View style={{
3822
- flexDirection: 'row',
3823
- alignItems: 'center',
3824
- borderRadius: 6,
3825
- overflow: 'hidden',
3806
+ alignSelf: 'flex-start',
3807
+ backgroundColor: 'rgba(255,255,255,0.1)',
3808
+ borderRadius: 10,
3809
+ paddingHorizontal: 8,
3810
+ paddingVertical: 3,
3811
+ gap: 5,
3826
3812
  borderWidth: 1,
3827
- borderColor: 'rgba(255,255,255,0.18)',
3813
+ borderColor: 'rgba(255,255,255,0.15)',
3828
3814
  }}>
3829
- <react_native_1.View style={{
3830
- paddingHorizontal: 5,
3831
- paddingVertical: 2,
3832
- backgroundColor: 'rgba(255,255,255,0.28)',
3833
- }}>
3834
- <react_native_1.Text style={{
3835
- fontFamily: AppFonts_1.AppFonts.interBold,
3836
- fontSize: 9,
3837
- color: '#FFFFFF',
3838
- letterSpacing: 0.3,
3839
- }}>
3840
- {react_native_1.Platform.OS === 'ios' ? 'iOS' : 'Android'}
3841
- </react_native_1.Text>
3842
- </react_native_1.View>
3843
- <react_native_1.View style={{
3844
- paddingHorizontal: 5,
3845
- paddingVertical: 2,
3846
- backgroundColor: 'rgba(255,255,255,0.12)',
3847
- }}>
3848
- <react_native_1.Text style={{
3849
- fontFamily: AppFonts_1.AppFonts.interMedium,
3850
- fontSize: 9.5,
3851
- color: 'rgba(255,255,255,0.92)',
3852
- }}>
3853
- {String(react_native_1.Platform.Version)}
3854
- </react_native_1.Text>
3855
- </react_native_1.View>
3856
- </react_native_1.View>
3857
-
3858
- {/* npm chip */}
3859
3815
  <react_native_1.View style={{
3860
- flexDirection: 'row',
3861
- alignItems: 'center',
3862
- borderRadius: 6,
3863
- overflow: 'hidden',
3864
- borderWidth: 1,
3865
- borderColor: 'rgba(255,255,255,0.18)',
3816
+ width: 6,
3817
+ height: 6,
3818
+ borderRadius: 3,
3819
+ backgroundColor: '#4ADE80',
3820
+ }}/>
3821
+ <react_native_1.Text style={{
3822
+ fontFamily: AppFonts_1.AppFonts.interMedium,
3823
+ fontSize: 10,
3824
+ color: 'rgba(255, 255, 255, 0.85)',
3825
+ letterSpacing: 0.2,
3826
+ }} numberOfLines={1}>
3827
+ {(0, helpers_1.getBundleIdentifier)()}
3828
+ </react_native_1.Text>
3829
+ <react_native_1.Animated.View style={{
3830
+ transform: [{ rotate: showHeaderInfo ? '180deg' : '0deg' }],
3831
+ marginLeft: 2,
3866
3832
  }}>
3833
+ <NetworkIcons_1.ChevronIcon color="rgba(255,255,255,0.6)" size={12}/>
3834
+ </react_native_1.Animated.View>
3835
+ </react_native_1.View>
3836
+ {showHeaderInfo && (<react_native_1.View style={{
3837
+ flexDirection: 'row',
3838
+ alignItems: 'center',
3839
+ gap: 6,
3840
+ marginTop: 4,
3841
+ }}>
3867
3842
  <react_native_1.View style={{
3868
- paddingHorizontal: 5,
3869
- paddingVertical: 2,
3870
- backgroundColor: 'rgba(255,255,255,0.28)',
3871
- }}>
3872
- <react_native_1.Text style={{
3873
- fontFamily: AppFonts_1.AppFonts.interBold,
3874
- fontSize: 9,
3875
- color: '#FFFFFF',
3876
- letterSpacing: 0.3,
3877
- }}>
3878
- npm
3879
- </react_native_1.Text>
3843
+ flexDirection: 'row',
3844
+ alignItems: 'center',
3845
+ borderRadius: 6,
3846
+ overflow: 'hidden',
3847
+ borderWidth: 1,
3848
+ borderColor: 'rgba(255,255,255,0.18)',
3849
+ }}>
3850
+ <react_native_1.View style={{
3851
+ paddingHorizontal: 5,
3852
+ paddingVertical: 2,
3853
+ backgroundColor: 'rgba(255,255,255,0.28)',
3854
+ }}>
3855
+ <react_native_1.Text style={{
3856
+ fontFamily: AppFonts_1.AppFonts.interBold,
3857
+ fontSize: 9,
3858
+ color: '#FFFFFF',
3859
+ letterSpacing: 0.3,
3860
+ }}>
3861
+ {react_native_1.Platform.OS === 'ios' ? 'iOS' : 'Android'}
3862
+ </react_native_1.Text>
3863
+ </react_native_1.View>
3864
+ <react_native_1.View style={{
3865
+ paddingHorizontal: 5,
3866
+ paddingVertical: 2,
3867
+ backgroundColor: 'rgba(255,255,255,0.12)',
3868
+ }}>
3869
+ <react_native_1.Text style={{
3870
+ fontFamily: AppFonts_1.AppFonts.interMedium,
3871
+ fontSize: 9.5,
3872
+ color: 'rgba(255,255,255,0.92)',
3873
+ }}>
3874
+ {String(react_native_1.Platform.Version)}
3875
+ </react_native_1.Text>
3876
+ </react_native_1.View>
3880
3877
  </react_native_1.View>
3881
3878
  <react_native_1.View style={{
3882
- paddingHorizontal: 5,
3883
- paddingVertical: 2,
3884
- backgroundColor: 'rgba(255,255,255,0.12)',
3885
- }}>
3886
- <react_native_1.Text style={{
3887
- fontFamily: AppFonts_1.AppFonts.interMedium,
3888
- fontSize: 9.5,
3889
- color: 'rgba(255,255,255,0.92)',
3890
- }}>
3891
- v{constants_1.LIB_VERSION}
3892
- </react_native_1.Text>
3879
+ flexDirection: 'row',
3880
+ alignItems: 'center',
3881
+ borderRadius: 6,
3882
+ overflow: 'hidden',
3883
+ borderWidth: 1,
3884
+ borderColor: 'rgba(255,255,255,0.18)',
3885
+ }}>
3886
+ <react_native_1.View style={{
3887
+ paddingHorizontal: 5,
3888
+ paddingVertical: 2,
3889
+ backgroundColor: 'rgba(255,255,255,0.28)',
3890
+ }}>
3891
+ <react_native_1.Text style={{
3892
+ fontFamily: AppFonts_1.AppFonts.interBold,
3893
+ fontSize: 9,
3894
+ color: '#FFFFFF',
3895
+ letterSpacing: 0.3,
3896
+ }}>
3897
+ npm
3898
+ </react_native_1.Text>
3899
+ </react_native_1.View>
3900
+ <react_native_1.View style={{
3901
+ paddingHorizontal: 5,
3902
+ paddingVertical: 2,
3903
+ backgroundColor: 'rgba(255,255,255,0.12)',
3904
+ }}>
3905
+ <react_native_1.Text style={{
3906
+ fontFamily: AppFonts_1.AppFonts.interMedium,
3907
+ fontSize: 9.5,
3908
+ color: 'rgba(255,255,255,0.92)',
3909
+ }}>
3910
+ v{constants_1.LIB_VERSION}
3911
+ </react_native_1.Text>
3912
+ </react_native_1.View>
3893
3913
  </react_native_1.View>
3894
- </react_native_1.View>
3895
- </react_native_1.View>
3914
+ </react_native_1.View>)}
3896
3915
  </react_native_1.View>
3897
- </react_native_1.View>) : null}
3916
+ </TouchableScale_1.default>) : null}
3898
3917
  </react_native_1.View>
3899
3918
 
3900
3919
  <react_native_1.View style={styles_1.default.headerCenter}>
@@ -89,6 +89,9 @@ export interface SectionHeaderProps {
89
89
  showDiff?: boolean;
90
90
  isDiffing?: boolean;
91
91
  onToggleDiff?: () => void;
92
+ showSearch?: boolean;
93
+ isSearching?: boolean;
94
+ onToggleSearch?: () => void;
92
95
  }
93
96
  export interface TreeNodeProps {
94
97
  data: unknown;
@@ -6,6 +6,7 @@ import JsonViewer from './JsonViewer';
6
6
  import TouchableScale from './TouchableScale';
7
7
  // Utils
8
8
  import { AppFonts } from '../styles/AppFonts';
9
+ import { getSize } from '../helpers';
9
10
  // Stylesheet
10
11
  import { AppColors } from '../styles/AppColors';
11
12
  const AnalyticsDetail = ({ event, }) => {
@@ -14,6 +15,26 @@ const AnalyticsDetail = ({ event, }) => {
14
15
  const params = event.params ?? {};
15
16
  const userProperties = event.userProperties ?? {};
16
17
  const upCount = Object.keys(userProperties).length;
18
+ const jsonData = {
19
+ name: event.name,
20
+ params: params,
21
+ ...(upCount > 0 ? { userProperties } : {}),
22
+ };
23
+ const isObject = typeof jsonData === 'object' && jsonData !== null;
24
+ const isArray = Array.isArray(jsonData);
25
+ let typeLabel = typeof jsonData;
26
+ let countLabel = '';
27
+ if (jsonData === null) {
28
+ typeLabel = 'null';
29
+ }
30
+ else if (isArray) {
31
+ typeLabel = 'array';
32
+ countLabel = `${jsonData.length} items`;
33
+ }
34
+ else if (isObject) {
35
+ typeLabel = 'object';
36
+ countLabel = `${Object.keys(jsonData).length} keys`;
37
+ }
17
38
  return (<ScrollView style={[detailStyles.scroll, { backgroundColor: AppColors.grayBackground }]} contentContainerStyle={detailStyles.content} showsVerticalScrollIndicator contentInsetAdjustmentBehavior="never" automaticallyAdjustContentInsets={false}>
18
39
 
19
40
  {/* Clean Toolbar */}
@@ -27,7 +48,8 @@ const AnalyticsDetail = ({ event, }) => {
27
48
  borderBottomColor: AppColors.grayBorderSecondary,
28
49
  backgroundColor: AppColors.primaryLight,
29
50
  }}>
30
- <TouchableScale style={{
51
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
52
+ <TouchableScale style={{
31
53
  flexDirection: 'row',
32
54
  alignItems: 'center',
33
55
  gap: 6,
@@ -42,20 +64,49 @@ const AnalyticsDetail = ({ event, }) => {
42
64
  setExpandDepth(nextDepth);
43
65
  setTreeKey(prev => prev + 1);
44
66
  }}>
45
- <Text style={{
67
+ <Text style={{
46
68
  fontFamily: AppFonts.interBold,
47
69
  fontSize: 12,
48
70
  color: AppColors.purple,
49
71
  }}>
50
- {expandDepth === 99 ? 'Collapse All' : 'Expand All'}
51
- </Text>
52
- </TouchableScale>
72
+ {expandDepth === 99 ? 'Collapse All' : 'Expand All'}
73
+ </Text>
74
+ </TouchableScale>
75
+ <View style={{
76
+ flexDirection: 'row',
77
+ alignItems: 'center',
78
+ backgroundColor: AppColors.grayBackground,
79
+ borderRadius: 6,
80
+ overflow: 'hidden',
81
+ borderWidth: 1,
82
+ borderColor: AppColors.grayBorderSecondary,
83
+ }}>
84
+ <View style={{ paddingHorizontal: 6, paddingVertical: 4, backgroundColor: AppColors.purple + '18' }}>
85
+ <Text style={{ fontFamily: AppFonts.interBold, fontSize: 9, color: AppColors.purple, letterSpacing: 0.3 }}>
86
+ {typeLabel.toUpperCase()}
87
+ </Text>
88
+ </View>
89
+ {countLabel ? (<View style={{ paddingHorizontal: 6, paddingVertical: 4 }}>
90
+ <Text style={{ fontFamily: AppFonts.interMedium, fontSize: 9, color: AppColors.grayText }}>
91
+ {countLabel}
92
+ </Text>
93
+ </View>) : null}
94
+ </View>
95
+ <View style={{
96
+ backgroundColor: AppColors.grayBackground,
97
+ borderRadius: 6,
98
+ paddingHorizontal: 6,
99
+ paddingVertical: 4,
100
+ borderWidth: 1,
101
+ borderColor: AppColors.grayBorderSecondary,
102
+ }}>
103
+ <Text style={{ fontFamily: AppFonts.interMedium, fontSize: 9, color: AppColors.grayText }}>
104
+ {getSize(jsonData)}
105
+ </Text>
106
+ </View>
107
+ </View>
53
108
 
54
- <CopyButton value={JSON.stringify({
55
- name: event.name,
56
- params: params,
57
- ...(upCount > 0 ? { userProperties } : {}),
58
- }, null, 2)} label="Copy JSON"/>
109
+ <CopyButton value={JSON.stringify(jsonData, null, 2)} label="Copy JSON"/>
59
110
  </View>
60
111
 
61
112
  {/* Direct JSON Viewer View */}
@@ -67,15 +118,7 @@ const AnalyticsDetail = ({ event, }) => {
67
118
  marginTop: 16,
68
119
  },
69
120
  ]}>
70
- <JsonViewer key={treeKey} data={{
71
- name: event.name,
72
- params: params,
73
- ...(upCount > 0
74
- ? {
75
- userProperties: userProperties,
76
- }
77
- : {}),
78
- }} defaultExpandDepth={expandDepth}/>
121
+ <JsonViewer key={treeKey} data={jsonData} defaultExpandDepth={expandDepth} fullHeight/>
79
122
  </View>
80
123
  </ScrollView>);
81
124
  };
@@ -87,8 +130,8 @@ const detailStyles = StyleSheet.create({
87
130
  },
88
131
  jsonBlockContainer: {
89
132
  marginHorizontal: 16,
90
- marginTop: 8,
91
- padding: 12,
133
+ marginTop: 16,
134
+ marginBottom: 16,
92
135
  borderWidth: 1,
93
136
  borderRadius: 12,
94
137
  },
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
- import { Text, Linking } from 'react-native';
2
+ import { Text } from 'react-native';
3
3
  // Helpers
4
- import { escapeRegex } from '../helpers';
4
+ import { escapeRegex, handleOpenExternalLink } from '../helpers';
5
5
  const HighlightText = ({ text, search, style, highlightStyle, detectLinks, ...rest }) => {
6
6
  const hasNumberOfLines = 'numberOfLines' in rest;
7
7
  const numLines = hasNumberOfLines ? rest.numberOfLines : 1;
@@ -28,7 +28,7 @@ const HighlightText = ({ text, search, style, highlightStyle, detectLinks, ...re
28
28
  color: '#007AFF', // skyBlue link color
29
29
  textDecorationLine: 'underline',
30
30
  }} onPress={() => {
31
- Linking.openURL(part).catch(() => { });
31
+ handleOpenExternalLink(part);
32
32
  }}>
33
33
  {part}
34
34
  </Text>);
@@ -1,9 +1,11 @@
1
1
  import React from 'react';
2
- declare const JsonViewer: ({ data, search, forceOpen, defaultExpandDepth, wrap, }: {
2
+ declare const JsonViewer: ({ data, search, forceOpen, defaultExpandDepth, wrap, fullHeight, onModeChange, }: {
3
3
  data: unknown;
4
4
  search?: string;
5
5
  forceOpen?: boolean;
6
6
  defaultExpandDepth?: number;
7
7
  wrap?: boolean;
8
+ fullHeight?: boolean;
9
+ onModeChange?: (mode: "pretty" | "raw" | "table") => void;
8
10
  }) => React.JSX.Element;
9
11
  export default JsonViewer;