react-native-inapp-inspector 1.1.35 → 2.0.1

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 (104) hide show
  1. package/README.md +123 -101
  2. package/android/build.gradle +13 -1
  3. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +890 -0
  4. package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.kt +17 -0
  5. package/dist/commonjs/components/ConsoleLogCard.js +5 -5
  6. package/dist/commonjs/components/CopyButton.js +3 -0
  7. package/dist/commonjs/components/EndOfListFooter.js +1 -1
  8. package/dist/commonjs/components/ErrorBoundary.js +3 -0
  9. package/dist/commonjs/components/Inspector/AnalyticsTab.js +25 -73
  10. package/dist/commonjs/components/Inspector/BundleTab.js +671 -189
  11. package/dist/commonjs/components/Inspector/ConsoleTab.js +110 -99
  12. package/dist/commonjs/components/Inspector/CrashTab.js +99 -91
  13. package/dist/commonjs/components/Inspector/InspectorHeader.js +107 -20
  14. package/dist/commonjs/components/Inspector/MainScreen.js +111 -68
  15. package/dist/commonjs/components/Inspector/NetworkTab.js +151 -30
  16. package/dist/commonjs/components/Inspector/PerformanceTab.js +96 -3
  17. package/dist/commonjs/components/Inspector/ReduxTab.js +18 -10
  18. package/dist/commonjs/components/Inspector/SettingsPanel.js +1218 -1238
  19. package/dist/commonjs/components/Inspector/TabBar.js +4 -2
  20. package/dist/commonjs/components/JsonViewer.js +9 -4
  21. package/dist/commonjs/components/LogCard.js +31 -1
  22. package/dist/commonjs/components/LogSyntaxHighlighter.d.ts +16 -0
  23. package/dist/commonjs/components/LogSyntaxHighlighter.js +130 -0
  24. package/dist/commonjs/components/NetworkIcons.d.ts +3 -0
  25. package/dist/commonjs/components/NetworkIcons.js +15 -1
  26. package/dist/commonjs/components/Slider.d.ts +13 -0
  27. package/dist/commonjs/components/Slider.js +261 -0
  28. package/dist/commonjs/components/TouchableScale.d.ts +1 -0
  29. package/dist/commonjs/components/TouchableScale.js +30 -32
  30. package/dist/commonjs/constants/index.d.ts +1 -2
  31. package/dist/commonjs/constants/index.js +4 -0
  32. package/dist/commonjs/constants/version.d.ts +1 -1
  33. package/dist/commonjs/constants/version.js +1 -1
  34. package/dist/commonjs/customHooks/analyticsLogger.d.ts +4 -0
  35. package/dist/commonjs/customHooks/analyticsLogger.js +8 -6
  36. package/dist/commonjs/customHooks/crashHandler.js +8 -1
  37. package/dist/commonjs/helpers/index.d.ts +1 -0
  38. package/dist/commonjs/helpers/index.js +25 -1
  39. package/dist/commonjs/helpers/searchQueryParser.d.ts +6 -0
  40. package/dist/commonjs/helpers/searchQueryParser.js +236 -0
  41. package/dist/commonjs/helpers/settingsStore.d.ts +9 -0
  42. package/dist/commonjs/helpers/settingsStore.js +59 -3
  43. package/dist/commonjs/index.d.ts +1 -0
  44. package/dist/commonjs/index.js +220 -43
  45. package/dist/commonjs/native/NativeInspector.d.ts +125 -0
  46. package/dist/commonjs/native/NativeInspector.js +313 -0
  47. package/dist/commonjs/native/NativeNetworkInspector.d.ts +22 -0
  48. package/dist/commonjs/native/NativeNetworkInspector.js +4 -0
  49. package/dist/commonjs/styles/index.js +41 -41
  50. package/dist/commonjs/types/enums.d.ts +1 -1
  51. package/dist/commonjs/types/interfaces.d.ts +9 -0
  52. package/dist/esm/components/ConsoleLogCard.js +5 -5
  53. package/dist/esm/components/CopyButton.js +3 -0
  54. package/dist/esm/components/EndOfListFooter.js +2 -2
  55. package/dist/esm/components/ErrorBoundary.js +3 -0
  56. package/dist/esm/components/Inspector/AnalyticsTab.js +27 -75
  57. package/dist/esm/components/Inspector/BundleTab.js +671 -189
  58. package/dist/esm/components/Inspector/ConsoleTab.js +111 -100
  59. package/dist/esm/components/Inspector/CrashTab.js +99 -91
  60. package/dist/esm/components/Inspector/InspectorHeader.js +108 -21
  61. package/dist/esm/components/Inspector/MainScreen.js +113 -70
  62. package/dist/esm/components/Inspector/NetworkTab.js +152 -31
  63. package/dist/esm/components/Inspector/PerformanceTab.js +96 -3
  64. package/dist/esm/components/Inspector/ReduxTab.js +18 -10
  65. package/dist/esm/components/Inspector/SettingsPanel.js +1222 -1242
  66. package/dist/esm/components/Inspector/TabBar.js +4 -2
  67. package/dist/esm/components/JsonViewer.js +9 -4
  68. package/dist/esm/components/LogCard.js +32 -2
  69. package/dist/esm/components/LogSyntaxHighlighter.d.ts +16 -0
  70. package/dist/esm/components/LogSyntaxHighlighter.js +123 -0
  71. package/dist/esm/components/NetworkIcons.d.ts +3 -0
  72. package/dist/esm/components/NetworkIcons.js +11 -0
  73. package/dist/esm/components/Slider.d.ts +13 -0
  74. package/dist/esm/components/Slider.js +222 -0
  75. package/dist/esm/components/TouchableScale.d.ts +1 -0
  76. package/dist/esm/components/TouchableScale.js +31 -33
  77. package/dist/esm/constants/index.d.ts +1 -2
  78. package/dist/esm/constants/index.js +4 -0
  79. package/dist/esm/constants/version.d.ts +1 -1
  80. package/dist/esm/constants/version.js +1 -1
  81. package/dist/esm/customHooks/analyticsLogger.d.ts +4 -0
  82. package/dist/esm/customHooks/analyticsLogger.js +6 -5
  83. package/dist/esm/customHooks/crashHandler.js +8 -1
  84. package/dist/esm/helpers/index.d.ts +1 -0
  85. package/dist/esm/helpers/index.js +11 -1
  86. package/dist/esm/helpers/searchQueryParser.d.ts +6 -0
  87. package/dist/esm/helpers/searchQueryParser.js +233 -0
  88. package/dist/esm/helpers/settingsStore.d.ts +9 -0
  89. package/dist/esm/helpers/settingsStore.js +58 -3
  90. package/dist/esm/index.d.ts +1 -0
  91. package/dist/esm/index.js +207 -44
  92. package/dist/esm/native/NativeInspector.d.ts +125 -0
  93. package/dist/esm/native/NativeInspector.js +289 -0
  94. package/dist/esm/native/NativeNetworkInspector.d.ts +22 -0
  95. package/dist/esm/native/NativeNetworkInspector.js +2 -0
  96. package/dist/esm/styles/index.js +41 -41
  97. package/dist/esm/types/enums.d.ts +1 -1
  98. package/dist/esm/types/interfaces.d.ts +9 -0
  99. package/ios/NetworkInspectorModule.h +6 -0
  100. package/ios/NetworkInspectorModule.m +760 -5
  101. package/package.json +13 -2
  102. package/react-native-inapp-inspector.podspec +7 -2
  103. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.java +0 -97
  104. package/android/src/main/java/com/inappinspector/NetworkInspectorPackage.java +0 -28
