react-native-inapp-inspector 1.1.0 → 1.1.2

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.
package/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  <p align="center">
4
4
  <picture>
5
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vengatmacuser/react-native-inapp-inspector/main/assets/banner_dark.svg">
6
5
  <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/vengatmacuser/react-native-inapp-inspector/main/assets/banner_light.svg">
7
- <img alt="React Native In-App Inspector Banner" src="https://raw.githubusercontent.com/vengatmacuser/react-native-inapp-inspector/main/assets/banner_light.svg" width="100%">
6
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/vengatmacuser/react-native-inapp-inspector/main/assets/banner_dark.svg">
7
+ <img alt="React Native In-App Inspector Banner" src="https://raw.githubusercontent.com/vengatmacuser/react-native-inapp-inspector/main/assets/banner_dark.svg" width="100%">
8
8
  </picture>
9
9
  </p>
10
10
 
@@ -20,15 +20,15 @@ A self-contained in-app debugging overlay for React Native. Inspect network traf
20
20
 
21
21
  ## Features
22
22
 
23
- | Feature | Description |
24
- |---|---|
25
- | Network inspector | Captures `fetch` and axios `GET`, `POST`, `PUT`, `PATCH`, and `DELETE` calls with URL, method, status, headers, body, response, duration, caller, cURL, and fetch snippets. |
26
- | Insights dashboard | Shows request totals, status breakdowns, latency, payload size, slow requests, and recent activity charts. |
27
- | Console logger | Captures `console.log`, `console.info`, `console.warn`, and `console.error` with source method and caller details. |
28
- | Analytics tracker | Captures manual analytics events and patched `@react-native-firebase/analytics` calls including `logEvent`, `logScreenView`, user properties, and user id. |
29
- | Redux inspector | Connects to a Redux store, displays the live state tree, tracks dispatched actions, affected slices, and action history. |
30
- | WebView inspector | Provides an instrumented `WebView` with console capture, navigation history, HTML/CSS/JS snapshots, and optional loading overlay. |
31
- | Error boundary | Exports an `ErrorBoundary` for catching React errors and wrapping the inspector safely. |
23
+ | Feature | Description |
24
+ | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
25
+ | Network inspector | Captures `fetch` and axios `GET`, `POST`, `PUT`, `PATCH`, and `DELETE` calls with URL, method, status, headers, body, response, duration, caller, cURL, and fetch snippets. |
26
+ | Insights dashboard | Shows request totals, status breakdowns, latency, payload size, slow requests, and recent activity charts. |
27
+ | Console logger | Captures `console.log`, `console.info`, `console.warn`, and `console.error` with source method and caller details. |
28
+ | Analytics tracker | Captures manual analytics events and patched `@react-native-firebase/analytics` calls including `logEvent`, `logScreenView`, user properties, and user id. |
29
+ | Redux inspector | Connects to a Redux store, displays the live state tree, tracks dispatched actions, affected slices, and action history. |
30
+ | WebView inspector | Provides an instrumented `WebView` with console capture, navigation history, HTML/CSS/JS snapshots, and optional loading overlay. |
31
+ | Error boundary | Exports an `ErrorBoundary` for catching React errors and wrapping the inspector safely. |
32
32
 
33
33
  ---
34
34
 
@@ -90,7 +90,9 @@ When mounted, the inspector sets up network logging, clears previous network log
90
90
  If you need to capture requests that happen before the component mounts, call `setupNetworkLogger()` at module level in your app entry file.
91
91
 
92
92
  ```tsx
93
- import NetworkInspector, {setupNetworkLogger} from 'react-native-inapp-inspector';
93
+ import NetworkInspector, {
94
+ setupNetworkLogger,
95
+ } from 'react-native-inapp-inspector';
94
96
 
95
97
  setupNetworkLogger();
96
98
  ```
@@ -214,40 +216,40 @@ import {ErrorBoundary} from 'react-native-inapp-inspector';
214
216
 
215
217
  <ErrorBoundary>
216
218
  <YourComponent />
