react-native-inapp-inspector 1.1.1 → 1.1.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 (45) hide show
  1. package/README.md +14 -0
  2. package/dist/commonjs/components/ConsoleLogCard.js +18 -0
  3. package/dist/commonjs/components/JsonViewer.d.ts +2 -1
  4. package/dist/commonjs/components/JsonViewer.js +6 -4
  5. package/dist/commonjs/components/LogCard.js +17 -0
  6. package/dist/commonjs/components/MetaAccordion.js +26 -6
  7. package/dist/commonjs/components/NetworkIcons.d.ts +9 -2
  8. package/dist/commonjs/components/NetworkIcons.js +59 -3
  9. package/dist/commonjs/components/ReduxTreeView.js +80 -5
  10. package/dist/commonjs/constants/version.d.ts +1 -1
  11. package/dist/commonjs/constants/version.js +1 -1
  12. package/dist/commonjs/customHooks/reduxLogger.d.ts +21 -7
  13. package/dist/commonjs/customHooks/reduxLogger.js +147 -48
  14. package/dist/commonjs/customHooks/webViewLogger.js +13 -8
  15. package/dist/commonjs/helpers/settingsStore.d.ts +24 -0
  16. package/dist/commonjs/helpers/settingsStore.js +74 -0
  17. package/dist/commonjs/index.d.ts +1 -1
  18. package/dist/commonjs/index.js +897 -170
  19. package/dist/commonjs/styles/index.d.ts +40 -0
  20. package/dist/commonjs/styles/index.js +45 -2
  21. package/dist/commonjs/types/index.d.ts +4 -0
  22. package/dist/esm/components/ConsoleLogCard.js +18 -0
  23. package/dist/esm/components/JsonViewer.d.ts +2 -1
  24. package/dist/esm/components/JsonViewer.js +6 -4
  25. package/dist/esm/components/LogCard.js +17 -0
  26. package/dist/esm/components/MetaAccordion.js +27 -7
  27. package/dist/esm/components/NetworkIcons.d.ts +9 -2
  28. package/dist/esm/components/NetworkIcons.js +51 -2
  29. package/dist/esm/components/ReduxTreeView.js +81 -6
  30. package/dist/esm/constants/version.d.ts +1 -1
  31. package/dist/esm/constants/version.js +1 -1
  32. package/dist/esm/customHooks/reduxLogger.d.ts +21 -7
  33. package/dist/esm/customHooks/reduxLogger.js +145 -47
  34. package/dist/esm/customHooks/webViewLogger.js +13 -8
  35. package/dist/esm/helpers/settingsStore.d.ts +24 -0
  36. package/dist/esm/helpers/settingsStore.js +67 -0
  37. package/dist/esm/index.d.ts +1 -1
  38. package/dist/esm/index.js +896 -172
  39. package/dist/esm/styles/index.d.ts +40 -0
  40. package/dist/esm/styles/index.js +45 -2
  41. package/dist/esm/types/index.d.ts +4 -0
  42. package/example/App.tsx +199 -61
  43. package/example/ios/example.xcodeproj/project.pbxproj +0 -8
  44. package/example/package-lock.json +4 -3
  45. package/package.json +1 -1
package/README.md CHANGED
@@ -185,6 +185,20 @@ import store from './store';
185
185
  connectReduxStore(store);
