react-native-network-lens 0.1.0 → 0.2.0

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 (57) hide show
  1. package/README.md +254 -97
  2. package/lib/module/components/BodyViewer.js +31 -19
  3. package/lib/module/components/BodyViewer.js.map +1 -1
  4. package/lib/module/components/JsonTree/JsonTreeView.js +10 -6
  5. package/lib/module/components/JsonTree/JsonTreeView.js.map +1 -1
  6. package/lib/module/components/JsonTree/model.js +2 -0
  7. package/lib/module/components/JsonTree/model.js.map +1 -1
  8. package/lib/module/components/NetworkLens.js +4 -8
  9. package/lib/module/components/NetworkLens.js.map +1 -1
  10. package/lib/module/components/NetworkLensOverlay.js +67 -22
  11. package/lib/module/components/NetworkLensOverlay.js.map +1 -1
  12. package/lib/module/components/RawTextView.js +10 -6
  13. package/lib/module/components/RawTextView.js.map +1 -1
  14. package/lib/module/components/RequestDetails/RequestDetails.js +44 -21
  15. package/lib/module/components/RequestDetails/RequestDetails.js.map +1 -1
  16. package/lib/module/components/RequestList/FilterBar.js +3 -3
  17. package/lib/module/components/RequestList/FilterBar.js.map +1 -1
  18. package/lib/module/components/RequestList/RequestList.js +7 -8
  19. package/lib/module/components/RequestList/RequestList.js.map +1 -1
  20. package/lib/module/components/ui/Button.js +21 -5
  21. package/lib/module/components/ui/Button.js.map +1 -1
  22. package/lib/module/components/ui/Pill.js +13 -6
  23. package/lib/module/components/ui/Pill.js.map +1 -1
  24. package/lib/module/settings.js +48 -0
  25. package/lib/module/settings.js.map +1 -0
  26. package/lib/module/theme.js +4 -4
  27. package/lib/typescript/src/components/BodyViewer.d.ts.map +1 -1
  28. package/lib/typescript/src/components/JsonTree/JsonTreeView.d.ts.map +1 -1
  29. package/lib/typescript/src/components/JsonTree/model.d.ts.map +1 -1
  30. package/lib/typescript/src/components/NetworkLens.d.ts +0 -3
  31. package/lib/typescript/src/components/NetworkLens.d.ts.map +1 -1
  32. package/lib/typescript/src/components/NetworkLensOverlay.d.ts +1 -1
  33. package/lib/typescript/src/components/NetworkLensOverlay.d.ts.map +1 -1
  34. package/lib/typescript/src/components/RawTextView.d.ts.map +1 -1
  35. package/lib/typescript/src/components/RequestDetails/RequestDetails.d.ts.map +1 -1
  36. package/lib/typescript/src/components/RequestList/RequestList.d.ts +1 -4
  37. package/lib/typescript/src/components/RequestList/RequestList.d.ts.map +1 -1
  38. package/lib/typescript/src/components/ui/Button.d.ts +3 -1
  39. package/lib/typescript/src/components/ui/Button.d.ts.map +1 -1
  40. package/lib/typescript/src/components/ui/Pill.d.ts +1 -0
  41. package/lib/typescript/src/components/ui/Pill.d.ts.map +1 -1
  42. package/lib/typescript/src/settings.d.ts +18 -0
  43. package/lib/typescript/src/settings.d.ts.map +1 -0
  44. package/package.json +3 -3
  45. package/src/components/BodyViewer.tsx +37 -19
  46. package/src/components/JsonTree/JsonTreeView.tsx +11 -5
  47. package/src/components/JsonTree/model.ts +2 -0
  48. package/src/components/NetworkLens.tsx +2 -11
  49. package/src/components/NetworkLensOverlay.tsx +54 -23
  50. package/src/components/RawTextView.tsx +11 -6
  51. package/src/components/RequestDetails/RequestDetails.tsx +31 -19
  52. package/src/components/RequestList/FilterBar.tsx +2 -2
  53. package/src/components/RequestList/RequestList.tsx +3 -7
  54. package/src/components/ui/Button.tsx +23 -7
  55. package/src/components/ui/Pill.tsx +14 -5
  56. package/src/settings.ts +55 -0
  57. package/src/theme.ts +2 -2
@@ -1,4 +1,4 @@
1
- import { useCallback, useMemo, useState, type ReactNode } from 'react';
1
+ import { useCallback, useMemo, useState } from 'react';
2
2
  import { FlatList, Share, StyleSheet, Text, View } from 'react-native';
3
3
  import type NetworkRequest from '../../core/NetworkRequest';
4
4
  import { useTheme } from '../../theme';
