rn-backstage 1.1.0 → 1.2.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 (103) hide show
  1. package/README.md +41 -19
  2. package/lib/commonjs/Backstage.js +42 -31
  3. package/lib/commonjs/Backstage.js.map +1 -1
  4. package/lib/commonjs/ThemeContext.js +43 -0
  5. package/lib/commonjs/ThemeContext.js.map +1 -0
  6. package/lib/commonjs/components/BackstagePanel.js +38 -16
  7. package/lib/commonjs/components/BackstagePanel.js.map +1 -1
  8. package/lib/commonjs/components/FlagsTab.js +256 -0
  9. package/lib/commonjs/components/FlagsTab.js.map +1 -0
  10. package/lib/commonjs/components/FloatingPill.js +4 -2
  11. package/lib/commonjs/components/FloatingPill.js.map +1 -1
  12. package/lib/commonjs/components/InfoTab.js +73 -107
  13. package/lib/commonjs/components/InfoTab.js.map +1 -1
  14. package/lib/commonjs/components/JsonTreeView.js +39 -34
  15. package/lib/commonjs/components/JsonTreeView.js.map +1 -1
  16. package/lib/commonjs/components/LogItem.js +33 -29
  17. package/lib/commonjs/components/LogItem.js.map +1 -1
  18. package/lib/commonjs/components/LogsTab.js +37 -42
  19. package/lib/commonjs/components/LogsTab.js.map +1 -1
  20. package/lib/commonjs/components/NetworkItem.js +111 -135
  21. package/lib/commonjs/components/NetworkItem.js.map +1 -1
  22. package/lib/commonjs/components/NetworkTab.js +48 -49
  23. package/lib/commonjs/components/NetworkTab.js.map +1 -1
  24. package/lib/commonjs/components/TabBar.js +8 -5
  25. package/lib/commonjs/components/TabBar.js.map +1 -1
  26. package/lib/commonjs/constants.js +24 -1
  27. package/lib/commonjs/constants.js.map +1 -1
  28. package/lib/commonjs/index.js +19 -0
  29. package/lib/commonjs/index.js.map +1 -1
  30. package/lib/commonjs/types.js +1 -0
  31. package/lib/commonjs/types.js.map +1 -1
  32. package/lib/module/Backstage.js +42 -31
  33. package/lib/module/Backstage.js.map +1 -1
  34. package/lib/module/ThemeContext.js +37 -0
  35. package/lib/module/ThemeContext.js.map +1 -0
  36. package/lib/module/components/BackstagePanel.js +40 -18
  37. package/lib/module/components/BackstagePanel.js.map +1 -1
  38. package/lib/module/components/FlagsTab.js +251 -0
  39. package/lib/module/components/FlagsTab.js.map +1 -0
  40. package/lib/module/components/FloatingPill.js +5 -3
  41. package/lib/module/components/FloatingPill.js.map +1 -1
  42. package/lib/module/components/InfoTab.js +73 -107
  43. package/lib/module/components/InfoTab.js.map +1 -1
  44. package/lib/module/components/JsonTreeView.js +42 -38
  45. package/lib/module/components/JsonTreeView.js.map +1 -1
  46. package/lib/module/components/LogItem.js +35 -31
  47. package/lib/module/components/LogItem.js.map +1 -1
  48. package/lib/module/components/LogsTab.js +38 -43
  49. package/lib/module/components/LogsTab.js.map +1 -1
  50. package/lib/module/components/NetworkItem.js +113 -137
  51. package/lib/module/components/NetworkItem.js.map +1 -1
  52. package/lib/module/components/NetworkTab.js +49 -50
  53. package/lib/module/components/NetworkTab.js.map +1 -1
  54. package/lib/module/components/TabBar.js +10 -7
  55. package/lib/module/components/TabBar.js.map +1 -1
  56. package/lib/module/constants.js +23 -0
  57. package/lib/module/constants.js.map +1 -1
  58. package/lib/module/index.js +1 -0
  59. package/lib/module/index.js.map +1 -1
  60. package/lib/module/types.js +2 -0
  61. package/lib/module/types.js.map +1 -1
  62. package/lib/typescript/Backstage.d.ts.map +1 -1
  63. package/lib/typescript/ThemeContext.d.ts +11 -0
  64. package/lib/typescript/ThemeContext.d.ts.map +1 -0
  65. package/lib/typescript/components/BackstagePanel.d.ts +4 -1
  66. package/lib/typescript/components/BackstagePanel.d.ts.map +1 -1
  67. package/lib/typescript/components/FlagsTab.d.ts +9 -0
  68. package/lib/typescript/components/FlagsTab.d.ts.map +1 -0
  69. package/lib/typescript/components/FloatingPill.d.ts.map +1 -1
  70. package/lib/typescript/components/InfoTab.d.ts +1 -0
  71. package/lib/typescript/components/InfoTab.d.ts.map +1 -1
  72. package/lib/typescript/components/JsonTreeView.d.ts.map +1 -1
  73. package/lib/typescript/components/LogItem.d.ts +1 -0
  74. package/lib/typescript/components/LogItem.d.ts.map +1 -1
  75. package/lib/typescript/components/LogsTab.d.ts +1 -0
  76. package/lib/typescript/components/LogsTab.d.ts.map +1 -1
  77. package/lib/typescript/components/NetworkItem.d.ts +1 -0
  78. package/lib/typescript/components/NetworkItem.d.ts.map +1 -1
  79. package/lib/typescript/components/NetworkTab.d.ts +1 -0
  80. package/lib/typescript/components/NetworkTab.d.ts.map +1 -1
  81. package/lib/typescript/components/TabBar.d.ts.map +1 -1
  82. package/lib/typescript/constants.d.ts +1 -0
  83. package/lib/typescript/constants.d.ts.map +1 -1
  84. package/lib/typescript/index.d.ts +3 -1
  85. package/lib/typescript/index.d.ts.map +1 -1
  86. package/lib/typescript/types.d.ts +18 -0
  87. package/lib/typescript/types.d.ts.map +1 -1
  88. package/package.json +1 -1
  89. package/src/Backstage.tsx +41 -31
  90. package/src/ThemeContext.tsx +38 -0
  91. package/src/components/BackstagePanel.tsx +84 -56
  92. package/src/components/FlagsTab.tsx +198 -0
  93. package/src/components/FloatingPill.tsx +6 -3
  94. package/src/components/InfoTab.tsx +152 -186
  95. package/src/components/JsonTreeView.tsx +53 -73
  96. package/src/components/LogItem.tsx +55 -100
  97. package/src/components/LogsTab.tsx +110 -132
  98. package/src/components/NetworkItem.tsx +306 -417
  99. package/src/components/NetworkTab.tsx +129 -163
  100. package/src/components/TabBar.tsx +51 -47
  101. package/src/constants.ts +23 -0
  102. package/src/index.ts +3 -0
  103. package/src/types.ts +25 -0