186
186
  ```
187
187
 
188
+ **Recommended:** if you use thunks, sagas or RTK Query, also add the inspector middleware so actions dispatched from inside them are captured with full type/payload attribution (they bypass the wrapped outer dispatch otherwise):
189
+
190
+ ```tsx
191
+ import {inspectorReduxMiddleware} from 'react-native-inapp-inspector';
192
+
193
+ const store = configureStore({
194
+ reducer,
195
+ middleware: getDefaultMiddleware =>
196
+ getDefaultMiddleware().concat(inspectorReduxMiddleware),
197
+ });
198
+ ```
199
+
200
+ Using both together is safe — they de-duplicate automatically.
201
+
188
202
  The Redux tab shows the latest state tree, recent dispatches, payloads, and changed top-level state slices. Action history is capped at 50 entries.
189
203
 
190
204
  ---
@@ -320,6 +320,24 @@ exports.ConsoleLogCard = react_1.default.memo(function ConsoleLogCard({ item, se
320
320
  : `Object{${Object.keys(jsonContent.data).length}}`}
321
321
  </react_native_1.Text>
322
322
  </react_native_1.View>)}
323
+ {/* #9 — collapsed duplicate counter */}
324
+ {'duplicateCount' in item &&
325
+ item.duplicateCount != null &&
326
+ item.duplicateCount > 1 && (<react_native_1.View style={[
327
+ styles.badge,
328
+ {
329
+ backgroundColor: 'rgba(104, 75, 155, 0.1)',
330
+ borderColor: 'rgba(104, 75, 155, 0.25)',
331
+ borderWidth: 1,
332
+ },
333
+ ]}>
334
+ <react_native_1.Text style={[
335
+ styles.badgeText,
336
+ { color: AppColors_1.AppColors.purple, fontWeight: '700' },
337
+ ]}>
338
+ ×{item.duplicateCount}
339
+ </react_native_1.Text>
340
+ </react_native_1.View>)}
323
341
  {isAnalyticsError && (<react_native_1.View style={[
324
342
  styles.badge,
325
343
  { backgroundColor: `${AppColors_1.AppColors.skyBlue}15` },
@@ -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;
@@ -116,6 +116,23 @@ const LogCard = react_1.default.memo(function LogCard({ item, onPress, timelineM
116
116
  .json
117
117
  </react_native_1.Text>
118
118
  </react_native_1.View>)}
119
+
120
+ {/* #9 — collapsed duplicate counter */}
121
+ {item.duplicateCount != null && item.duplicateCount > 1 && (<react_native_1.View style={[
122
+ styles_1.default.chip,
123
+ {
124
+ backgroundColor: `${AppColors_1.AppColors.purple}15`,
125
+ borderColor: `${AppColors_1.AppColors.purple}30`,
126
+ marginLeft: 6,
127
+ },
128
+ ]}>
129
+ <react_native_1.Text style={[
130
+ styles_1.default.chipText,
131
+ { color: AppColors_1.AppColors.purple, fontWeight: '700' },
132
+ ]}>
133
+ ×{item.duplicateCount}
134
+ </react_native_1.Text>
135
+ </react_native_1.View>)}
119
136
  </react_native_1.View>
120
137
 
121
138
  <react_native_1.View style={styles_1.default.cardBottomRow}>
@@ -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>
@@ -40,5 +40,12 @@ export declare const HtmlIcon: ({ color, size }: any) => React.JSX.Element;
40
40
  export declare const CssIcon: ({ color, size }: any) => React.JSX.Element;
41
41
  export declare const JsIcon: ({ color, size }: any) => React.JSX.Element;
42
42
  export declare const EyeIcon: ({ color, size }: any) => React.JSX.Element;
43
- export declare const SettingsIcon: ({ color, size }: any) => React.JSX.Element;
44
- export declare const FolderIcon: ({ color, size }: any) => React.JSX.Element;
43
+ export declare const SettingsIcon: ({ color, size, }: any) => React.JSX.Element;
44
+ export declare const FolderIcon: ({ color, size, }: any) => React.JSX.Element;
45
+ export declare const WipeIcon: ({ color, size }: any) => React.JSX.Element;
46
+ export declare const LayersIcon: ({ color, size, }: any) => React.JSX.Element;
47
+ export declare const UserIcon: ({ color, size }: any) => React.JSX.Element;
48
+ export declare const InfoCircleIcon: ({ color, size, }: any) => React.JSX.Element;
49
+ export declare const WarningTriangleIcon: ({ color, size, }: any) => React.JSX.Element;
50
+ export declare const ErrorCircleIcon: ({ color, size, }: any) => React.JSX.Element;
51
+ export declare const TrendingUpIcon: ({ color, size, }: any) => React.JSX.Element;
@@ -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.FolderIcon = exports.SettingsIcon = exports.EyeIcon = exports.JsIcon = exports.CssIcon = exports.HtmlIcon = exports.BrandSquareIcon = exports.BrandCircleIcon = exports.MoonIcon = exports.SunIcon = exports.DebugIcon = exports.InsightsIcon = exports.AnalyticsIcon = exports.WhiteBackNavigation = exports.CloseWhite = exports.DownloadIcon = exports.FilterIcon = exports.ChevronIcon = exports.SortArrowIcon = exports.GlobeIcon = exports.DiffIcon = exports.SignalIcon = exports.ExportIcon = exports.HeaderPauseIcon = exports.TrashIcon = exports.FailIcon = exports.CheckIcon = exports.TerminalIcon = exports.FetchIcon = exports.CopyIcon = exports.HeadersIcon = exports.ResponseIcon = exports.RequestIcon = exports.SizeIcon = exports.StatusIcon = exports.CalendarIcon = exports.ClockIcon = exports.ClearIcon = exports.SearchIcon = exports.ExpandCollapseIcon = exports.ScreenIcon = exports.MapPinIcon = exports.EmptyRadarIcon = void 0;
39
+ exports.TrendingUpIcon = exports.ErrorCircleIcon = exports.WarningTriangleIcon = exports.InfoCircleIcon = exports.UserIcon = exports.LayersIcon = exports.WipeIcon = exports.FolderIcon = exports.SettingsIcon = exports.EyeIcon = exports.JsIcon = exports.CssIcon = exports.HtmlIcon = exports.BrandSquareIcon = exports.BrandCircleIcon = exports.MoonIcon = exports.SunIcon = exports.DebugIcon = exports.InsightsIcon = exports.AnalyticsIcon = exports.WhiteBackNavigation = exports.CloseWhite = exports.DownloadIcon = exports.FilterIcon = exports.ChevronIcon = exports.SortArrowIcon = exports.GlobeIcon = exports.DiffIcon = exports.SignalIcon = exports.ExportIcon = exports.HeaderPauseIcon = exports.TrashIcon = exports.FailIcon = exports.CheckIcon = exports.TerminalIcon = exports.FetchIcon = exports.CopyIcon = exports.HeadersIcon = exports.ResponseIcon = exports.RequestIcon = exports.SizeIcon = exports.StatusIcon = exports.CalendarIcon = exports.ClockIcon = exports.ClearIcon = exports.SearchIcon = exports.ExpandCollapseIcon = exports.ScreenIcon = exports.MapPinIcon = exports.EmptyRadarIcon = void 0;
40
40
  const react_1 = __importDefault(require("react"));
41
41
  const react_native_svg_1 = __importStar(require("react-native-svg"));
42
42
  // Stylesheet
@@ -317,16 +317,72 @@ const EyeIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 14 }) => {
317
317
  </react_native_svg_1.default>);
318
318
  };
319
319
  exports.EyeIcon = EyeIcon;
320
- const SettingsIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 14 }) => {
320
+ const SettingsIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 14, }) => {
321
321
  return (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
322
322
  <react_native_svg_1.Path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
323
323
  <react_native_svg_1.Circle cx="12" cy="12" r="3" stroke={color} strokeWidth="2"/>
324
324
  </react_native_svg_1.default>);
325
325
  };
326
326
  exports.SettingsIcon = SettingsIcon;
327
- const FolderIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 14 }) => {
327
+ const FolderIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 14, }) => {
328
328
  return (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
329
329
  <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"/>
330
330
  </react_native_svg_1.default>);
331
331
  };
332
332
  exports.FolderIcon = FolderIcon;
333
+ // #3 — Broom/sweep "wipe" icon used by the header Clear-Everything button.
334
+ const WipeIcon = ({ color = '#FFFFFF', size = 16 }) => {
335
+ return (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
336
+ {/* Handle */}
337
+ <react_native_svg_1.Path d="M19.5 3.5L12.7 10.3" stroke={color} strokeWidth="2" strokeLinecap="round"/>
338
+ {/* Brush head */}
339
+ <react_native_svg_1.Path d="M13.5 9.5l1.5 1.5c.8.8.8 2 0 2.8L10 19l-5-5 5.2-5.5c.8-.8 2-.8 2.8 0z" stroke={color} strokeWidth="2" strokeLinejoin="round"/>
340
+ {/* Bristle strokes */}
341
+ <react_native_svg_1.Path d="M7.5 16.5L5.5 18.5M10 19l-1.5 1.5" stroke={color} strokeWidth="2" strokeLinecap="round"/>
342
+ {/* Dust sparks */}
343
+ <react_native_svg_1.Path d="M3 11.5h.01M5.5 8.5h.01" stroke={color} strokeWidth="2.4" strokeLinecap="round"/>
344
+ </react_native_svg_1.default>);
345
+ };
346
+ exports.WipeIcon = WipeIcon;
347
+ // #7 — Icons for the inner filter chips / sub tabs.
348
+ const LayersIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 12, }) => {
349
+ return (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
350
+ <react_native_svg_1.Path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
351
+ </react_native_svg_1.default>);
352
+ };
353
+ exports.LayersIcon = LayersIcon;
354
+ const UserIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 12 }) => {
355
+ return (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
356
+ <react_native_svg_1.Path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
357
+ <react_native_svg_1.Circle cx="12" cy="7" r="4" stroke={color} strokeWidth="2"/>
358
+ </react_native_svg_1.default>);
359
+ };
360
+ exports.UserIcon = UserIcon;
361
+ const InfoCircleIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 12, }) => {
362
+ return (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
363
+ <react_native_svg_1.Circle cx="12" cy="12" r="10" stroke={color} strokeWidth="2"/>
364
+ <react_native_svg_1.Path d="M12 16v-4M12 8h.01" stroke={color} strokeWidth="2" strokeLinecap="round"/>
365
+ </react_native_svg_1.default>);
366
+ };
367
+ exports.InfoCircleIcon = InfoCircleIcon;
368
+ const WarningTriangleIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 12, }) => {
369
+ return (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
370
+ <react_native_svg_1.Path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
371
+ <react_native_svg_1.Path d="M12 9v4M12 17h.01" stroke={color} strokeWidth="2" strokeLinecap="round"/>
372
+ </react_native_svg_1.default>);
373
+ };
374
+ exports.WarningTriangleIcon = WarningTriangleIcon;
375
+ const ErrorCircleIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 12, }) => {
376
+ return (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
377
+ <react_native_svg_1.Circle cx="12" cy="12" r="10" stroke={color} strokeWidth="2"/>
378
+ <react_native_svg_1.Path d="M15 9l-6 6M9 9l6 6" stroke={color} strokeWidth="2" strokeLinecap="round"/>
379
+ </react_native_svg_1.default>);
380
+ };
381
+ exports.ErrorCircleIcon = ErrorCircleIcon;
382
+ const TrendingUpIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 12, }) => {
383
+ return (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
384
+ <react_native_svg_1.Path d="M23 6l-9.5 9.5-5-5L1 18" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
385
+ <react_native_svg_1.Path d="M17 6h6v6" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
386
+ </react_native_svg_1.default>);
387
+ };
388
+ exports.TrendingUpIcon = TrendingUpIcon;
@@ -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"/>
@@ -353,12 +391,49 @@ const ReduxActionTimeline = ({ history, onClear, search, }) => {
353
391
  },
354
392
  ]}>
355
393
  <react_native_1.View style={timelineStyles.cardHeader}>
356
- <react_native_1.View style={timelineStyles.typeBadge}>
357
- <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
+ })}/>
358
436
  </react_native_1.View>
359
- <react_native_1.Text style={timelineStyles.timestamp}>
360
- {item.timestamp}
361
- </react_native_1.Text>
362
437
  </react_native_1.View>
363
438
 
364
439
  {item.affectedSlices.length > 0 && (<react_native_1.View style={timelineStyles.slicesRow}>
@@ -1 +1 @@
1
- export declare const LIB_VERSION = "1.1.1";
1
+ export declare const LIB_VERSION = "1.1.3";
@@ -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.1';
6
+ exports.LIB_VERSION = '1.1.3';
@@ -1,16 +1,30 @@
1
- export declare const getReduxState: () => any;
2
- export declare const setReduxAutoRefresh: (val: boolean) => void;
3
- export declare const getReduxAutoRefresh: () => boolean;
4
- export declare const getLastActionForReducer: () => Record<string, any>;
5
- export declare const clearLastActionForReducer: () => void;
6
- export declare const getActionHistory: () => {
1
+ export interface ReduxHistoryEntry {
7
2
  id: number;
8
3
  type: string;
9
4
  payload: any;
10
5
  timestamp: string;
11
6
  affectedSlices: string[];
12
- }[];
7
+ }
8
+ export declare const getReduxState: () => any;
9
+ export declare const setReduxAutoRefresh: (val: boolean) => void;
10
+ export declare const getReduxAutoRefresh: () => boolean;
11
+ export declare const getLastActionForReducer: () => Record<string, any>;
12
+ export declare const clearLastActionForReducer: () => void;
13
+ export declare const getActionHistory: () => ReduxHistoryEntry[];
13
14
  export declare const clearActionHistory: () => void;
14
15
  export declare const setReduxState: (state: any) => void;
15
16
  export declare const subscribeReduxState: (cb: () => void) => () => void;
17
+ /**
18
+ * Standard Redux middleware — add it to your store to capture every action,
19
+ * including those dispatched from thunks, sagas and RTK Query:
20
+ *
21
+ * const store = configureStore({
22
+ * reducer,
23
+ * middleware: gDM => gDM().concat(inspectorReduxMiddleware),
24
+ * });
25
+ *
26
+ * Pair with `connectReduxStore(store)` (safe — they de-duplicate) or rely on
27
+ * the middleware alone; the initial snapshot is taken on the first action.
28
+ */
29
+ export declare const inspectorReduxMiddleware: (storeApi: any) => (next: (action: any) => any) => (action: any) => any;
16
30
  export declare const connectReduxStore: (store: any) => void;