@@ -6,9 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const react_1 = __importDefault(require("react"));
7
7
  const react_native_1 = require("react-native");
8
8
  const InspectorContext_1 = require("./InspectorContext");
9
- const TouchableScale_1 = __importDefault(require("../TouchableScale"));
10
9
  const styles_1 = __importDefault(require("../../styles"));
11
10
  const AppColors_1 = require("../../styles/AppColors");
11
+ const TouchableScale_1 = __importDefault(require("../TouchableScale"));
12
12
  const NetworkIcons_1 = require("../NetworkIcons");
13
13
  const reduxLogger_1 = require("../../customHooks/reduxLogger");
14
14
  const analyticsLogger_1 = require("../../customHooks/analyticsLogger");
@@ -85,7 +85,9 @@ const TabBar = react_1.default.memo(() => {
85
85
  consoleLogs.length > lastReadLogsCount;
86
86
  const hasUnreadCrashes = activeTab !== 'crash' &&
87
87
  (crashRecords?.length || 0) > (lastReadCrashesCount || 0);
88
- return (<TouchableScale_1.default key={tab.key} onPress={() => switchActiveTab(tab.key)} style={[
88
+ return (<TouchableScale_1.default key={tab.key} onPress={() => {
89
+ switchActiveTab(tab.key);
90
+ }} style={[
89
91
  styles_1.default.contentTabButton,
90
92
  isActive && styles_1.default.contentTabButtonActive,
91
93
  ]}>
@@ -106,20 +106,25 @@ const JsonViewer = react_1.default.memo(({ data, search, forceOpen, defaultExpan
106
106
  }
107
107
  };
108
108
  const rawText = react_1.default.useMemo(() => {
109
+ if (data === undefined || data === null) {
110
+ return '';
111
+ }
109
112
  if (typeof data === 'string') {
110
113
  return data;
111
114
  }
112
115
  try {
113
- return JSON.stringify(data);
116
+ const stringified = JSON.stringify(data);
117
+ return stringified ?? '';
114
118
  }
115
119
  catch {
116
- return String(data);
120
+ return String(data) || '';
117
121
  }
118
122
  }, [data]);
119
123
  const [showFullRaw, setShowFullRaw] = (0, react_1.useState)(false);
120
124
  const RAW_LIMIT = 50000;
121
- const isTruncated = rawText.length > RAW_LIMIT && !showFullRaw;
122
- const displayRawText = isTruncated ? rawText.slice(0, RAW_LIMIT) : rawText;
125
+ const safeRawText = typeof rawText === 'string' ? rawText : '';
126
+ const isTruncated = safeRawText.length > RAW_LIMIT && !showFullRaw;
127
+ const displayRawText = isTruncated ? safeRawText.slice(0, RAW_LIMIT) : safeRawText;
123
128
  (0, react_1.useEffect)(() => {
124
129
  if (externalMode) {
125
130
  setInternalMode(externalMode);
@@ -97,6 +97,22 @@ const LogCard = react_1.default.memo(function LogCard({ item, onPress, timelineM
97
97
  }).start();
98
98
  }
99
99
  }, [isNew]);
100
+ const renderStatusIcon = () => {
101
+ if (isLoading) {
102
+ return <NetworkIcons_1.ClockIcon color={AppColors_1.AppColors.darkOrange} size={9}/>;
103
+ }
104
+ const num = typeof item.status === 'number' ? item.status : parseInt(String(item.status || 0), 10);
105
+ if (num >= 200 && num < 300) {
106
+ return <NetworkIcons_1.CircleCheckIcon color={AppColors_1.AppColors.greenColor} size={9}/>;
107
+ }
108
+ if (num >= 300 && num < 400) {
109
+ return <NetworkIcons_1.RepeatIcon color={AppColors_1.AppColors.amber700} size={9}/>;
110
+ }
111
+ if (num >= 400 && num < 500) {
112
+ return <NetworkIcons_1.CircleAlertIcon color={AppColors_1.AppColors.darkOrange} size={9}/>;
113
+ }
114
+ return <NetworkIcons_1.CircleXIcon color={AppColors_1.AppColors.errorColor} size={9}/>;
115
+ };
100
116
  const triggeredAt = (0, helpers_1.formatDateTime)(item.startTime);
101
117
  const isJson = item.url.split('?')[0].toLowerCase().endsWith('.json');
102
118
  return (<TouchableScale_1.default onPress={onPress} style={[
@@ -248,6 +264,9 @@ const LogCard = react_1.default.memo(function LogCard({ item, onPress, timelineM
248
264
  <react_native_1.View style={[
249
265
  styles_1.default.statusPill,
250
266
  {
267
+ flexDirection: 'row',
268
+ alignItems: 'center',
269
+ gap: 3.5,
251
270
  backgroundColor: isFailed
252
271
  ? `${AppColors_1.AppColors.errorColor}15`
253
272
  : isLoading
@@ -260,6 +279,7 @@ const LogCard = react_1.default.memo(function LogCard({ item, onPress, timelineM
260
279
  : `${statusColor}30`,
261
280
  },
262
281
  ]}>
282
+ {renderStatusIcon()}
263
283
  <react_native_1.Text style={[
264
284
  styles_1.default.statusPillText,
265
285
  {
@@ -282,7 +302,17 @@ const LogCard = react_1.default.memo(function LogCard({ item, onPress, timelineM
282
302
  {/* Row 2: Full URL Capsule Container (Clickable with link prompt) */}
283
303
  <react_native_1.View style={styles_1.default.cardSlugBox}>
284
304
  <react_native_1.Pressable onPress={handleOpenUrl} style={styles_1.default.slugLeft} hitSlop={6}>
285
- <react_native_1.Text style={styles_1.default.slugTag}>URL ↗</react_native_1.Text>
305
+ <react_native_1.View style={{
306
+ width: 17,
307
+ height: 17,
308
+ borderRadius: 4,
309
+ backgroundColor: `${AppColors_1.AppColors.skyBlue}1A`,
310
+ alignItems: 'center',
311
+ justifyContent: 'center',
312
+ marginRight: 4,
313
+ }}>
314
+ <NetworkIcons_1.GlobeIcon color={AppColors_1.AppColors.skyBlue} size={11}/>
315
+ </react_native_1.View>
286
316
  <HighlightText_1.default text={item.url} search={searchStr} style={[styles_1.default.slugText, { color: AppColors_1.AppColors.skyBlue, textDecorationLine: 'underline' }]} highlightStyle={styles_1.default.highlight} numberOfLines={2} ellipsizeMode="middle"/>
287
317
  </react_native_1.Pressable>
288
318
 
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { TextStyle } from 'react-native';
3
+ export interface LogSyntaxHighlighterProps {
4
+ text: string;
5
+ search?: string;
6
+ numberOfLines?: number;
7
+ style?: TextStyle | TextStyle[];
8
+ detectLinks?: boolean;
9
+ }
10
+ interface Token {
11
+ type: 'key' | 'string' | 'number' | 'boolean' | 'null' | 'url' | 'bracket' | 'tag' | 'plain';
12
+ value: string;
13
+ }
14
+ export declare const tokenizeText: (input: string) => Token[];
15
+ export declare const LogSyntaxHighlighter: React.FC<LogSyntaxHighlighterProps>;
16
+ export default LogSyntaxHighlighter;
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LogSyntaxHighlighter = exports.tokenizeText = void 0;
7
+ const react_1 = __importDefault(require("react"));
8
+ const react_native_1 = require("react-native");
9
+ const AppColors_1 = require("../styles/AppColors");
10
+ const AppFonts_1 = require("../styles/AppFonts");
11
+ const helpers_1 = require("../helpers");
12
+ const TOKEN_REGEX = /("(?:\\.|[^"\\])*"(?=\s*:))|("(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*')|(\b-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b)|(\b(?:true|false)\b)|(\b(?:null|undefined|NaN)\b)|(https?:\/\/[^\s"',]+)|(\[[\w\s_-]+\])|([{}[\],:])|([^"'\d\s{}[\],:]+|[ \t\r\n]+)/g;
13
+ const tokenizeText = (input) => {
14
+ if (!input)
15
+ return [];
16
+ const tokens = [];
17
+ let match;
18
+ TOKEN_REGEX.lastIndex = 0;
19
+ while ((match = TOKEN_REGEX.exec(input)) !== null) {
20
+ if (match[1]) {
21
+ tokens.push({ type: 'key', value: match[1] });
22
+ }
23
+ else if (match[2]) {
24
+ tokens.push({ type: 'string', value: match[2] });
25
+ }
26
+ else if (match[3]) {
27
+ tokens.push({ type: 'number', value: match[3] });
28
+ }
29
+ else if (match[4]) {
30
+ tokens.push({ type: 'boolean', value: match[4] });
31
+ }
32
+ else if (match[5]) {
33
+ tokens.push({ type: 'null', value: match[5] });
34
+ }
35
+ else if (match[6]) {
36
+ tokens.push({ type: 'url', value: match[6] });
37
+ }
38
+ else if (match[7]) {
39
+ tokens.push({ type: 'tag', value: match[7] });
40
+ }
41
+ else if (match[8]) {
42
+ tokens.push({ type: 'bracket', value: match[8] });
43
+ }
44
+ else if (match[9]) {
45
+ tokens.push({ type: 'plain', value: match[9] });
46
+ }
47
+ }
48
+ return tokens;
49
+ };
50
+ exports.tokenizeText = tokenizeText;
51
+ const getTokenColor = (type) => {
52
+ switch (type) {
53
+ case 'key':
54
+ return AppColors_1.AppColors.sky600 || '#0369a1';
55
+ case 'string':
56
+ return AppColors_1.AppColors.emerald600 || '#059669';
57
+ case 'number':
58
+ return AppColors_1.AppColors.amber600 || '#d97706';
59
+ case 'boolean':
60
+ return AppColors_1.AppColors.purple || '#7c3aed';
61
+ case 'null':
62
+ return AppColors_1.AppColors.red600 || '#dc2626';
63
+ case 'url':
64
+ return '#0284c7';
65
+ case 'tag':
66
+ return AppColors_1.AppColors.violet600 || '#7c3aed';
67
+ case 'bracket':
68
+ return AppColors_1.AppColors.slate500 || '#64748b';
69
+ case 'plain':
70
+ default:
71
+ return AppColors_1.AppColors.primaryBlack || '#1e293b';
72
+ }
73
+ };
74
+ exports.LogSyntaxHighlighter = react_1.default.memo(({ text, search, numberOfLines, style, detectLinks = true }) => {
75
+ if (!text)
76
+ return null;
77
+ const tokens = react_1.default.useMemo(() => (0, exports.tokenizeText)(text), [text]);
78
+ const renderToken = (token, tokenIdx) => {
79
+ const baseColor = getTokenColor(token.type);
80
+ const isUrl = token.type === 'url';
81
+ const isKey = token.type === 'key';
82
+ const tokenStyle = {
83
+ color: baseColor,
84
+ fontFamily: isKey ? AppFonts_1.AppFonts.interBold : AppFonts_1.AppFonts.interRegular,
85
+ textDecorationLine: isUrl ? 'underline' : 'none',
86
+ };
87
+ if (!search || search.trim().length === 0) {
88
+ return (<react_native_1.Text key={tokenIdx} style={tokenStyle} onPress={isUrl && detectLinks
89
+ ? () => (0, helpers_1.handleOpenExternalLink)(token.value)
90
+ : undefined}>
91
+ {token.value}
92
+ </react_native_1.Text>);
93
+ }
94
+ const regex = new RegExp(`(${(0, helpers_1.escapeRegex)(search.trim())})`, 'gi');
95
+ const parts = token.value.split(regex);
96
+ return (<react_native_1.Text key={tokenIdx} style={tokenStyle}>
97
+ {parts.map((part, partIdx) => {
98
+ const isMatch = part.toLowerCase() === search.trim().toLowerCase();
99
+ return isMatch ? (<react_native_1.Text key={partIdx} style={[
100
+ tokenStyle,
101
+ styles.searchHighlight,
102
+ ]}>
103
+ {part}
104
+ </react_native_1.Text>) : (<react_native_1.Text key={partIdx} style={tokenStyle} onPress={isUrl && detectLinks
105
+ ? () => (0, helpers_1.handleOpenExternalLink)(token.value)
106
+ : undefined}>
107
+ {part}
108
+ </react_native_1.Text>);
109
+ })}
110
+ </react_native_1.Text>);
111
+ };
112
+ return (<react_native_1.Text style={[styles.containerText, style]} numberOfLines={numberOfLines}>
113
+ {tokens.map(renderToken)}
114
+ </react_native_1.Text>);
115
+ });
116
+ const styles = react_native_1.StyleSheet.create({
117
+ containerText: {
118
+ fontFamily: AppFonts_1.AppFonts.interRegular,
119
+ fontSize: 12,
120
+ lineHeight: 18,
121
+ color: AppColors_1.AppColors.primaryBlack,
122
+ },
123
+ searchHighlight: {
124
+ backgroundColor: '#fef08a',
125
+ color: '#854d0e',
126
+ fontFamily: AppFonts_1.AppFonts.interBold,
127
+ borderRadius: 2,
128
+ },
129
+ });
130
+ exports.default = exports.LogSyntaxHighlighter;
@@ -124,3 +124,6 @@ export declare const SmartphoneIcon: ({ color, size }: IconProps) => React.JSX.E
124
124
  export declare const AlertTriangleIcon: ({ color, size }: IconProps) => React.JSX.Element;
125
125
  export declare const BugIcon: ({ color, size }: IconProps) => React.JSX.Element;
126
126
  export declare const TagIcon: ({ color, size }: IconProps) => React.JSX.Element;
127
+ export declare const NpmIcon: ({ color, size }: IconProps) => React.JSX.Element;
128
+ export declare const ResetIcon: ({ color, size }: IconProps) => React.JSX.Element;
129
+ export declare const ChevronDownIcon: ({ color, size }: IconProps) => React.JSX.Element;
@@ -38,7 +38,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
39
  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.CircleAlertIcon = exports.CircleXIcon = exports.CircleCheckIcon = 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
  exports.DiagnosticsIcon = exports.StackTraceIcon = exports.LayoutIcon = exports.ChipIcon = exports.SkullIcon = exports.ShieldAlertIcon = exports.CrashIcon = exports.UserCheckIcon = exports.TargetGoalIcon = exports.RepeatIcon = exports.PinIcon = exports.HourglassIcon = exports.FlameIcon = exports.CodeBracketsIcon = exports.AndroidIcon = exports.AppleIcon = exports.LinkChainIcon = exports.GitHubIcon = exports.PackageBoxIcon = exports.ExternalLinkIcon = exports.MoneyIcon = exports.CartIcon = exports.TextAaIcon = exports.BrainIcon = exports.AtomIcon = exports.MapIcon = exports.SparkleIcon = exports.LightbulbIcon = exports.DocIcon = exports.FolderOpenIcon = exports.BanIcon = exports.BoltIcon = exports.PerformanceIcon = exports.ReduxIcon = exports.MetadataIcon = exports.StorageIcon = exports.RefreshCcwIcon = exports.TimelineIcon = exports.LiveStateIcon = exports.BundleIcon = exports.ForwardChevronIcon = exports.PackageIcon = exports.TableIcon = exports.RawIcon = exports.PrettyIcon = exports.SortIcon = exports.MotionIcon = exports.TrendingUpIcon = exports.ErrorCircleIcon = exports.WarningTriangleIcon = void 0;
41
- exports.TagIcon = exports.BugIcon = exports.AlertTriangleIcon = exports.SmartphoneIcon = exports.KeyIcon = exports.BarChartIcon = exports.DiceIcon = exports.ZapIcon = exports.FlaskIcon = exports.LoadingSpinnerIcon = exports.ListenerIcon = exports.AllFramesIcon = exports.AppFramesIcon = exports.RawJsonIcon = exports.TrailIcon = void 0;
41
+ exports.ChevronDownIcon = exports.ResetIcon = exports.NpmIcon = exports.TagIcon = exports.BugIcon = exports.AlertTriangleIcon = exports.SmartphoneIcon = exports.KeyIcon = exports.BarChartIcon = exports.DiceIcon = exports.ZapIcon = exports.FlaskIcon = exports.LoadingSpinnerIcon = exports.ListenerIcon = exports.AllFramesIcon = exports.AppFramesIcon = exports.RawJsonIcon = exports.TrailIcon = void 0;
42
42
  const react_1 = __importDefault(require("react"));
43
43
  const react_native_svg_1 = __importStar(require("react-native-svg"));
44
44
  // Stylesheet
@@ -855,3 +855,17 @@ const TagIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 14 }) => (
855
855
  <react_native_svg_1.Circle cx="7.5" cy="7.5" r="1.5" fill={color}/>
856
856
  </react_native_svg_1.default>);
857
857
  exports.TagIcon = TagIcon;
858
+ const NpmIcon = ({ color = '#CB3837', size = 14 }) => (<react_native_svg_1.default width={size} height={size} viewBox="0 0 256 256" fill="none">
859
+ <react_native_svg_1.Rect width="256" height="256" rx="32" fill={color}/>
860
+ <react_native_svg_1.Path d="M48 48h160v160h-32V96h-32v112H48V48z" fill="#FFFFFF"/>
861
+ </react_native_svg_1.default>);
862
+ exports.NpmIcon = NpmIcon;
863
+ const ResetIcon = ({ color = AppColors_1.AppColors.white, size = 16 }) => (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
864
+ <react_native_svg_1.Path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
865
+ <react_native_svg_1.Path d="M3 3v5h5" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
866
+ </react_native_svg_1.default>);
867
+ exports.ResetIcon = ResetIcon;
868
+ const ChevronDownIcon = ({ color = AppColors_1.AppColors.grayTextWeak, size = 14 }) => (<react_native_svg_1.default width={size} height={size} viewBox="0 0 24 24" fill="none">
869
+ <react_native_svg_1.Path d="M6 9l6 6 6-6" stroke={color} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
870
+ </react_native_svg_1.default>);
871
+ exports.ChevronDownIcon = ChevronDownIcon;
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ export interface SliderProps {
3
+ value: number;
4
+ onValueChange: (value: number) => void;
5
+ min?: number;
6
+ max?: number;
7
+ step?: number;
8
+ formatLabel?: (value: number) => string;
9
+ quickPresets?: number[];
10
+ disabled?: boolean;
11
+ }
12
+ export declare const Slider: React.FC<SliderProps>;
13
+ export default Slider;
@@ -0,0 +1,261 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.Slider = void 0;
40
+ const react_1 = __importStar(require("react"));
41
+ const react_native_1 = require("react-native");
42
+ const AppColors_1 = require("../styles/AppColors");
43
+ const AppFonts_1 = require("../styles/AppFonts");
44
+ const TouchableScale_1 = __importDefault(require("./TouchableScale"));
45
+ exports.Slider = react_1.default.memo(({ value, onValueChange, min = 50, max = 90, step = 5, formatLabel = val => `${Math.round(val)}%`, quickPresets = [50, 60, 70, 80, 90], disabled = false, }) => {
46
+ const trackWidthRef = (0, react_1.useRef)(0);
47
+ const [trackWidth, setTrackWidth] = (0, react_1.useState)(0);
48
+ const [isDragging, setIsDragging] = (0, react_1.useState)(false);
49
+ const clampedValue = Math.max(min, Math.min(max, value));
50
+ const percentage = (clampedValue - min) / (max - min || 1);
51
+ const updateValueFromPosition = (0, react_1.useCallback)((pageX, trackPageX) => {
52
+ if (trackWidthRef.current <= 0)
53
+ return;
54
+ const relativeX = Math.max(0, Math.min(trackWidthRef.current, pageX - trackPageX));
55
+ const rawRatio = relativeX / trackWidthRef.current;
56
+ let newValue = min + rawRatio * (max - min);
57
+ if (step > 0) {
58
+ newValue = Math.round(newValue / step) * step;
59
+ }
60
+ newValue = Math.max(min, Math.min(max, newValue));
61
+ onValueChange(newValue);
62
+ }, [min, max, step, onValueChange]);
63
+ const trackContainerRef = (0, react_1.useRef)(null);
64
+ const trackPageXRef = (0, react_1.useRef)(0);
65
+ const measureTrack = (0, react_1.useCallback)(() => {
66
+ if (trackContainerRef.current) {
67
+ trackContainerRef.current.measure((_x, _y, _width, _height, pageX) => {
68
+ trackPageXRef.current = pageX;
69
+ });
70
+ }
71
+ }, []);
72
+ const panResponder = (0, react_1.useMemo)(() => react_native_1.PanResponder.create({
73
+ onStartShouldSetPanResponder: () => !disabled,
74
+ onMoveShouldSetPanResponder: () => !disabled,
75
+ onPanResponderGrant: (evt) => {
76
+ setIsDragging(true);
77
+ measureTrack();
78
+ updateValueFromPosition(evt.nativeEvent.pageX, trackPageXRef.current);
79
+ },
80
+ onPanResponderMove: (evt, _gestureState) => {
81
+ updateValueFromPosition(evt.nativeEvent.pageX, trackPageXRef.current);
82
+ },
83
+ onPanResponderRelease: () => {
84
+ setIsDragging(false);
85
+ },
86
+ onPanResponderTerminate: () => {
87
+ setIsDragging(false);
88
+ },
89
+ }), [disabled, measureTrack, updateValueFromPosition]);
90
+ const handleLayout = (e) => {
91
+ const w = e.nativeEvent.layout.width;
92
+ trackWidthRef.current = w;
93
+ setTrackWidth(w);
94
+ measureTrack();
95
+ };
96
+ const thumbPosition = percentage * (trackWidth || 0);
97
+ return (<react_native_1.View style={styles.container}>
98
+ {/* Value Display Row */}
99
+ <react_native_1.View style={styles.valueRow}>
100
+ <react_native_1.Text style={styles.rangeText}>{min}%</react_native_1.Text>
101
+ <react_native_1.View style={[
102
+ styles.currentValueBadge,
103
+ isDragging && styles.currentValueBadgeActive,
104
+ ]}>
105
+ <react_native_1.Text style={styles.currentValueText}>{formatLabel(clampedValue)}</react_native_1.Text>
106
+ </react_native_1.View>
107
+ <react_native_1.Text style={styles.rangeText}>{max}%</react_native_1.Text>
108
+ </react_native_1.View>
109
+
110
+ {/* Interactive Track Area */}
111
+ <react_native_1.View ref={trackContainerRef} onLayout={handleLayout} {...panResponder.panHandlers} style={styles.touchArea}>
112
+ {/* Background Rail */}
113
+ <react_native_1.View style={styles.rail}>
114
+ {/* Active Filled Bar */}
115
+ <react_native_1.View style={[
116
+ styles.fillBar,
117
+ { width: `${Math.round(percentage * 100)}%` },
118
+ ]}/>
119
+ </react_native_1.View>
120
+
121
+ {/* Draggable Thumb */}
122
+ <react_native_1.View style={[
123
+ styles.thumb,
124
+ {
125
+ left: Math.max(0, Math.min((trackWidth || 0) - 24, thumbPosition - 12)),
126
+ },
127
+ isDragging && styles.thumbActive,
128
+ ]}>
129
+ <react_native_1.View style={styles.thumbCenterDot}/>
130
+ </react_native_1.View>
131
+ </react_native_1.View>
132
+
133
+ {/* Quick Presets */}
134
+ {quickPresets && quickPresets.length > 0 && (<react_native_1.View style={styles.presetRow}>
135
+ {quickPresets.map(preset => {
136
+ const isSelected = Math.round(clampedValue) === preset;
137
+ return (<TouchableScale_1.default key={preset} onPress={() => onValueChange(preset)} style={[
138
+ styles.presetButton,
139
+ isSelected && styles.presetButtonActive,
140
+ ]}>
141
+ <react_native_1.Text style={[
142
+ styles.presetText,
143
+ isSelected && styles.presetTextActive,
144
+ ]}>
145
+ {preset}%
146
+ </react_native_1.Text>
147
+ </TouchableScale_1.default>);
148
+ })}
149
+ </react_native_1.View>)}
150
+ </react_native_1.View>);
151
+ });
152
+ const styles = react_native_1.StyleSheet.create({
153
+ container: {
154
+ paddingVertical: 4,
155
+ gap: 8,
156
+ },
157
+ valueRow: {
158
+ flexDirection: 'row',
159
+ alignItems: 'center',
160
+ justifyContent: 'space-between',
161
+ paddingHorizontal: 2,
162
+ },
163
+ rangeText: {
164
+ fontFamily: AppFonts_1.AppFonts.interMedium,
165
+ fontSize: 11,
166
+ color: AppColors_1.AppColors.grayText,
167
+ },
168
+ currentValueBadge: {
169
+ backgroundColor: `${AppColors_1.AppColors.purple}1A`,
170
+ borderColor: `${AppColors_1.AppColors.purple}33`,
171
+ borderWidth: 1,
172
+ borderRadius: 8,
173
+ paddingHorizontal: 10,
174
+ paddingVertical: 2.5,
175
+ },
176
+ currentValueBadgeActive: {
177
+ backgroundColor: AppColors_1.AppColors.purple,
178
+ borderColor: AppColors_1.AppColors.purple,
179
+ transform: [{ scale: 1.05 }],
180
+ },
181
+ currentValueText: {
182
+ fontFamily: AppFonts_1.AppFonts.interBold,
183
+ fontSize: 12,
184
+ color: AppColors_1.AppColors.purple,
185
+ },
186
+ touchArea: {
187
+ height: 36,
188
+ justifyContent: 'center',
189
+ position: 'relative',
190
+ },
191
+ rail: {
192
+ height: 8,
193
+ backgroundColor: `${AppColors_1.AppColors.grayTextWeak}2B`,
194
+ borderRadius: 4,
195
+ overflow: 'hidden',
196
+ position: 'relative',
197
+ },
198
+ fillBar: {
199
+ height: '100%',
200
+ backgroundColor: AppColors_1.AppColors.purple,
201
+ borderRadius: 4,
202
+ },
203
+ thumb: {
204
+ position: 'absolute',
205
+ width: 24,
206
+ height: 24,
207
+ borderRadius: 12,
208
+ backgroundColor: AppColors_1.AppColors.white,
209
+ borderWidth: 2.5,
210
+ borderColor: AppColors_1.AppColors.purple,
211
+ alignItems: 'center',
212
+ justifyContent: 'center',
213
+ shadowColor: AppColors_1.AppColors.black,
214
+ shadowOffset: { width: 0, height: 2 },
215
+ shadowOpacity: 0.18,
216
+ shadowRadius: 3.5,
217
+ elevation: 4,
218
+ },
219
+ thumbActive: {
220
+ transform: [{ scale: 1.15 }],
221
+ shadowOpacity: 0.28,
222
+ shadowRadius: 5,
223
+ elevation: 6,
224
+ borderColor: AppColors_1.AppColors.purple,
225
+ },
226
+ thumbCenterDot: {
227
+ width: 6,
228
+ height: 6,
229
+ borderRadius: 3,
230
+ backgroundColor: AppColors_1.AppColors.purple,
231
+ },
232
+ presetRow: {
233
+ flexDirection: 'row',
234
+ alignItems: 'center',
235
+ justifyContent: 'space-between',
236
+ gap: 8,
237
+ marginTop: 2,
238
+ },
239
+ presetButton: {
240
+ flex: 1,
241
+ paddingVertical: 5,
242
+ borderRadius: 7,
243
+ alignItems: 'center',
244
+ backgroundColor: AppColors_1.AppColors.grayBackground,
245
+ borderWidth: 1,
246
+ borderColor: AppColors_1.AppColors.dividerColor,
247
+ },
248
+ presetButtonActive: {
249
+ backgroundColor: `${AppColors_1.AppColors.purple}20`,
250
+ borderColor: AppColors_1.AppColors.purple,
251
+ },
252
+ presetText: {
253
+ fontFamily: AppFonts_1.AppFonts.interBold,
254
+ fontSize: 10.5,
255
+ color: AppColors_1.AppColors.grayText,
256
+ },
257
+ presetTextActive: {
258
+ color: AppColors_1.AppColors.purple,
259
+ },
260
+ });
261
+ exports.default = exports.Slider;
@@ -7,6 +7,7 @@ export interface TouchableScaleProps extends PressableProps {
7
7
  children?: React.ReactNode;
8
8
  hitSlop?: any;
9
9
  disabled?: boolean;
10
+ enableHaptics?: boolean;
10
11
  }
11
12
  declare const TouchableScale: React.NamedExoticComponent<TouchableScaleProps>;
12
13
  export default TouchableScale;
@@ -35,48 +35,46 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  const react_1 = __importStar(require("react"));
37
37
  const react_native_1 = require("react-native");
38
- const TouchableScale = react_1.default.memo(function TouchableScale({ onPress, onLongPress, style, children, hitSlop, disabled, accessible, accessibilityRole, accessibilityLabel, accessibilityHint, accessibilityState, accessibilityValue, ...rest }) {
39
- if (react_native_1.Platform.OS === 'android') {
40
- return (<react_native_1.Pressable accessible={accessible} accessibilityRole={accessibilityRole} accessibilityLabel={accessibilityLabel} accessibilityHint={accessibilityHint} accessibilityState={accessibilityState} accessibilityValue={accessibilityValue} disabled={disabled} onPress={onPress} onLongPress={onLongPress} hitSlop={hitSlop} style={({ pressed }) => [
41
- style,
42
- { opacity: pressed ? 0.75 : 1 },
43
- ]} {...rest}>
44
- {children}
45
- </react_native_1.Pressable>);
46
- }
38
+ const NativeInspector_1 = require("../native/NativeInspector");
39
+ const AnimatedPressable = react_native_1.Animated.createAnimatedComponent(react_native_1.Pressable);
40
+ const TouchableScale = react_1.default.memo(function TouchableScale({ onPress, onLongPress, style, children, hitSlop, disabled, enableHaptics = true, accessible, accessibilityRole, accessibilityLabel, accessibilityHint, accessibilityState, accessibilityValue, ...rest }) {
47
41
  const scale = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
48
42
  const opacity = (0, react_1.useRef)(new react_native_1.Animated.Value(1)).current;
49
- const animatePress = (pressed) => {
43
+ const handlePressIn = () => {
44
+ if (disabled)
45
+ return;
46
+ if (enableHaptics) {
47
+ (0, NativeInspector_1.triggerNativeHaptic)('light');
48
+ }
50
49
  react_native_1.Animated.parallel([
51
- react_native_1.Animated.spring(scale, {
52
- toValue: pressed ? 0.94 : 1,
53
- friction: 6,
54
- tension: 120,
50
+ react_native_1.Animated.timing(scale, {
51
+ toValue: 0.94,
52
+ duration: 50,
55
53
  useNativeDriver: true,
56
54
  }),
57
55
  react_native_1.Animated.timing(opacity, {
58
- toValue: pressed ? 0.86 : 1,
59
- duration: pressed ? 90 : 140,
56
+ toValue: 0.85,
57
+ duration: 50,
60
58
  useNativeDriver: true,
61
59
  }),
62
60
  ]).start();
63
61
  };
64
- const flattenedStyle = react_native_1.StyleSheet.flatten(style) || {};
65
- const layoutStyle = {
66
- flex: flattenedStyle.flex,
67
- flexDirection: flattenedStyle.flexDirection,
68
- alignItems: flattenedStyle.alignItems,
69
- justifyContent: flattenedStyle.justifyContent,
70
- flexWrap: flattenedStyle.flexWrap,
71
- alignSelf: flattenedStyle.alignSelf,
72
- flexGrow: flattenedStyle.flexGrow,
73
- flexShrink: flattenedStyle.flexShrink,
74
- gap: flattenedStyle.gap,
62
+ const handlePressOut = () => {
63
+ react_native_1.Animated.parallel([
64
+ react_native_1.Animated.timing(scale, {
65
+ toValue: 1,
66
+ duration: 100,
67
+ useNativeDriver: true,
68
+ }),
69
+ react_native_1.Animated.timing(opacity, {
70
+ toValue: 1,
71
+ duration: 100,
72
+ useNativeDriver: true,
73
+ }),
74
+ ]).start();
75
75
  };
76
- return (<react_native_1.Pressable accessible={accessible} accessibilityRole={accessibilityRole} accessibilityLabel={accessibilityLabel} accessibilityHint={accessibilityHint} accessibilityState={accessibilityState} accessibilityValue={accessibilityValue} disabled={disabled} style={style} onPressIn={() => animatePress(true)} onPressOut={() => animatePress(false)} onPress={onPress} onLongPress={onLongPress} hitSlop={hitSlop} {...rest}>
77
- <react_native_1.Animated.View style={[{ opacity, transform: [{ scale }] }, layoutStyle]}>
78
- {children}
79
- </react_native_1.Animated.View>
80
- </react_native_1.Pressable>);
76
+ return (<AnimatedPressable accessible={accessible} accessibilityRole={accessibilityRole} accessibilityLabel={accessibilityLabel} accessibilityHint={accessibilityHint} accessibilityState={accessibilityState} accessibilityValue={accessibilityValue} disabled={disabled} style={[style, { opacity, transform: [{ scale }] }]} onPressIn={handlePressIn} onPressOut={handlePressOut} onPress={onPress} onLongPress={onLongPress} hitSlop={hitSlop} {...rest}>
77
+ {children}
78
+ </AnimatedPressable>);
81
79
  });
82
80
  exports.default = TouchableScale;