@@ -1,7 +1,8 @@
1
1
  import React, { useCallback, useMemo, useState } from 'react'
2
2
  import { FlatList, StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native'
3
- import { DarkTheme, MonospaceFont, TestIDs } from '../constants'
4
- import type { LogEntry, BackstageStyleOverrides } from '../types'
3
+ import { MonospaceFont, TestIDs } from '../constants'
4
+ import { useBackstageTheme } from '../ThemeContext'
5
+ import type { LogEntry, BackstageStyleOverrides, BackstageTheme } from '../types'
5
6
  import { LogItem } from './LogItem'
6
7
  import { formatTimestamp } from '../utils/formatTimestamp'
7
8
 
@@ -11,6 +12,7 @@ interface LogsTabProps {
11
12
  logs: LogEntry[]
12
13
  onRefresh: () => void
13
14
  onCopyLogs?: (logs: string) => void
15
+ jsonMaxDepth?: number
14
16
  styles?: BackstageStyleOverrides
15
17
  }
16
18
 
@@ -20,31 +22,29 @@ export const LogsTab: React.FC<LogsTabProps> = ({
20
22
  logs,
21
23
  onRefresh,
22
24
  onCopyLogs,
25
+ jsonMaxDepth,
23
26
  styles: propStyles,
24
27
  }) => {
28
+ const theme = useBackstageTheme()
29
+ const s = useMemo(() => createStyles(theme), [theme])
25
30
  const [searchText, setSearchText] = useState('')
26
31
 
27
- // Filter logs based on search text
28
32
  const filteredLogs = useMemo(() => {
29
33
  if (!searchText.trim()) return logs
30
-
31
34
  const query = searchText.toLowerCase()
32
35
  return logs.filter(log => {
33
36
  return log.message.toLowerCase().includes(query) || log.level.toLowerCase().includes(query)
34
37
  })
35
38
  }, [logs, searchText])
36
39
 
37
- // Copy all visible logs to text
38
40
  const handleCopyAll = useCallback(() => {
39
41
  if (!onCopyLogs) return
40
-
41
42
  const text = filteredLogs
42
43
  .map(log => `[${log.level.toUpperCase()}] ${formatTimestamp(log.timestamp)} ${log.message}`)
43
44
  .join('\n')
44
45
  onCopyLogs(text)
45
46
  }, [filteredLogs, onCopyLogs])
46
47
 
47
- // Copy individual log
48
48
  const handleCopyItem = useCallback(
49
49
  (text: string) => {
50
50
  if (onCopyLogs) {
@@ -54,10 +54,14 @@ export const LogsTab: React.FC<LogsTabProps> = ({
54
54
  [onCopyLogs],
55
55
  )
56
56
 
57
- // Render log item
58
57
  const renderItem = useCallback(
59
58
  ({ item }: { item: LogEntry }) => (
60
- <LogItem item={item} onCopy={onCopyLogs ? handleCopyItem : undefined} styles={propStyles} />
59
+ <LogItem
60
+ item={item}
61
+ onCopy={onCopyLogs ? handleCopyItem : undefined}
62
+ jsonMaxDepth={jsonMaxDepth}
63
+ styles={propStyles}
64
+ />
61
65
  ),
62
66
  [handleCopyItem, onCopyLogs, propStyles],
63
67
  )
@@ -65,16 +69,15 @@ export const LogsTab: React.FC<LogsTabProps> = ({
65
69
  const keyExtractor = useCallback((item: LogEntry) => item.id, [])
66
70
 
67
71
  return (
68
- <View style={styles.container}>
69
- {/* Search Bar */}
70
- <View style={styles.searchContainer}>
71
- <View style={styles.searchInputWrapper}>
72
- <Text style={styles.searchIcon}>⌕</Text>
72
+ <View style={s.container}>
73
+ <View style={s.searchContainer}>
74
+ <View style={s.searchInputWrapper}>
75
+ <Text style={s.searchIcon}>⌕</Text>
73
76
  <TextInput
74
77
  testID={TestIDs.logsTab.searchInput}
75
- style={styles.searchInput}
78
+ style={s.searchInput}
76
79
  placeholder="Filter logs..."
77
- placeholderTextColor={DarkTheme.textMuted}
80
+ placeholderTextColor={theme.textMuted}
78
81
  value={searchText}
79
82
  onChangeText={setSearchText}
80
83
  autoCapitalize="none"
@@ -86,26 +89,24 @@ export const LogsTab: React.FC<LogsTabProps> = ({
86
89
  {onCopyLogs && (
87
90
  <TouchableOpacity
88
91
  testID={TestIDs.logsTab.copyButton}
89
- style={styles.copyAllButton}
92
+ style={s.copyAllButton}
90
93
  onPress={handleCopyAll}
91
94
  activeOpacity={0.7}
92
95
  >
93
- <Text style={styles.copyAllText}>Copy All</Text>
96
+ <Text style={s.copyAllText}>Copy All</Text>
94
97
  </TouchableOpacity>
95
98
  )}
96
99
  </View>
97
100
 
98
- {/* Log Count */}
99
- <View style={styles.countBar}>
100
- <Text style={styles.countText}>
101
+ <View style={s.countBar}>
102
+ <Text style={s.countText}>
101
103
  {filteredLogs.length === logs.length
102
104
  ? `${logs.length} log${logs.length !== 1 ? 's' : ''}`
103
105
  : `${filteredLogs.length} of ${logs.length} logs`}
104
106
  </Text>
105
- <Text style={styles.pullHint}>↓ pull to refresh</Text>
107
+ <Text style={s.pullHint}>↓ pull to refresh</Text>
106
108
  </View>
107
109
 
108
- {/* Log List */}
109
110
  <FlatList
110
111
  testID={TestIDs.logsTab.list}
111
112
  data={filteredLogs}
@@ -113,16 +114,15 @@ export const LogsTab: React.FC<LogsTabProps> = ({
113
114
  keyExtractor={keyExtractor}
114
115
  refreshing={false}
115
116
  onRefresh={onRefresh}
116
- style={styles.list}
117
- contentContainerStyle={filteredLogs.length === 0 ? styles.emptyContainer : undefined}
117
+ style={s.list}
118
+ contentContainerStyle={filteredLogs.length === 0 ? s.emptyContainer : undefined}
118
119
  ListEmptyComponent={
119
- <View style={styles.emptyState}>
120
- <Text style={styles.emptyIcon}>📋</Text>
121
- <Text style={styles.emptyTitle}>No logs yet</Text>
122
- <Text style={styles.emptySubtitle}>Console output will appear here</Text>
120
+ <View style={s.emptyState}>
121
+ <Text style={s.emptyIcon}>📋</Text>
122
+ <Text style={s.emptyTitle}>No logs yet</Text>
123
+ <Text style={s.emptySubtitle}>Console output will appear here</Text>
123
124
  </View>
124
125
  }
125
- // Perf optimizations
126
126
  maxToRenderPerBatch={20}
127
127
  windowSize={10}
128
128
  initialNumToRender={20}
@@ -135,105 +135,83 @@ export const LogsTab: React.FC<LogsTabProps> = ({
135
135
 
136
136
  // ─── Styles ──────────────────────────────────────────────────────────────────
137
137
 
138
- const styles = StyleSheet.create({
139
- container: {
140
- flex: 1,
141
- },
142
- searchContainer: {
143
- flexDirection: 'row',
144
- alignItems: 'center',
145
- paddingHorizontal: 14,
146
- paddingVertical: 10,
147
- gap: 10,
148
- borderBottomWidth: 1,
149
- borderBottomColor: DarkTheme.border,
150
- },
151
- searchInputWrapper: {
152
- flex: 1,
153
- flexDirection: 'row',
154
- alignItems: 'center',
155
- backgroundColor: DarkTheme.surfaceElevated,
156
- borderRadius: 10,
157
- borderWidth: 1,
158
- borderColor: DarkTheme.border,
159
- paddingHorizontal: 12,
160
- height: 38,
161
- },
162
- searchIcon: {
163
- fontSize: 16,
164
- color: DarkTheme.textMuted,
165
- marginRight: 8,
166
- },
167
- searchInput: {
168
- flex: 1,
169
- fontFamily: MonospaceFont,
170
- fontSize: 13,
171
- color: DarkTheme.text,
172
- padding: 0,
173
- },
174
- copyAllButton: {
175
- backgroundColor: DarkTheme.accentDim,
176
- borderRadius: 8,
177
- borderWidth: 1,
178
- borderColor: DarkTheme.accent,
179
- paddingHorizontal: 14,
180
- height: 38,
181
- justifyContent: 'center',
182
- },
183
- copyAllText: {
184
- fontFamily: MonospaceFont,
185
- fontSize: 12,
186
- fontWeight: '700',
187
- color: DarkTheme.accent,
188
- letterSpacing: 0.5,
189
- },
190
- countBar: {
191
- flexDirection: 'row',
192
- justifyContent: 'space-between',
193
- alignItems: 'center',
194
- paddingHorizontal: 16,
195
- paddingVertical: 6,
196
- backgroundColor: DarkTheme.surface,
197
- },
198
- countText: {
199
- fontFamily: MonospaceFont,
200
- fontSize: 11,
201
- color: DarkTheme.textMuted,
202
- },
203
- pullHint: {
204
- fontFamily: MonospaceFont,
205
- fontSize: 10,
206
- color: DarkTheme.textMuted,
207
- fontStyle: 'italic',
208
- },
209
- list: {
210
- flex: 1,
211
- },
212
- emptyContainer: {
213
- flex: 1,
214
- justifyContent: 'center',
215
- },
216
- emptyState: {
217
- alignItems: 'center',
218
- justifyContent: 'center',
219
- padding: 40,
220
- },
221
- emptyIcon: {
222
- fontSize: 48,
223
- marginBottom: 16,
224
- opacity: 0.5,
225
- },
226
- emptyTitle: {
227
- fontFamily: MonospaceFont,
228
- fontSize: 16,
229
- fontWeight: '700',
230
- color: DarkTheme.textSecondary,
231
- marginBottom: 8,
232
- },
233
- emptySubtitle: {
234
- fontFamily: MonospaceFont,
235
- fontSize: 13,
236
- color: DarkTheme.textMuted,
237
- textAlign: 'center',
238
- },
239
- })
138
+ const createStyles = (t: BackstageTheme) =>
139
+ StyleSheet.create({
140
+ container: { flex: 1 },
141
+ searchContainer: {
142
+ flexDirection: 'row',
143
+ alignItems: 'center',
144
+ paddingHorizontal: 14,
145
+ paddingVertical: 10,
146
+ gap: 10,
147
+ borderBottomWidth: 1,
148
+ borderBottomColor: t.border,
149
+ },
150
+ searchInputWrapper: {
151
+ flex: 1,
152
+ flexDirection: 'row',
153
+ alignItems: 'center',
154
+ backgroundColor: t.surfaceElevated,
155
+ borderRadius: 10,
156
+ borderWidth: 1,
157
+ borderColor: t.border,
158
+ paddingHorizontal: 12,
159
+ height: 38,
160
+ },
161
+ searchIcon: { fontSize: 16, color: t.textMuted, marginRight: 8 },
162
+ searchInput: {
163
+ flex: 1,
164
+ fontFamily: MonospaceFont,
165
+ fontSize: 13,
166
+ color: t.text,
167
+ padding: 0,
168
+ },
169
+ copyAllButton: {
170
+ backgroundColor: t.accentDim,
171
+ borderRadius: 8,
172
+ borderWidth: 1,
173
+ borderColor: t.accent,
174
+ paddingHorizontal: 14,
175
+ height: 38,
176
+ justifyContent: 'center',
177
+ },
178
+ copyAllText: {
179
+ fontFamily: MonospaceFont,
180
+ fontSize: 12,
181
+ fontWeight: '700',
182
+ color: t.accent,
183
+ letterSpacing: 0.5,
184
+ },
185
+ countBar: {
186
+ flexDirection: 'row',
187
+ justifyContent: 'space-between',
188
+ alignItems: 'center',
189
+ paddingHorizontal: 16,
190
+ paddingVertical: 6,
191
+ backgroundColor: t.surface,
192
+ },
193
+ countText: { fontFamily: MonospaceFont, fontSize: 11, color: t.textMuted },
194
+ pullHint: {
195
+ fontFamily: MonospaceFont,
196
+ fontSize: 10,
197
+ color: t.textMuted,
198
+ fontStyle: 'italic',
199
+ },
200
+ list: { flex: 1 },
201
+ emptyContainer: { flex: 1, justifyContent: 'center' },
202
+ emptyState: { alignItems: 'center', justifyContent: 'center', padding: 40 },
203
+ emptyIcon: { fontSize: 48, marginBottom: 16, opacity: 0.5 },
204
+ emptyTitle: {
205
+ fontFamily: MonospaceFont,
206
+ fontSize: 16,
207
+ fontWeight: '700',
208
+ color: t.textSecondary,
209
+ marginBottom: 8,
210
+ },
211
+ emptySubtitle: {
212
+ fontFamily: MonospaceFont,
213
+ fontSize: 13,
214
+ color: t.textMuted,
215
+ textAlign: 'center',
216
+ },
217
+ })