217
- </ErrorBoundary>
219
+ </ErrorBoundary>;
218
220
  ```
219
221
 
220
222
  ---
221
223
 
222
224
  ## Public API
223
225
 
224
- | Export | Type | Description |
225
- |---|---|---|
226
- | `NetworkInspector` | default component | Floating inspector overlay. Mount once near the root of the app. |
227
- | `setupNetworkLogger()` | function | Patches `fetch`, default axios, and future `axios.create()` instances. |
228
- | `addAxiosInterceptors(instance)` | function | Manually attaches axios interceptors to an existing instance. |
229
- | `clearNetworkLogs()` | function | Clears captured network logs. |
230
- | `subscribeNetworkLogs(callback)` | function | Subscribes to network log updates and returns an unsubscribe function. |
231
- | `setupConsoleLogger()` | function | Patches console methods. |
232
- | `clearConsoleLogs()` | function | Clears captured console logs. |
233
- | `subscribeConsoleLogs(callback)` | function | Subscribes to console log updates and returns an unsubscribe function. |
234
- | `setupAnalyticsLogger(instance)` | function | Patches a Firebase Analytics instance. |
235
- | `logAnalyticsEvent(name, params?, userProperties?)` | function | Adds a manual analytics event to the inspector. |
236
- | `clearAnalyticsEvents()` | function | Clears captured analytics events. |
237
- | `subscribeAnalyticsEvents(callback)` | function | Subscribes to analytics event updates and returns an unsubscribe function. |
238
- | `connectReduxStore(store)` | function | Connects a Redux store for live state and action inspection. |
239
- | `getReduxState()` | function | Returns the latest captured Redux state. |
240
- | `subscribeReduxState(callback)` | function | Subscribes to Redux state updates and returns an unsubscribe function. |
241
- | `WebView` | component | Instrumented WebView wrapper. |
242
- | `getWebViewLogs()` | function | Returns captured WebView console logs. |
243
- | `getWebViewNavHistory()` | function | Returns captured WebView navigation history. |
244
- | `getWebViewHtml()` | function | Returns the latest captured WebView HTML. |
245
- | `getWebViewCss()` | function | Returns the latest captured WebView CSS. |
246
- | `getWebViewJs()` | function | Returns the latest captured WebView JavaScript. |
247
- | `getWebViewHtmlUrl()` | function | Returns the URL for the latest captured WebView source snapshot. |
248
- | `clearWebViewData()` | function | Clears captured WebView logs, navigation, and source data. |
249
- | `subscribeWebView(callback)` | function | Subscribes to WebView data changes and returns an unsubscribe function. |
250
- | `ErrorBoundary` | component | React error boundary component. |
226
+ | Export | Type | Description |
227
+ | --------------------------------------------------- | ----------------- | -------------------------------------------------------------------------- |
228
+ | `NetworkInspector` | default component | Floating inspector overlay. Mount once near the root of the app. |
229
+ | `setupNetworkLogger()` | function | Patches `fetch`, default axios, and future `axios.create()` instances. |
230
+ | `addAxiosInterceptors(instance)` | function | Manually attaches axios interceptors to an existing instance. |
231
+ | `clearNetworkLogs()` | function | Clears captured network logs. |
232
+ | `subscribeNetworkLogs(callback)` | function | Subscribes to network log updates and returns an unsubscribe function. |
233
+ | `setupConsoleLogger()` | function | Patches console methods. |
234
+ | `clearConsoleLogs()` | function | Clears captured console logs. |
235
+ | `subscribeConsoleLogs(callback)` | function | Subscribes to console log updates and returns an unsubscribe function. |
236
+ | `setupAnalyticsLogger(instance)` | function | Patches a Firebase Analytics instance. |
237
+ | `logAnalyticsEvent(name, params?, userProperties?)` | function | Adds a manual analytics event to the inspector. |
238
+ | `clearAnalyticsEvents()` | function | Clears captured analytics events. |
239
+ | `subscribeAnalyticsEvents(callback)` | function | Subscribes to analytics event updates and returns an unsubscribe function. |
240
+ | `connectReduxStore(store)` | function | Connects a Redux store for live state and action inspection. |
241
+ | `getReduxState()` | function | Returns the latest captured Redux state. |
242
+ | `subscribeReduxState(callback)` | function | Subscribes to Redux state updates and returns an unsubscribe function. |
243
+ | `WebView` | component | Instrumented WebView wrapper. |
244
+ | `getWebViewLogs()` | function | Returns captured WebView console logs. |
245
+ | `getWebViewNavHistory()` | function | Returns captured WebView navigation history. |
246
+ | `getWebViewHtml()` | function | Returns the latest captured WebView HTML. |
247
+ | `getWebViewCss()` | function | Returns the latest captured WebView CSS. |
248
+ | `getWebViewJs()` | function | Returns the latest captured WebView JavaScript. |
249
+ | `getWebViewHtmlUrl()` | function | Returns the URL for the latest captured WebView source snapshot. |
250
+ | `clearWebViewData()` | function | Clears captured WebView logs, navigation, and source data. |
251
+ | `subscribeWebView(callback)` | function | Subscribes to WebView data changes and returns an unsubscribe function. |
252
+ | `ErrorBoundary` | component | React error boundary component. |
251
253
 
252
254
  ---
253
255
 
@@ -1,8 +1,9 @@
1
1
  import React from 'react';
2
- declare const JsonViewer: ({ data, search, forceOpen, defaultExpandDepth, }: {
2
+ declare const JsonViewer: ({ data, search, forceOpen, defaultExpandDepth, wrap, }: {
3
3
  data: unknown;
4
4
  search?: string;
5
5
  forceOpen?: boolean;
6
6
  defaultExpandDepth?: number;
7
+ wrap?: boolean;
7
8
  }) => React.JSX.Element;
8
9
  export default JsonViewer;
@@ -9,11 +9,13 @@ const react_native_1 = require("react-native");
9
9
  const TreeNode_1 = __importDefault(require("./TreeNode"));
10
10
  // Stylesheet
11
11
  const styles_1 = __importDefault(require("../styles"));
12
- const JsonViewer = ({ data, search, forceOpen, defaultExpandDepth, }) => {
12
+ const JsonViewer = ({ data, search, forceOpen, defaultExpandDepth, wrap, }) => {
13
+ const tree = (<TreeNode_1.default data={data} search={search} forceOpen={forceOpen} defaultExpandDepth={defaultExpandDepth}/>);
14
+ if (wrap) {
15
+ return <react_native_1.View style={[styles_1.default.codeBlock, { width: '100%' }]}>{tree}</react_native_1.View>;
16
+ }
13
17
  return (<react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={true} style={styles_1.default.codeBlockScroll}>
14
- <react_native_1.View style={styles_1.default.codeBlock}>
15
- <TreeNode_1.default data={data} search={search} forceOpen={forceOpen} defaultExpandDepth={defaultExpandDepth}/>
16
- </react_native_1.View>
18
+ <react_native_1.View style={styles_1.default.codeBlock}>{tree}</react_native_1.View>
17
19
  </react_native_1.ScrollView>);
18
20
  };
19
21
  exports.default = JsonViewer;
@@ -45,7 +45,7 @@ const MetaAccordion = ({ status, statusColor, duration, size, triggeredAt, metho
45
45
  </react_native_1.Text>
46
46
  </react_native_1.View>
47
47
  <react_native_1.View style={styles_1.default.metaDivider}/>
48
-
48
+
49
49
  <react_native_1.View style={styles_1.default.metaRow}>
50
50
  <react_native_1.View style={styles_1.default.metaLabelRow}>
51
51
  <NetworkIcons_1.TerminalIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
@@ -56,9 +56,12 @@ const MetaAccordion = ({ status, statusColor, duration, size, triggeredAt, metho
56
56
  {
57
57
  borderColor: 'rgba(107, 78, 255, 0.25)',
58
58
  backgroundColor: 'rgba(107, 78, 255, 0.08)',
59
- }
59
+ },
60
+ ]}>
61
+ <react_native_1.Text style={[
62
+ styles_1.default.statusText,
63
+ { color: AppColors_1.AppColors.purple, fontFamily: AppFonts_1.AppFonts.interBold },
60
64
  ]}>
61
- <react_native_1.Text style={[styles_1.default.statusText, { color: AppColors_1.AppColors.purple, fontFamily: AppFonts_1.AppFonts.interBold }]}>
62
65
  {method || 'GET'}
63
66
  </react_native_1.Text>
64
67
  </react_native_1.View>
@@ -96,7 +99,9 @@ const MetaAccordion = ({ status, statusColor, duration, size, triggeredAt, metho
96
99
  <NetworkIcons_1.GlobeIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
97
100
  <react_native_1.Text style={styles_1.default.metaLabel}>Content Type</react_native_1.Text>
98
101
  </react_native_1.View>
99
- <react_native_1.Text style={styles_1.default.metaValue}>{contentType || 'application/json'}</react_native_1.Text>
102
+ <react_native_1.Text style={styles_1.default.metaValue}>
103
+ {contentType || 'application/json'}
104
+ </react_native_1.Text>
100
105
  </react_native_1.View>
101
106
  <react_native_1.View style={styles_1.default.metaDivider}/>
102
107
 
@@ -130,7 +135,7 @@ const MetaAccordion = ({ status, statusColor, duration, size, triggeredAt, metho
130
135
  </react_native_1.View>
131
136
  </react_native_1.View>
132
137
  <react_native_1.View style={styles_1.default.metaDivider}/>
133
-
138
+
134
139
  <react_native_1.View style={styles_1.default.metaRow}>
135
140
  <react_native_1.View style={styles_1.default.metaLabelRow}>
136
141
  <NetworkIcons_1.SizeIcon color={AppColors_1.AppColors.grayTextWeak}/>
@@ -145,7 +150,22 @@ const MetaAccordion = ({ status, statusColor, duration, size, triggeredAt, metho
145
150
  <NetworkIcons_1.GlobeIcon color={AppColors_1.AppColors.grayTextWeak} size={14}/>
146
151
  <react_native_1.Text style={styles_1.default.metaLabel}>Full URL</react_native_1.Text>
147
152
  </react_native_1.View>
148
- <react_native_1.Text selectable={true} numberOfLines={3} ellipsizeMode="tail" style={[styles_1.default.metaValue, { fontSize: 11.5, color: AppColors_1.AppColors.grayTextWeak, flex: 1, textAlign: 'right', lineHeight: 16 }]}>
153
+ <react_native_1.Text selectable={true} numberOfLines={3} ellipsizeMode="tail" onPress={() => {
154
+ if (url) {
155
+ react_native_1.Linking.openURL(url).catch(() => { });
156
+ }
157
+ }} style={[
158
+ styles_1.default.metaValue,
159
+ {
160
+ fontSize: 11.5,
161
+ color: url ? AppColors_1.AppColors.purple : AppColors_1.AppColors.grayTextWeak,
162
+ textDecorationLine: url ? 'underline' : 'none',
163
+ fontFamily: AppFonts_1.AppFonts.interMedium,
164
+ flex: 1,
165
+ textAlign: 'right',
166
+ lineHeight: 16,
167
+ },
168
+ ]}>
149
169
  {url || '—'}
150
170
  </react_native_1.Text>
151
171
  </react_native_1.View>
@@ -1,4 +1,8 @@
1
1
  import React from 'react';
2
+ export declare const ReduxStoreIcon: ({ color, size, }: any) => React.JSX.Element;
3
+ export declare const ReduxBoltIcon: ({ color, size, }: any) => React.JSX.Element;
4
+ export declare const ReduxTimelineIcon: ({ color, size, }: any) => React.JSX.Element;
5
+ export declare const ReduxTreeIcon: ({ color, size, }: any) => React.JSX.Element;
2
6
  export declare const ReduxTreeView: ({ state, lastActionMap, search, }: {
3
7
  state: any;
4
8
  lastActionMap: Record<string, any>;
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.ReduxActionTimeline = exports.ReduxTreeView = void 0;
39
+ exports.ReduxActionTimeline = exports.ReduxTreeView = exports.ReduxTreeIcon = exports.ReduxTimelineIcon = exports.ReduxBoltIcon = exports.ReduxStoreIcon = void 0;
40
40
  const react_1 = __importStar(require("react"));
41
41
  const react_native_1 = require("react-native");
42
42
  const AppColors_1 = require("../styles/AppColors");
@@ -44,6 +44,44 @@ const AppFonts_1 = require("../styles/AppFonts");
44
44
  const NetworkIcons_1 = require("./NetworkIcons");
45
45
  const react_native_svg_1 = __importStar(require("react-native-svg"));
46
46
  const AnimatedEntrance_1 = __importDefault(require("./AnimatedEntrance"));
47
+ const helpers_1 = require("../helpers");
48
+ // #15 — copy-to-clipboard control for a single dispatched action
49
+ const ActionCopyButton = ({ value }) => {
50
+ const [copied, setCopied] = (0, react_1.useState)(false);
51
+ return (<react_native_1.Pressable hitSlop={10} onPress={() => {
52
+ (0, helpers_1.copyToClipboard)(value(), 'Action');
53
+ setCopied(true);
54
+ setTimeout(() => setCopied(false), 1200);
55
+ }} style={{
56
+ width: 26,
57
+ height: 26,
58
+ borderRadius: 7,
59
+ alignItems: 'center',
60
+ justifyContent: 'center',
61
+ backgroundColor: copied
62
+ ? `${AppColors_1.AppColors.greenColor}1A`
63
+ : AppColors_1.AppColors.grayBackground,
64
+ borderWidth: 1,
65
+ borderColor: AppColors_1.AppColors.dividerColor,
66
+ }}>
67
+ {copied ? (<NetworkIcons_1.CheckIcon color={AppColors_1.AppColors.greenColor} size={13}/>) : (<NetworkIcons_1.CopyIcon color={AppColors_1.AppColors.grayTextWeak} size={13}/>)}
68
+ </react_native_1.Pressable>);
69
+ };
70
+ // #15 — derive the redux module / folder name from an action type.
71
+ // Supports RTK slice convention ("booking/setDate" -> "Booking") and
72
+ // falls back to the first affected slice.
73
+ const getActionModule = (type, affectedSlices) => {
74
+ if (type && type.includes('/')) {
75
+ const prefix = type.split('/')[0];
76
+ if (prefix)
77
+ return prefix.charAt(0).toUpperCase() + prefix.slice(1);
78
+ }
79
+ if (affectedSlices && affectedSlices.length > 0) {
80
+ const s = affectedSlices[0];
81
+ return s.charAt(0).toUpperCase() + s.slice(1);
82
+ }
83
+ return null;
84
+ };
47
85
  // Custom icons
48
86
  const DatabaseIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 12 }) => (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
49
87
  <react_native_svg_1.Path d="M12 2C6.5 2 2 4.2 2 7v10c0 2.8 4.5 5 10 5s10-2.2 10-5V7c0-2.8-4.5-5-10-5z" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
@@ -56,6 +94,30 @@ const BoltIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 12 }) =>
56
94
  const FolderIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 12 }) => (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
57
95
  <react_native_svg_1.Path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
58
96
  </react_native_svg_1.default>);
97
+ // Exported icons so the Redux tab's section headers and sub-tab buttons can
98
+ // render real vector icons instead of emoji (which fail to render on some
99
+ // Android/font setups).
100
+ const ReduxStoreIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 12, }) => (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
101
+ <react_native_svg_1.Path d="M3 9l1.5-5h15L21 9M3 9v10a1 1 0 0 0 1 1h16a1 1 0 0 0 1-1V9M3 9h18M7 9v3a2 2 0 0 0 4 0V9m2 0v3a2 2 0 0 0 4 0V9" stroke={color} strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
102
+ </react_native_svg_1.default>);
103
+ exports.ReduxStoreIcon = ReduxStoreIcon;
104
+ const ReduxBoltIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 12, }) => (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
105
+ <react_native_svg_1.Path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" fill={color} stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
106
+ </react_native_svg_1.default>);
107
+ exports.ReduxBoltIcon = ReduxBoltIcon;
108
+ // Action Timeline — a history/clock icon reads as "sequence over time".
109
+ const ReduxTimelineIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 12, }) => (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
110
+ <react_native_svg_1.Path d="M3 3v5h5" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
111
+ <react_native_svg_1.Path d="M3.05 13A9 9 0 1 0 6 5.3L3 8" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
112
+ <react_native_svg_1.Path d="M12 7v5l3 2" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
113
+ </react_native_svg_1.default>);
114
+ exports.ReduxTimelineIcon = ReduxTimelineIcon;
115
+ // Store Tree — a node hierarchy icon reads as "nested tree structure".
116
+ const ReduxTreeIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 12, }) => (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
117
+ <react_native_svg_1.Path d="M9 4h6v4H9zM3 16h6v4H3zm12 0h6v4h-6z" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
118
+ <react_native_svg_1.Path d="M12 8v4M6 16v-2h12v2" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
119
+ </react_native_svg_1.default>);
120
+ exports.ReduxTreeIcon = ReduxTreeIcon;
59
121
  const animateTreeLayout = () => {
60
122
  react_native_1.LayoutAnimation.configureNext(react_native_1.LayoutAnimation.Presets.easeInEaseOut);
61
123
  };
@@ -181,7 +243,10 @@ const ReduxTreeView = ({ state, lastActionMap, search, }) => {
181
243
  setStoreExpanded(!storeExpanded);
182
244
  }} style={styles.storeHeader}>
183
245
  <AnimatedChevron color="#FFFFFF" expanded={storeExpanded} size={12} style={styles.chevronWrap}/>
184
- <react_native_1.Text style={styles.storeTitle}>🏪 Redux Store</react_native_1.Text>
246
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
247
+ <exports.ReduxStoreIcon color="#FFFFFF" size={14}/>
248
+ <react_native_1.Text style={styles.storeTitle}>Redux Store</react_native_1.Text>
249
+ </react_native_1.View>
185
250
  <react_native_1.View style={styles.badge}>
186
251
  <react_native_1.Text style={styles.badgeText}>{reducers.length} Reducers</react_native_1.Text>
187
252
  </react_native_1.View>
@@ -286,9 +351,12 @@ const ReduxActionTimeline = ({ history, onClear, search, }) => {
286
351
  });
287
352
  return (<react_native_1.View style={timelineStyles.container}>
288
353
  <react_native_1.View style={timelineStyles.headerRow}>
289
- <react_native_1.Text style={timelineStyles.headerTitle}>
290
- Dispatched Actions ({filteredHistory.length})
291
- </react_native_1.Text>
354
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6 }}>
355
+ <exports.ReduxBoltIcon color={AppColors_1.AppColors.purple} size={15}/>
356
+ <react_native_1.Text style={timelineStyles.headerTitle}>
357
+ Dispatched Actions ({filteredHistory.length})
358
+ </react_native_1.Text>
359
+ </react_native_1.View>
292
360
  {history.length > 0 && (<react_native_1.Pressable onPress={onClear} style={timelineStyles.clearBtn}>
293
361
  <react_native_1.Text style={timelineStyles.clearBtnText}>Clear Log</react_native_1.Text>
294
362
  </react_native_1.Pressable>)}
@@ -323,12 +391,49 @@ const ReduxActionTimeline = ({ history, onClear, search, }) => {
323
391
  },
324
392
  ]}>
325
393
  <react_native_1.View style={timelineStyles.cardHeader}>
326
- <react_native_1.View style={timelineStyles.typeBadge}>
327
- <react_native_1.Text style={timelineStyles.typeText}>{item.type}</react_native_1.Text>
394
+ <react_native_1.View style={{
395
+ flexDirection: 'row',
396
+ alignItems: 'center',
397
+ gap: 6,
398
+ flex: 1,
399
+ }}>
400
+ {(() => {
401
+ const moduleName = getActionModule(item.type, item.affectedSlices);
402
+ return moduleName ? (<react_native_1.View style={{
403
+ paddingHorizontal: 7,
404
+ paddingVertical: 2,
405
+ borderRadius: 6,
406
+ backgroundColor: `${AppColors_1.AppColors.purple}14`,
407
+ borderWidth: 1,
408
+ borderColor: `${AppColors_1.AppColors.purple}33`,
409
+ }}>
410
+ <react_native_1.Text style={{
411
+ fontFamily: AppFonts_1.AppFonts.interBold,
412
+ fontSize: 9.5,
413
+ color: AppColors_1.AppColors.purple,
414
+ letterSpacing: 0.2,
415
+ }}>
416
+ {moduleName}
417
+ </react_native_1.Text>
418
+ </react_native_1.View>) : null;
419
+ })()}
420
+ <react_native_1.View style={timelineStyles.typeBadge}>
421
+ <react_native_1.Text style={timelineStyles.typeText}>{item.type}</react_native_1.Text>
422
+ </react_native_1.View>
423
+ </react_native_1.View>
424
+ <react_native_1.View style={{
425
+ flexDirection: 'row',
426
+ alignItems: 'center',
427
+ gap: 8,
428
+ }}>
429
+ <react_native_1.Text style={timelineStyles.timestamp}>
430
+ {item.timestamp}
431
+ </react_native_1.Text>
432
+ <ActionCopyButton value={() => ({
433
+ type: item.type,
434
+ payload: item.payload,
435
+ })}/>
328
436
  </react_native_1.View>
329
- <react_native_1.Text style={timelineStyles.timestamp}>
330
- {item.timestamp}
331
- </react_native_1.Text>
332
437
  </react_native_1.View>
333
438
 
334
439
  {item.affectedSlices.length > 0 && (<react_native_1.View style={timelineStyles.slicesRow}>
@@ -5,3 +5,4 @@ export declare const METHOD_COLORS: Record<Method, string>;
5
5
  export declare const DOMAIN_COLORS: string[];
6
6
  export declare const DURATION_FAST_MS = 200;
7
7
  export declare const DURATION_SLOW_MS = 800;
8
+ export { LIB_VERSION } from './version';
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DURATION_SLOW_MS = exports.DURATION_FAST_MS = exports.DOMAIN_COLORS = exports.METHOD_COLORS = exports.STATUS_FILTERS = void 0;
3
+ exports.LIB_VERSION = exports.DURATION_SLOW_MS = exports.DURATION_FAST_MS = exports.DOMAIN_COLORS = exports.METHOD_COLORS = exports.STATUS_FILTERS = void 0;
4
4
  // Styles
5
5
  const AppColors_1 = require("../styles/AppColors");
6
6
  exports.STATUS_FILTERS = [
@@ -33,3 +33,7 @@ exports.DOMAIN_COLORS = [
33
33
  ];
34
34
  exports.DURATION_FAST_MS = 200;
35
35
  exports.DURATION_SLOW_MS = 800;
36
+ // Package version — auto-generated from package.json at build time.
37
+ // See scripts/gen-version.js (wired to the "prebuild" npm script).
38
+ var version_1 = require("./version");
39
+ Object.defineProperty(exports, "LIB_VERSION", { enumerable: true, get: function () { return version_1.LIB_VERSION; } });
@@ -0,0 +1 @@
1
+ export declare const LIB_VERSION = "1.1.2";
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LIB_VERSION = void 0;
4
+ // AUTO-GENERATED FILE — do not edit by hand.
5
+ // Regenerated from package.json on every build by scripts/gen-version.js.
6
+ exports.LIB_VERSION = '1.1.2';
@@ -41,7 +41,9 @@ const subscribeReduxState = (cb) => {
41
41
  };
42
42
  exports.subscribeReduxState = subscribeReduxState;
43
43
  const connectReduxStore = (store) => {
44
- if (!store || typeof store.getState !== 'function' || typeof store.subscribe !== 'function') {
44
+ if (!store ||
45
+ typeof store.getState !== 'function' ||
46
+ typeof store.subscribe !== 'function') {
45
47
  console.warn('[NetworkInspector] Invalid Redux store passed to connectReduxStore.');
46
48
  return;
47
49
  }
@@ -84,8 +86,14 @@ const connectReduxStore = (store) => {
84
86
  }
85
87
  }
86
88
  if (globalReduxAutoRefresh) {
89
+ // Refresh the displayed state tree snapshot.
87
90
  (0, exports.setReduxState)(nextState);
88
91
  }
92
+ else {
93
+ // Tree is paused, but the action timeline / last-action map still changed,
94
+ // so notify subscribers to re-render those without moving the tree snapshot.
95
+ listeners.forEach(cb => cb());
96
+ }
89
97
  return result;
90
98
  };
91
99
  (0, exports.setReduxState)(store.getState());