rn-backstage 1.2.0 → 1.3.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 (110) hide show
  1. package/README.md +84 -2
  2. package/lib/commonjs/Backstage.js +46 -33
  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 +35 -12
  7. package/lib/commonjs/components/BackstagePanel.js.map +1 -1
  8. package/lib/commonjs/components/FlagsTab.js +60 -57
  9. package/lib/commonjs/components/FlagsTab.js.map +1 -1
  10. package/lib/commonjs/components/FloatingPill.js +86 -24
  11. package/lib/commonjs/components/FloatingPill.js.map +1 -1
  12. package/lib/commonjs/components/InfoTab.js +77 -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 +39 -29
  17. package/lib/commonjs/components/LogItem.js.map +1 -1
  18. package/lib/commonjs/components/LogsTab.js +39 -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 +50 -49
  23. package/lib/commonjs/components/NetworkTab.js.map +1 -1
  24. package/lib/commonjs/components/StorageTab.js +655 -0
  25. package/lib/commonjs/components/StorageTab.js.map +1 -0
  26. package/lib/commonjs/components/TabBar.js +8 -5
  27. package/lib/commonjs/components/TabBar.js.map +1 -1
  28. package/lib/commonjs/constants.js +96 -7
  29. package/lib/commonjs/constants.js.map +1 -1
  30. package/lib/commonjs/index.js +96 -0
  31. package/lib/commonjs/index.js.map +1 -1
  32. package/lib/commonjs/types.js +1 -0
  33. package/lib/commonjs/types.js.map +1 -1
  34. package/lib/module/Backstage.js +46 -33
  35. package/lib/module/Backstage.js.map +1 -1
  36. package/lib/module/ThemeContext.js +37 -0
  37. package/lib/module/ThemeContext.js.map +1 -0
  38. package/lib/module/components/BackstagePanel.js +37 -14
  39. package/lib/module/components/BackstagePanel.js.map +1 -1
  40. package/lib/module/components/FlagsTab.js +61 -58
  41. package/lib/module/components/FlagsTab.js.map +1 -1
  42. package/lib/module/components/FloatingPill.js +90 -28
  43. package/lib/module/components/FloatingPill.js.map +1 -1
  44. package/lib/module/components/InfoTab.js +77 -107
  45. package/lib/module/components/InfoTab.js.map +1 -1
  46. package/lib/module/components/JsonTreeView.js +42 -38
  47. package/lib/module/components/JsonTreeView.js.map +1 -1
  48. package/lib/module/components/LogItem.js +41 -31
  49. package/lib/module/components/LogItem.js.map +1 -1
  50. package/lib/module/components/LogsTab.js +40 -43
  51. package/lib/module/components/LogsTab.js.map +1 -1
  52. package/lib/module/components/NetworkItem.js +113 -137
  53. package/lib/module/components/NetworkItem.js.map +1 -1
  54. package/lib/module/components/NetworkTab.js +51 -50
  55. package/lib/module/components/NetworkTab.js.map +1 -1
  56. package/lib/module/components/StorageTab.js +650 -0
  57. package/lib/module/components/StorageTab.js.map +1 -0
  58. package/lib/module/components/TabBar.js +10 -7
  59. package/lib/module/components/TabBar.js.map +1 -1
  60. package/lib/module/constants.js +95 -6
  61. package/lib/module/constants.js.map +1 -1
  62. package/lib/module/index.js +14 -0
  63. package/lib/module/index.js.map +1 -1
  64. package/lib/module/types.js +2 -0
  65. package/lib/module/types.js.map +1 -1
  66. package/lib/typescript/Backstage.d.ts.map +1 -1
  67. package/lib/typescript/ThemeContext.d.ts +11 -0
  68. package/lib/typescript/ThemeContext.d.ts.map +1 -0
  69. package/lib/typescript/components/BackstagePanel.d.ts +3 -1
  70. package/lib/typescript/components/BackstagePanel.d.ts.map +1 -1
  71. package/lib/typescript/components/FlagsTab.d.ts.map +1 -1
  72. package/lib/typescript/components/FloatingPill.d.ts +2 -0
  73. package/lib/typescript/components/FloatingPill.d.ts.map +1 -1
  74. package/lib/typescript/components/InfoTab.d.ts +1 -0
  75. package/lib/typescript/components/InfoTab.d.ts.map +1 -1
  76. package/lib/typescript/components/JsonTreeView.d.ts.map +1 -1
  77. package/lib/typescript/components/LogItem.d.ts +1 -0
  78. package/lib/typescript/components/LogItem.d.ts.map +1 -1
  79. package/lib/typescript/components/LogsTab.d.ts +1 -0
  80. package/lib/typescript/components/LogsTab.d.ts.map +1 -1
  81. package/lib/typescript/components/NetworkItem.d.ts +1 -0
  82. package/lib/typescript/components/NetworkItem.d.ts.map +1 -1
  83. package/lib/typescript/components/NetworkTab.d.ts +1 -0
  84. package/lib/typescript/components/NetworkTab.d.ts.map +1 -1
  85. package/lib/typescript/components/StorageTab.d.ts +9 -0
  86. package/lib/typescript/components/StorageTab.d.ts.map +1 -0
  87. package/lib/typescript/components/TabBar.d.ts.map +1 -1
  88. package/lib/typescript/constants.d.ts +60 -4
  89. package/lib/typescript/constants.d.ts.map +1 -1
  90. package/lib/typescript/index.d.ts +14 -1
  91. package/lib/typescript/index.d.ts.map +1 -1
  92. package/lib/typescript/types.d.ts +20 -0
  93. package/lib/typescript/types.d.ts.map +1 -1
  94. package/package.json +6 -4
  95. package/src/Backstage.tsx +45 -33
  96. package/src/ThemeContext.tsx +38 -0
  97. package/src/components/BackstagePanel.tsx +89 -61
  98. package/src/components/FlagsTab.tsx +125 -174
  99. package/src/components/FloatingPill.tsx +127 -30
  100. package/src/components/InfoTab.tsx +153 -186
  101. package/src/components/JsonTreeView.tsx +53 -73
  102. package/src/components/LogItem.tsx +64 -100
  103. package/src/components/LogsTab.tsx +110 -132
  104. package/src/components/NetworkItem.tsx +306 -417
  105. package/src/components/NetworkTab.tsx +129 -163
  106. package/src/components/StorageTab.tsx +607 -0
  107. package/src/components/TabBar.tsx +51 -47
  108. package/src/constants.ts +103 -4
  109. package/src/index.ts +17 -0
  110. package/src/types.ts +28 -0