@@ -30,8 +30,6 @@ interface Props {
30
30
  loggingEnabled: boolean;
31
31
  onPressItem: (id: string) => void;
32
32
  menuActions: ActionItem[];
33
- /** Optional row rendered above the search bar (used by the overlay for title + close). */
34
- header?: ReactNode;
35
33
  }
36
34
 
37
35
  const keyExtractor = (row: NetworkRequestRow) => row.id;
@@ -52,7 +50,6 @@ const RequestList = ({
52
50
  loggingEnabled,
53
51
  onPressItem,
54
52
  menuActions,
55
- header,
56
53
  }: Props) => {
57
54
  const theme = useTheme();
58
55
  const [search, setSearch] = useState('');
@@ -134,7 +131,6 @@ const RequestList = ({
134
131
  },
135
132
  ]}
136
133
  >
137
- {header}
138
134
  <View style={styles.searchRow}>
139
135
  <SearchInput
140
136
  value={search}
@@ -215,8 +211,8 @@ const styles = StyleSheet.create({
215
211
  paddingVertical: 8,
216
212
  borderBottomWidth: StyleSheet.hairlineWidth,
217
213
  },
218
- searchRow: { flexDirection: 'row', alignItems: 'center', gap: 4 },
219
- search: { flex: 1 },
214
+ searchRow: { flexDirection: 'row', alignItems: 'center' },
215
+ search: { flex: 1, marginRight: 4 },
220
216
  statusBar: { paddingHorizontal: 12, paddingVertical: 4 },
221
217
  statusText: { fontSize: 11, fontWeight: '600' },
222
218
  statusTextPaused: { color: '#ffffff' },
@@ -8,11 +8,17 @@ import {
8
8
  } from 'react-native';
9
9
  import { useTheme } from '../../theme';
10
10
 
11
+ // Object form keeps compatibility with React Native versions before numeric hitSlop.
12
+ const HIT_SLOP_SMALL = { top: 6, bottom: 6, left: 6, right: 6 };
13
+ const HIT_SLOP = { top: 8, bottom: 8, left: 8, right: 8 };
14
+
11
15
  interface TextButtonProps {
12
16
  label: string;
13
17
  onPress?: () => void;
14
18
  disabled?: boolean;
15
19
  active?: boolean;
20
+ /** Text-only button in the primary colour, for navigation actions like Back. */
21
+ plain?: boolean;
16
22
  style?: StyleProp<ViewStyle>;
17
23
  textStyle?: StyleProp<TextStyle>;
18
24
  }
@@ -22,6 +28,7 @@ export const TextButton = ({
22
28
  onPress,
23
29
  disabled,
24
30
  active,
31
+ plain,
25
32
  style,
26
33
  textStyle,
27
34
  }: TextButtonProps) => {
@@ -31,13 +38,15 @@ export const TextButton = ({
31
38
  accessibilityRole="button"
32
39
  disabled={disabled}
33
40
  onPress={onPress}
34
- hitSlop={6}
41
+ hitSlop={HIT_SLOP_SMALL}
35
42
  style={({ pressed }) => [
36
43
  styles.button,
37
44
  {
38
- backgroundColor: active
39
- ? theme.colors.primary
40
- : theme.colors.surfaceAlt,
45
+ backgroundColor: plain
46
+ ? 'transparent'
47
+ : active
48
+ ? theme.colors.primary
49
+ : theme.colors.surfaceAlt,
41
50
  },
42
51
  disabled ? styles.disabled : pressed && styles.pressed,
43
52
  style,
@@ -46,7 +55,13 @@ export const TextButton = ({
46
55
  <Text
47
56
  style={[
48
57
  styles.label,
49
- { color: active ? theme.colors.onPrimary : theme.colors.text },
58
+ {
59
+ color: plain
60
+ ? theme.colors.primary
61
+ : active
62
+ ? theme.colors.onPrimary
63
+ : theme.colors.text,
64
+ },
50
65
  textStyle,
51
66
  ]}
52
67
  >
@@ -79,7 +94,7 @@ export const IconButton = ({
79
94
  accessibilityLabel={accessibilityLabel}
80
95
  disabled={disabled}
81
96
  onPress={onPress}
82
- hitSlop={8}
97
+ hitSlop={HIT_SLOP}
83
98
  style={({ pressed }) => [
84
99
  styles.icon,
85
100
  active && { backgroundColor: theme.colors.primary },
@@ -108,7 +123,8 @@ const styles = StyleSheet.create({
108
123
  },
109
124
  label: { fontSize: 13, fontWeight: '600' },
110
125
  icon: {
111
- width: 32,
126
+ minWidth: 32,
127
+ paddingHorizontal: 6,
112
128
  height: 32,
113
129
  borderRadius: 8,
114
130
  alignItems: 'center',
@@ -14,6 +14,7 @@ interface Props {
14
14
  style?: StyleProp<ViewStyle>;
15
15
  }
16
16
 
17
+ /** Fixed-height badge so filled and outlined variants align on one row. */
17
18
  export const Pill = ({ label, color, filled, small, style }: Props) => (
18
19
  <View
19
20
  style={[
@@ -39,15 +40,23 @@ export const Pill = ({ label, color, filled, small, style }: Props) => (
39
40
 
40
41
  const styles = StyleSheet.create({
41
42
  pill: {
43
+ height: 24,
44
+ minWidth: 44,
45
+ paddingHorizontal: 8,
42
46
  borderWidth: 1,
43
47
  borderRadius: 6,
44
- paddingHorizontal: 6,
45
- paddingVertical: 2,
48
+ alignItems: 'center',
49
+ justifyContent: 'center',
46
50
  alignSelf: 'flex-start',
47
51
  },
48
- pillSmall: { paddingHorizontal: 4, paddingVertical: 1, borderRadius: 4 },
52
+ pillSmall: {
53
+ height: 20,
54
+ minWidth: 40,
55
+ paddingHorizontal: 6,
56
+ borderRadius: 5,
57
+ },
49
58
  outline: { backgroundColor: 'transparent' },
50
- text: { fontSize: 12, fontWeight: '700', letterSpacing: 0.3 },
51
- textSmall: { fontSize: 11 },
59
+ text: { fontSize: 12, lineHeight: 14, fontWeight: '700', letterSpacing: 0.3 },
60
+ textSmall: { fontSize: 11, lineHeight: 13 },
52
61
  textFilled: { color: '#ffffff' },
53
62
  });
@@ -0,0 +1,55 @@
1
+ import { useSyncExternalStore } from 'react';
2
+ import type { Theme } from './theme';
3
+
4
+ /**
5
+ * Tiny in-memory preferences shared by every viewer in the session, e.g. the
6
+ * code font scale the user picks with the "Aa" button.
7
+ */
8
+ export type CodeFontScale = 'small' | 'medium' | 'large';
9
+
10
+ const SCALE_FACTOR: Record<CodeFontScale, number> = {
11
+ small: 0.85,
12
+ medium: 1,
13
+ large: 1.2,
14
+ };
15
+ const ORDER: CodeFontScale[] = ['small', 'medium', 'large'];
16
+
17
+ let scale: CodeFontScale = 'medium';
18
+ const listeners = new Set<() => void>();
19
+
20
+ const subscribe = (listener: () => void) => {
21
+ listeners.add(listener);
22
+ return () => {
23
+ listeners.delete(listener);
24
+ };
25
+ };
26
+ const getScale = () => scale;
27
+
28
+ export const setCodeFontScale = (next: CodeFontScale) => {
29
+ if (scale === next) return;
30
+ scale = next;
31
+ listeners.forEach((listener) => listener());
32
+ };
33
+
34
+ export const cycleCodeFontScale = () => {
35
+ setCodeFontScale(
36
+ ORDER[(ORDER.indexOf(scale) + 1) % ORDER.length] ?? 'medium'
37
+ );
38
+ };
39
+
40
+ export const useCodeFontScale = (): CodeFontScale =>
41
+ useSyncExternalStore(subscribe, getScale, getScale);
42
+
43
+ /** Font metrics for code views: the theme's base size times the chosen scale. */
44
+ export const useCodeFont = (theme: Theme) => {
45
+ const current = useCodeFontScale();
46
+ const factor = SCALE_FACTOR[current];
47
+ const fontSize = Math.round(theme.sizes.codeFontSize * factor);
48
+ return {
49
+ scale: current,
50
+ fontSize,
51
+ lineHeight: Math.round(fontSize * 1.5),
52
+ /** Average glyph advance for monospace fonts; used to size horizontal scroll areas. */
53
+ charWidth: fontSize * 0.62,
54
+ };
55
+ };
package/src/theme.ts CHANGED
@@ -80,7 +80,7 @@ export const lightTheme: Theme = {
80
80
  onHighlight: '#1f2937',
81
81
  },
82
82
  fonts: { mono: mono ?? 'monospace' },
83
- sizes: { codeFontSize: 13, codeLineHeight: 20 },
83
+ sizes: { codeFontSize: 14, codeLineHeight: 21 },
84
84
  };
85
85
 
86
86
  export const darkTheme: Theme = {
@@ -114,7 +114,7 @@ export const darkTheme: Theme = {
114
114
  onHighlight: '#fef3c7',
115
115
  },
116
116
  fonts: { mono: mono ?? 'monospace' },
117
- sizes: { codeFontSize: 13, codeLineHeight: 20 },
117
+ sizes: { codeFontSize: 14, codeLineHeight: 21 },
118
118
  };
119
119
 
120
120
  export type ThemeInput = ThemeName | DeepPartial<Theme>;