@@ -0,0 +1,655 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.StorageTab = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _reactNative = require("react-native");
9
+ var _constants = require("../constants");
10
+ var _ThemeContext = require("../ThemeContext");
11
+ var _JsonTreeView = require("./JsonTreeView");
12
+ var _jsxRuntime = require("react/jsx-runtime");
13
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
14
+ // ─── Types ───────────────────────────────────────────────────────────────────
15
+
16
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
17
+
18
+ function tryParseJSON(text) {
19
+ try {
20
+ const parsed = JSON.parse(text);
21
+ return typeof parsed === 'object' && parsed !== null ? parsed : null;
22
+ } catch {
23
+ return null;
24
+ }
25
+ }
26
+ function truncateValue(value, max = 80) {
27
+ if (value.length <= max) return value;
28
+ return value.substring(0, max) + '…';
29
+ }
30
+
31
+ // ─── Component ───────────────────────────────────────────────────────────────
32
+
33
+ const StorageTab = ({
34
+ adapter,
35
+ jsonMaxDepth
36
+ }) => {
37
+ const theme = (0, _ThemeContext.useBackstageTheme)();
38
+ const s = (0, _react.useMemo)(() => createStyles(theme), [theme]);
39
+ const [entries, setEntries] = (0, _react.useState)([]);
40
+ const [loading, setLoading] = (0, _react.useState)(true);
41
+ const [searchText, setSearchText] = (0, _react.useState)('');
42
+
43
+ // Edit state
44
+ const [editingKey, setEditingKey] = (0, _react.useState)(null);
45
+ const [editValue, setEditValue] = (0, _react.useState)('');
46
+
47
+ // Add new entry state
48
+ const [showAddForm, setShowAddForm] = (0, _react.useState)(false);
49
+ const [newKey, setNewKey] = (0, _react.useState)('');
50
+ const [newValue, setNewValue] = (0, _react.useState)('');
51
+
52
+ // Expanded entries (for JSON preview)
53
+ const [expandedKeys, setExpandedKeys] = (0, _react.useState)(new Set());
54
+
55
+ // ─── Load Entries ────────────────────────────────────────
56
+ const loadEntries = (0, _react.useCallback)(async () => {
57
+ setLoading(true);
58
+ try {
59
+ const keys = await adapter.getAllKeys();
60
+ const sorted = [...keys].sort((a, b) => a.localeCompare(b));
61
+ const results = [];
62
+ for (const key of sorted) {
63
+ const value = await adapter.getItem(key);
64
+ results.push({
65
+ key,
66
+ value: value ?? ''
67
+ });
68
+ }
69
+ setEntries(results);
70
+ } catch (err) {
71
+ console.error('[Backstage] StorageTab load error:', err);
72
+ } finally {
73
+ setLoading(false);
74
+ }
75
+ }, [adapter]);
76
+ (0, _react.useEffect)(() => {
77
+ loadEntries();
78
+ }, [loadEntries]);
79
+
80
+ // ─── Filter ──────────────────────────────────────────────
81
+ const filteredEntries = (0, _react.useMemo)(() => {
82
+ if (!searchText.trim()) return entries;
83
+ const query = searchText.toLowerCase();
84
+ return entries.filter(e => e.key.toLowerCase().includes(query) || e.value.toLowerCase().includes(query));
85
+ }, [entries, searchText]);
86
+
87
+ // ─── Toggle Expand ───────────────────────────────────────
88
+ const toggleExpand = (0, _react.useCallback)(key => {
89
+ setExpandedKeys(prev => {
90
+ const next = new Set(prev);
91
+ if (next.has(key)) {
92
+ next.delete(key);
93
+ } else {
94
+ next.add(key);
95
+ }
96
+ return next;
97
+ });
98
+ }, []);
99
+
100
+ // ─── Edit ────────────────────────────────────────────────
101
+ const startEditing = (0, _react.useCallback)(entry => {
102
+ setEditingKey(entry.key);
103
+ setEditValue(entry.value);
104
+ }, []);
105
+ const cancelEditing = (0, _react.useCallback)(() => {
106
+ setEditingKey(null);
107
+ setEditValue('');
108
+ }, []);
109
+ const saveEdit = (0, _react.useCallback)(async () => {
110
+ if (editingKey === null) return;
111
+ try {
112
+ await adapter.setItem(editingKey, editValue);
113
+ setEntries(prev => prev.map(e => e.key === editingKey ? {
114
+ ...e,
115
+ value: editValue
116
+ } : e));
117
+ setEditingKey(null);
118
+ setEditValue('');
119
+ } catch (err) {
120
+ _reactNative.Alert.alert('Error', `Failed to save: ${err}`);
121
+ }
122
+ }, [adapter, editingKey, editValue]);
123
+
124
+ // ─── Delete ──────────────────────────────────────────────
125
+ const confirmDelete = (0, _react.useCallback)(key => {
126
+ _reactNative.Alert.alert('Delete Entry', `Remove "${key}" from storage?`, [{
127
+ text: 'Cancel',
128
+ style: 'cancel'
129
+ }, {
130
+ text: 'Delete',
131
+ style: 'destructive',
132
+ onPress: async () => {
133
+ try {
134
+ await adapter.removeItem(key);
135
+ setEntries(prev => prev.filter(e => e.key !== key));
136
+ setExpandedKeys(prev => {
137
+ const next = new Set(prev);
138
+ next.delete(key);
139
+ return next;
140
+ });
141
+ } catch (err) {
142
+ _reactNative.Alert.alert('Error', `Failed to delete: ${err}`);
143
+ }
144
+ }
145
+ }]);
146
+ }, [adapter]);
147
+
148
+ // ─── Add New Entry ───────────────────────────────────────
149
+ const handleAddEntry = (0, _react.useCallback)(async () => {
150
+ const trimmedKey = newKey.trim();
151
+ if (!trimmedKey) {
152
+ _reactNative.Alert.alert('Error', 'Key cannot be empty');
153
+ return;
154
+ }
155
+ try {
156
+ await adapter.setItem(trimmedKey, newValue);
157
+ setEntries(prev => {
158
+ const exists = prev.findIndex(e => e.key === trimmedKey);
159
+ if (exists >= 0) {
160
+ const updated = [...prev];
161
+ updated[exists] = {
162
+ key: trimmedKey,
163
+ value: newValue
164
+ };
165
+ return updated;
166
+ }
167
+ return [...prev, {
168
+ key: trimmedKey,
169
+ value: newValue
170
+ }].sort((a, b) => a.key.localeCompare(b.key));
171
+ });
172
+ setNewKey('');
173
+ setNewValue('');
174
+ setShowAddForm(false);
175
+ } catch (err) {
176
+ _reactNative.Alert.alert('Error', `Failed to save: ${err}`);
177
+ }
178
+ }, [adapter, newKey, newValue]);
179
+
180
+ // ─── Render Entry ────────────────────────────────────────
181
+ const renderItem = (0, _react.useCallback)(({
182
+ item
183
+ }) => {
184
+ const isEditing = editingKey === item.key;
185
+ const isExpanded = expandedKeys.has(item.key);
186
+ const jsonValue = tryParseJSON(item.value);
187
+ const isJSON = jsonValue !== null;
188
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
189
+ style: s.entryContainer,
190
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
191
+ style: s.entryHeader,
192
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
193
+ style: s.entryKeyContainer,
194
+ onPress: () => toggleExpand(item.key),
195
+ activeOpacity: 0.7,
196
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
197
+ style: s.entryChevron,
198
+ children: isExpanded ? '▼' : '▶'
199
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
200
+ style: s.entryKey,
201
+ numberOfLines: 1,
202
+ children: item.key
203
+ }), isJSON && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
204
+ style: s.jsonBadge,
205
+ children: "JSON"
206
+ })]
207
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
208
+ style: s.entryActions,
209
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
210
+ onPress: () => startEditing(item),
211
+ hitSlop: {
212
+ top: 8,
213
+ bottom: 8,
214
+ left: 8,
215
+ right: 8
216
+ },
217
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
218
+ style: s.actionIcon,
219
+ children: "\u270E"
220
+ })
221
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
222
+ onPress: () => confirmDelete(item.key),
223
+ hitSlop: {
224
+ top: 8,
225
+ bottom: 8,
226
+ left: 8,
227
+ right: 8
228
+ },
229
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
230
+ style: [s.actionIcon, s.deleteIcon],
231
+ children: "\u2715"
232
+ })
233
+ })]
234
+ })]
235
+ }), isEditing ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
236
+ style: s.editContainer,
237
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
238
+ style: s.editInput,
239
+ value: editValue,
240
+ onChangeText: setEditValue,
241
+ multiline: true,
242
+ autoFocus: true,
243
+ textAlignVertical: "top",
244
+ placeholderTextColor: theme.textMuted,
245
+ placeholder: "Value"
246
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
247
+ style: s.editActions,
248
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
249
+ style: s.cancelButton,
250
+ onPress: cancelEditing,
251
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
252
+ style: s.cancelButtonText,
253
+ children: "Cancel"
254
+ })
255
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
256
+ style: s.saveButton,
257
+ onPress: saveEdit,
258
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
259
+ style: s.saveButtonText,
260
+ children: "Save"
261
+ })
262
+ })]
263
+ })]
264
+ }) : isExpanded ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
265
+ style: s.expandedValue,
266
+ children: isJSON ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
267
+ style: s.jsonContainer,
268
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_JsonTreeView.JsonTreeView, {
269
+ data: jsonValue,
270
+ hideRoot: true,
271
+ maxDepth: jsonMaxDepth
272
+ })
273
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
274
+ style: s.valueText,
275
+ selectable: true,
276
+ children: item.value || '(empty)'
277
+ })
278
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
279
+ onPress: () => toggleExpand(item.key),
280
+ activeOpacity: 0.7,
281
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
282
+ style: s.valuePreview,
283
+ numberOfLines: 1,
284
+ children: truncateValue(item.value) || '(empty)'
285
+ })
286
+ })]
287
+ });
288
+ }, [editingKey, editValue, expandedKeys, jsonMaxDepth, s, theme.textMuted, toggleExpand, startEditing, cancelEditing, saveEdit, confirmDelete]);
289
+ const keyExtractor = (0, _react.useCallback)(item => item.key, []);
290
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
291
+ style: s.container,
292
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
293
+ style: s.searchContainer,
294
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
295
+ style: s.searchInputWrapper,
296
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
297
+ style: s.searchIcon,
298
+ children: "\u2315"
299
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
300
+ style: s.searchInput,
301
+ placeholder: "Filter by key or value...",
302
+ placeholderTextColor: theme.textMuted,
303
+ value: searchText,
304
+ onChangeText: setSearchText,
305
+ autoCapitalize: "none",
306
+ autoCorrect: false,
307
+ clearButtonMode: "while-editing",
308
+ returnKeyType: "search"
309
+ })]
310
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
311
+ style: s.addButton,
312
+ onPress: () => setShowAddForm(prev => !prev),
313
+ activeOpacity: 0.7,
314
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
315
+ style: s.addButtonText,
316
+ children: showAddForm ? '✕' : '+'
317
+ })
318
+ })]
319
+ }), showAddForm && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
320
+ style: s.addForm,
321
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
322
+ style: s.addInput,
323
+ placeholder: "Key",
324
+ placeholderTextColor: theme.textMuted,
325
+ value: newKey,
326
+ onChangeText: setNewKey,
327
+ autoCapitalize: "none",
328
+ autoCorrect: false
329
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
330
+ style: [s.addInput, s.addValueInput],
331
+ placeholder: "Value",
332
+ placeholderTextColor: theme.textMuted,
333
+ value: newValue,
334
+ onChangeText: setNewValue,
335
+ multiline: true,
336
+ textAlignVertical: "top"
337
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
338
+ style: s.addSubmitButton,
339
+ onPress: handleAddEntry,
340
+ activeOpacity: 0.7,
341
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
342
+ style: s.addSubmitText,
343
+ children: "Add Entry"
344
+ })
345
+ })]
346
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
347
+ style: s.statsBar,
348
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
349
+ style: s.statText,
350
+ children: filteredEntries.length === entries.length ? `${entries.length} entr${entries.length !== 1 ? 'ies' : 'y'}` : `${filteredEntries.length} of ${entries.length}`
351
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
352
+ style: s.pullHint,
353
+ children: "\u2193 pull to refresh"
354
+ })]
355
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.FlatList, {
356
+ data: filteredEntries,
357
+ renderItem: renderItem,
358
+ keyExtractor: keyExtractor,
359
+ refreshing: loading,
360
+ onRefresh: loadEntries,
361
+ style: s.list,
362
+ contentContainerStyle: filteredEntries.length === 0 ? s.emptyContainer : undefined,
363
+ ListEmptyComponent: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
364
+ style: s.emptyState,
365
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
366
+ style: s.emptyIcon,
367
+ children: "\uD83D\uDDC4"
368
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
369
+ style: s.emptyTitle,
370
+ children: loading ? 'Loading…' : 'No entries'
371
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
372
+ style: s.emptySubtitle,
373
+ children: loading ? 'Reading storage keys' : 'Storage is empty or no entries match'
374
+ })]
375
+ }),
376
+ maxToRenderPerBatch: 20,
377
+ windowSize: 10,
378
+ initialNumToRender: 20,
379
+ removeClippedSubviews: true
380
+ })]
381
+ });
382
+ };
383
+
384
+ // ─── Styles ──────────────────────────────────────────────────────────────────
385
+ exports.StorageTab = StorageTab;
386
+ const createStyles = t => _reactNative.StyleSheet.create({
387
+ container: {
388
+ flex: 1
389
+ },
390
+ // ── Search ─────────────────────
391
+ searchContainer: {
392
+ flexDirection: 'row',
393
+ alignItems: 'center',
394
+ paddingHorizontal: 14,
395
+ paddingVertical: 10,
396
+ gap: 10,
397
+ borderBottomWidth: 1,
398
+ borderBottomColor: t.border
399
+ },
400
+ searchInputWrapper: {
401
+ flex: 1,
402
+ flexDirection: 'row',
403
+ alignItems: 'center',
404
+ backgroundColor: t.surfaceElevated,
405
+ borderRadius: 10,
406
+ borderWidth: 1,
407
+ borderColor: t.border,
408
+ paddingHorizontal: 12,
409
+ height: 38
410
+ },
411
+ searchIcon: {
412
+ fontSize: 16,
413
+ color: t.textMuted,
414
+ marginRight: 8
415
+ },
416
+ searchInput: {
417
+ flex: 1,
418
+ fontFamily: _constants.MonospaceFont,
419
+ fontSize: 13,
420
+ color: t.text,
421
+ padding: 0
422
+ },
423
+ addButton: {
424
+ width: 38,
425
+ height: 38,
426
+ borderRadius: 10,
427
+ backgroundColor: t.accentDim,
428
+ borderWidth: 1,
429
+ borderColor: t.accent,
430
+ alignItems: 'center',
431
+ justifyContent: 'center'
432
+ },
433
+ addButtonText: {
434
+ fontSize: 18,
435
+ color: t.accent,
436
+ fontWeight: '700'
437
+ },
438
+ // ── Add Form ───────────────────
439
+ addForm: {
440
+ padding: 14,
441
+ borderBottomWidth: 1,
442
+ borderBottomColor: t.border,
443
+ backgroundColor: t.surface,
444
+ gap: 8
445
+ },
446
+ addInput: {
447
+ fontFamily: _constants.MonospaceFont,
448
+ fontSize: 13,
449
+ color: t.text,
450
+ backgroundColor: t.surfaceElevated,
451
+ borderRadius: 8,
452
+ borderWidth: 1,
453
+ borderColor: t.border,
454
+ paddingHorizontal: 12,
455
+ paddingVertical: 8
456
+ },
457
+ addValueInput: {
458
+ minHeight: 60
459
+ },
460
+ addSubmitButton: {
461
+ backgroundColor: t.accent,
462
+ borderRadius: 8,
463
+ paddingVertical: 10,
464
+ alignItems: 'center'
465
+ },
466
+ addSubmitText: {
467
+ fontFamily: _constants.MonospaceFont,
468
+ fontSize: 13,
469
+ fontWeight: '700',
470
+ color: '#FFFFFF'
471
+ },
472
+ // ── Stats ──────────────────────
473
+ statsBar: {
474
+ flexDirection: 'row',
475
+ justifyContent: 'space-between',
476
+ alignItems: 'center',
477
+ paddingHorizontal: 16,
478
+ paddingVertical: 6,
479
+ backgroundColor: t.surface
480
+ },
481
+ statText: {
482
+ fontFamily: _constants.MonospaceFont,
483
+ fontSize: 11,
484
+ color: t.textMuted
485
+ },
486
+ pullHint: {
487
+ fontFamily: _constants.MonospaceFont,
488
+ fontSize: 10,
489
+ color: t.textMuted,
490
+ fontStyle: 'italic'
491
+ },
492
+ // ── List ───────────────────────
493
+ list: {
494
+ flex: 1
495
+ },
496
+ emptyContainer: {
497
+ flex: 1,
498
+ justifyContent: 'center'
499
+ },
500
+ emptyState: {
501
+ alignItems: 'center',
502
+ justifyContent: 'center',
503
+ padding: 40
504
+ },
505
+ emptyIcon: {
506
+ fontSize: 48,
507
+ marginBottom: 16,
508
+ opacity: 0.5
509
+ },
510
+ emptyTitle: {
511
+ fontFamily: _constants.MonospaceFont,
512
+ fontSize: 16,
513
+ fontWeight: '700',
514
+ color: t.textSecondary,
515
+ marginBottom: 8
516
+ },
517
+ emptySubtitle: {
518
+ fontFamily: _constants.MonospaceFont,
519
+ fontSize: 13,
520
+ color: t.textMuted,
521
+ textAlign: 'center'
522
+ },
523
+ // ── Entry ──────────────────────
524
+ entryContainer: {
525
+ paddingHorizontal: 14,
526
+ paddingVertical: 10,
527
+ borderBottomWidth: 1,
528
+ borderBottomColor: t.border
529
+ },
530
+ entryHeader: {
531
+ flexDirection: 'row',
532
+ alignItems: 'center',
533
+ justifyContent: 'space-between',
534
+ marginBottom: 4
535
+ },
536
+ entryKeyContainer: {
537
+ flex: 1,
538
+ flexDirection: 'row',
539
+ alignItems: 'center'
540
+ },
541
+ entryChevron: {
542
+ fontFamily: _constants.MonospaceFont,
543
+ fontSize: 10,
544
+ color: t.textMuted,
545
+ marginRight: 6,
546
+ width: 12
547
+ },
548
+ entryKey: {
549
+ fontFamily: _constants.MonospaceFont,
550
+ fontSize: 13,
551
+ fontWeight: '700',
552
+ color: t.text,
553
+ flex: 1
554
+ },
555
+ jsonBadge: {
556
+ fontFamily: _constants.MonospaceFont,
557
+ fontSize: 9,
558
+ fontWeight: '800',
559
+ color: t.info,
560
+ backgroundColor: t.infoDim,
561
+ borderRadius: 3,
562
+ paddingHorizontal: 5,
563
+ paddingVertical: 1,
564
+ marginLeft: 6,
565
+ overflow: 'hidden'
566
+ },
567
+ entryActions: {
568
+ flexDirection: 'row',
569
+ alignItems: 'center',
570
+ gap: 12,
571
+ marginLeft: 8
572
+ },
573
+ actionIcon: {
574
+ fontSize: 16,
575
+ color: t.textMuted
576
+ },
577
+ deleteIcon: {
578
+ color: t.error
579
+ },
580
+ // ── Value Preview ──────────────
581
+ valuePreview: {
582
+ fontFamily: _constants.MonospaceFont,
583
+ fontSize: 12,
584
+ color: t.textSecondary,
585
+ paddingLeft: 18,
586
+ lineHeight: 18
587
+ },
588
+ expandedValue: {
589
+ marginTop: 4,
590
+ paddingLeft: 18
591
+ },
592
+ valueText: {
593
+ fontFamily: _constants.MonospaceFont,
594
+ fontSize: 12,
595
+ color: t.text,
596
+ lineHeight: 18
597
+ },
598
+ jsonContainer: {
599
+ backgroundColor: t.surfaceElevated,
600
+ borderRadius: 8,
601
+ borderWidth: 1,
602
+ borderColor: t.border,
603
+ padding: 8
604
+ },
605
+ // ── Edit ───────────────────────
606
+ editContainer: {
607
+ marginTop: 6,
608
+ paddingLeft: 18,
609
+ gap: 8
610
+ },
611
+ editInput: {
612
+ fontFamily: _constants.MonospaceFont,
613
+ fontSize: 12,
614
+ color: t.text,
615
+ backgroundColor: t.surfaceElevated,
616
+ borderRadius: 8,
617
+ borderWidth: 1,
618
+ borderColor: t.accent,
619
+ paddingHorizontal: 10,
620
+ paddingVertical: 8,
621
+ minHeight: 60,
622
+ lineHeight: 18
623
+ },
624
+ editActions: {
625
+ flexDirection: 'row',
626
+ gap: 8,
627
+ justifyContent: 'flex-end'
628
+ },
629
+ cancelButton: {
630
+ borderRadius: 6,
631
+ borderWidth: 1,
632
+ borderColor: t.border,
633
+ paddingHorizontal: 14,
634
+ paddingVertical: 6
635
+ },
636
+ cancelButtonText: {
637
+ fontFamily: _constants.MonospaceFont,
638
+ fontSize: 12,
639
+ fontWeight: '600',
640
+ color: t.textSecondary
641
+ },
642
+ saveButton: {
643
+ borderRadius: 6,
644
+ backgroundColor: t.accent,
645
+ paddingHorizontal: 14,
646
+ paddingVertical: 6
647
+ },
648
+ saveButtonText: {
649
+ fontFamily: _constants.MonospaceFont,
650
+ fontSize: 12,
651
+ fontWeight: '700',
652
+ color: '#FFFFFF'
653
+ }
654
+ });
655
+ //# sourceMappingURL=StorageTab.js.map