react-native-storage-inspector 1.0.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.
package/dist/index.mjs ADDED
@@ -0,0 +1,1223 @@
1
+ import React6, { useState, useMemo, useEffect, useCallback } from 'react';
2
+ import { StyleSheet, Dimensions, View, ScrollView, RefreshControl, Text, TouchableOpacity, Share, Modal, TextInput } from 'react-native';
3
+
4
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
5
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
6
+ }) : x)(function(x) {
7
+ if (typeof require !== "undefined") return require.apply(this, arguments);
8
+ throw Error('Dynamic require of "' + x + '" is not supported');
9
+ });
10
+
11
+ // src/adapters/mmkv.ts
12
+ function createMMKVAdapter(instance, name) {
13
+ return {
14
+ type: "mmkv",
15
+ name: name ?? "MMKV",
16
+ getAllKeys() {
17
+ return Promise.resolve(instance.getAllKeys());
18
+ },
19
+ getItem(key) {
20
+ const value = instance.getString(key);
21
+ return Promise.resolve(value ?? null);
22
+ },
23
+ setItem(key, value) {
24
+ instance.set(key, value);
25
+ return Promise.resolve();
26
+ },
27
+ removeItem(key) {
28
+ instance.delete(key);
29
+ return Promise.resolve();
30
+ },
31
+ isAvailable() {
32
+ return true;
33
+ }
34
+ };
35
+ }
36
+
37
+ // src/adapters/async-storage.ts
38
+ var asyncStorage = null;
39
+ function getAsyncStorage() {
40
+ if (asyncStorage) return asyncStorage;
41
+ try {
42
+ asyncStorage = __require("@react-native-async-storage/async-storage").default;
43
+ return asyncStorage;
44
+ } catch {
45
+ return null;
46
+ }
47
+ }
48
+ function createAsyncStorageAdapter() {
49
+ return {
50
+ type: "async-storage",
51
+ name: "Async Storage",
52
+ async getAllKeys() {
53
+ const storage = getAsyncStorage();
54
+ if (!storage) return [];
55
+ return storage.getAllKeys();
56
+ },
57
+ async getItem(key) {
58
+ const storage = getAsyncStorage();
59
+ if (!storage) return null;
60
+ return storage.getItem(key);
61
+ },
62
+ async setItem(key, value) {
63
+ const storage = getAsyncStorage();
64
+ if (!storage) throw new Error("AsyncStorage is not available");
65
+ await storage.setItem(key, value);
66
+ },
67
+ async removeItem(key) {
68
+ const storage = getAsyncStorage();
69
+ if (!storage) throw new Error("AsyncStorage is not available");
70
+ await storage.removeItem(key);
71
+ },
72
+ isAvailable() {
73
+ return getAsyncStorage() !== null;
74
+ }
75
+ };
76
+ }
77
+
78
+ // src/adapters/keychain.ts
79
+ var keychain = null;
80
+ function getKeychain() {
81
+ if (keychain) return keychain;
82
+ try {
83
+ keychain = __require("react-native-keychain");
84
+ return keychain;
85
+ } catch {
86
+ return null;
87
+ }
88
+ }
89
+ function createKeychainAdapter(knownKeys = []) {
90
+ return {
91
+ type: "keychain",
92
+ name: "Keychain",
93
+ async getAllKeys() {
94
+ const kc = getKeychain();
95
+ if (!kc) return [...knownKeys];
96
+ const genericServices = [];
97
+ if (typeof kc.getAllGenericPasswordServices === "function") {
98
+ try {
99
+ const services = await kc.getAllGenericPasswordServices();
100
+ if (Array.isArray(services)) genericServices.push(...services);
101
+ } catch {
102
+ }
103
+ }
104
+ const merged = /* @__PURE__ */ new Set([...genericServices, ...knownKeys]);
105
+ return Array.from(merged);
106
+ },
107
+ async getItem(key) {
108
+ const kc = getKeychain();
109
+ if (!kc) return null;
110
+ if (typeof kc.getGenericPassword === "function") {
111
+ try {
112
+ const creds2 = await kc.getGenericPassword({ service: key });
113
+ if (creds2 && typeof creds2 === "object" && "password" in creds2) {
114
+ return creds2.password;
115
+ }
116
+ } catch {
117
+ }
118
+ }
119
+ const creds = await kc.getInternetCredentials(key);
120
+ return creds?.password ?? null;
121
+ },
122
+ async setItem(key, value) {
123
+ const kc = getKeychain();
124
+ if (!kc) throw new Error("react-native-keychain is not available");
125
+ if (typeof kc.setGenericPassword === "function") {
126
+ const result2 = await kc.setGenericPassword(key, value, { service: key });
127
+ if (result2 === false) throw new Error("Keychain set failed");
128
+ return;
129
+ }
130
+ const result = await kc.setInternetCredentials(key, key, value);
131
+ if (result === false) throw new Error("Keychain set failed");
132
+ },
133
+ async removeItem(key) {
134
+ const kc = getKeychain();
135
+ if (!kc) throw new Error("react-native-keychain is not available");
136
+ if (typeof kc.resetGenericPassword === "function") {
137
+ await kc.resetGenericPassword({ service: key });
138
+ }
139
+ await kc.resetInternetCredentials(key);
140
+ },
141
+ isAvailable() {
142
+ return getKeychain() !== null;
143
+ }
144
+ };
145
+ }
146
+
147
+ // src/adapters/secure-store.ts
148
+ var secureStore = null;
149
+ function getSecureStore() {
150
+ if (secureStore) return secureStore;
151
+ try {
152
+ secureStore = __require("expo-secure-store");
153
+ return secureStore;
154
+ } catch {
155
+ return null;
156
+ }
157
+ }
158
+ function createSecureStoreAdapter(knownKeys = []) {
159
+ return {
160
+ type: "expo-secure-store",
161
+ name: "Secure Store",
162
+ async getAllKeys() {
163
+ return [...knownKeys];
164
+ },
165
+ async getItem(key) {
166
+ const store = getSecureStore();
167
+ if (!store) return null;
168
+ return store.getItemAsync(key);
169
+ },
170
+ async setItem(key, value) {
171
+ const store = getSecureStore();
172
+ if (!store) throw new Error("expo-secure-store is not available");
173
+ await store.setItemAsync(key, value);
174
+ },
175
+ async removeItem(key) {
176
+ const store = getSecureStore();
177
+ if (!store) throw new Error("expo-secure-store is not available");
178
+ await store.deleteItemAsync(key);
179
+ },
180
+ isAvailable() {
181
+ return getSecureStore() !== null;
182
+ }
183
+ };
184
+ }
185
+ function useStorageItems(adapter) {
186
+ const [items, setItems] = useState([]);
187
+ const [loading, setLoading] = useState(true);
188
+ const [error, setError] = useState(null);
189
+ const refresh = useCallback(async () => {
190
+ if (!adapter || !adapter.isAvailable()) {
191
+ setItems([]);
192
+ setLoading(false);
193
+ return;
194
+ }
195
+ setLoading(true);
196
+ setError(null);
197
+ try {
198
+ const keys = await adapter.getAllKeys();
199
+ const pairs = [];
200
+ for (const key of keys) {
201
+ const value = await adapter.getItem(key);
202
+ pairs.push({ key, value: value ?? "" });
203
+ }
204
+ setItems(pairs);
205
+ } catch (e) {
206
+ setError(e instanceof Error ? e.message : "Failed to load items");
207
+ setItems([]);
208
+ } finally {
209
+ setLoading(false);
210
+ }
211
+ }, [adapter]);
212
+ useEffect(() => {
213
+ refresh();
214
+ }, [refresh]);
215
+ return { items, loading, error, refresh };
216
+ }
217
+
218
+ // src/theme.ts
219
+ var theme = {
220
+ colors: {
221
+ background: "#ffffff",
222
+ backgroundSecondary: "#f5f5f5",
223
+ backgroundTertiary: "#eeeeee",
224
+ border: "#e0e0e0",
225
+ borderLight: "#ebebeb",
226
+ text: "#000000",
227
+ textSecondary: "#666666",
228
+ textMuted: "#999999",
229
+ inverted: "#ffffff"
230
+ }
231
+ };
232
+
233
+ // src/components/Icon.tsx
234
+ var GLYPHS = {
235
+ chevronBack: "\u2039",
236
+ refresh: "\u21BB",
237
+ plus: "+",
238
+ chevronDown: "\u203A",
239
+ chevronUp: "\u203A",
240
+ chevronRight: "\u203A",
241
+ close: "\xD7",
242
+ copy: "\u2398",
243
+ edit: "\u270E",
244
+ trash: "\u232B"
245
+ };
246
+ var ROTATION = {
247
+ chevronDown: "90deg",
248
+ chevronUp: "-90deg"
249
+ };
250
+ function Icon({
251
+ name,
252
+ size = 20,
253
+ tintColor = theme.colors.text,
254
+ iconStyle
255
+ }) {
256
+ const glyph = GLYPHS[name] ?? "?";
257
+ const rotation = ROTATION[name];
258
+ return /* @__PURE__ */ React6.createElement(
259
+ Text,
260
+ {
261
+ style: [
262
+ styles.icon,
263
+ { fontSize: size, color: tintColor, lineHeight: size },
264
+ ...rotation ? [{ transform: [{ rotate: rotation }] }] : [],
265
+ iconStyle
266
+ ]
267
+ },
268
+ glyph
269
+ );
270
+ }
271
+ var styles = StyleSheet.create({
272
+ icon: {
273
+ alignSelf: "center",
274
+ fontWeight: "300"
275
+ }
276
+ });
277
+ var { width: SCREEN_WIDTH } = Dimensions.get("window");
278
+ var LAYOUT = {
279
+ padding: 16,
280
+ fontSize: 14,
281
+ headerHeight: 52,
282
+ rowMinHeight: 48,
283
+ sectionHeaderHeight: 48,
284
+ iconSize: 20,
285
+ chevronSize: 24,
286
+ iconGap: 2,
287
+ iconButtonSize: 36,
288
+ hitSlop: { top: 8, bottom: 8, left: 8, right: 8 },
289
+ hitSlopLarge: { top: 10, bottom: 10, left: 10, right: 10 },
290
+ fabSize: 52,
291
+ modalRadius: 16,
292
+ sectionRadius: 4,
293
+ screenWidth: SCREEN_WIDTH
294
+ };
295
+ var { colors } = theme;
296
+ var styles2 = StyleSheet.create({
297
+ container: {
298
+ flex: 1,
299
+ width: "100%",
300
+ backgroundColor: colors.background
301
+ },
302
+ content: {
303
+ flex: 1
304
+ },
305
+ scroll: {
306
+ flex: 1
307
+ },
308
+ header: {
309
+ height: LAYOUT.headerHeight,
310
+ flexDirection: "row",
311
+ alignItems: "center",
312
+ justifyContent: "space-between",
313
+ paddingHorizontal: LAYOUT.padding,
314
+ borderBottomWidth: StyleSheet.hairlineWidth,
315
+ borderBottomColor: colors.border,
316
+ backgroundColor: colors.background
317
+ },
318
+ headerLeft: {
319
+ minWidth: 44,
320
+ alignItems: "flex-start"
321
+ },
322
+ headerCenter: {
323
+ flex: 1,
324
+ alignItems: "center",
325
+ justifyContent: "center"
326
+ },
327
+ headerRight: {
328
+ minWidth: 44,
329
+ alignItems: "flex-end"
330
+ },
331
+ sectionHeaderLabelWrap: {
332
+ flex: 1
333
+ },
334
+ headerTitle: {
335
+ fontSize: 17,
336
+ fontWeight: "600",
337
+ color: colors.text
338
+ },
339
+ headerButton: {
340
+ width: 44,
341
+ height: 44,
342
+ alignItems: "center",
343
+ justifyContent: "center"
344
+ },
345
+ scrollContent: {
346
+ flexGrow: 1,
347
+ paddingBottom: LAYOUT.fabSize + LAYOUT.padding + 20,
348
+ paddingTop: LAYOUT.padding
349
+ },
350
+ sectionHeader: {
351
+ height: LAYOUT.sectionHeaderHeight,
352
+ flexDirection: "row",
353
+ alignItems: "center",
354
+ paddingHorizontal: LAYOUT.padding,
355
+ borderBottomWidth: StyleSheet.hairlineWidth,
356
+ borderBottomColor: colors.border,
357
+ backgroundColor: colors.backgroundSecondary,
358
+ marginTop: LAYOUT.padding,
359
+ marginHorizontal: LAYOUT.padding,
360
+ borderRadius: LAYOUT.sectionRadius
361
+ },
362
+ sectionHeaderLabel: {
363
+ fontSize: 15,
364
+ fontWeight: "600",
365
+ color: colors.text
366
+ },
367
+ sectionHeaderCount: {
368
+ color: colors.textSecondary,
369
+ fontWeight: "400"
370
+ },
371
+ storageRowActions: {
372
+ flexDirection: "row",
373
+ alignItems: "center",
374
+ gap: LAYOUT.iconGap
375
+ },
376
+ iconButton: {
377
+ width: LAYOUT.iconButtonSize,
378
+ height: LAYOUT.iconButtonSize,
379
+ alignItems: "center",
380
+ justifyContent: "center"
381
+ },
382
+ iconSlot: {
383
+ width: LAYOUT.iconButtonSize,
384
+ height: LAYOUT.iconButtonSize,
385
+ alignItems: "center",
386
+ justifyContent: "center"
387
+ },
388
+ itemRow: {
389
+ minHeight: LAYOUT.rowMinHeight,
390
+ paddingHorizontal: LAYOUT.padding,
391
+ paddingVertical: 12,
392
+ borderBottomWidth: StyleSheet.hairlineWidth,
393
+ borderBottomColor: colors.borderLight,
394
+ backgroundColor: colors.background,
395
+ marginHorizontal: LAYOUT.padding,
396
+ marginBottom: 4
397
+ },
398
+ itemRowCollapsed: {
399
+ flexDirection: "row",
400
+ alignItems: "center",
401
+ alignSelf: "stretch"
402
+ },
403
+ itemKey: {
404
+ flex: 1,
405
+ fontSize: LAYOUT.fontSize,
406
+ fontWeight: "500",
407
+ color: colors.text
408
+ },
409
+ itemChars: {
410
+ fontSize: 12,
411
+ color: colors.textSecondary,
412
+ marginTop: 2
413
+ },
414
+ itemRowActions: {
415
+ flexDirection: "row",
416
+ alignItems: "center",
417
+ marginLeft: LAYOUT.iconGap,
418
+ gap: LAYOUT.iconGap
419
+ },
420
+ itemRowExpanded: {
421
+ paddingTop: 4
422
+ },
423
+ valueBox: {
424
+ backgroundColor: colors.backgroundSecondary,
425
+ borderRadius: 8,
426
+ padding: 12,
427
+ marginTop: 8,
428
+ marginBottom: 8,
429
+ borderWidth: StyleSheet.hairlineWidth,
430
+ borderColor: colors.border
431
+ },
432
+ valueBoxLabel: {
433
+ fontSize: 11,
434
+ fontWeight: "600",
435
+ color: colors.textSecondary,
436
+ marginBottom: 4,
437
+ textTransform: "uppercase"
438
+ },
439
+ valueBoxText: {
440
+ fontSize: LAYOUT.fontSize,
441
+ color: colors.text
442
+ },
443
+ empty: {
444
+ padding: LAYOUT.padding * 2,
445
+ alignItems: "center",
446
+ marginHorizontal: LAYOUT.padding
447
+ },
448
+ emptyText: {
449
+ fontSize: LAYOUT.fontSize,
450
+ color: colors.textMuted
451
+ },
452
+ loading: {
453
+ padding: LAYOUT.padding * 2,
454
+ alignItems: "center",
455
+ marginHorizontal: LAYOUT.padding
456
+ },
457
+ loadingText: {
458
+ fontSize: LAYOUT.fontSize,
459
+ color: colors.textSecondary
460
+ },
461
+ error: {
462
+ padding: LAYOUT.padding,
463
+ backgroundColor: colors.backgroundTertiary,
464
+ marginHorizontal: LAYOUT.padding,
465
+ marginVertical: 8,
466
+ borderRadius: 8
467
+ },
468
+ errorText: {
469
+ fontSize: LAYOUT.fontSize,
470
+ color: colors.text
471
+ },
472
+ keychainHint: {
473
+ padding: LAYOUT.padding,
474
+ marginHorizontal: LAYOUT.padding,
475
+ marginTop: 8,
476
+ marginBottom: 4,
477
+ backgroundColor: colors.backgroundSecondary,
478
+ borderRadius: 8
479
+ },
480
+ keychainHintText: {
481
+ fontSize: LAYOUT.fontSize - 1,
482
+ color: colors.textSecondary
483
+ },
484
+ list: {
485
+ flex: 1
486
+ },
487
+ listContent: {
488
+ flexGrow: 1,
489
+ paddingBottom: LAYOUT.fabSize + LAYOUT.padding + 20
490
+ },
491
+ row: {
492
+ flexDirection: "row",
493
+ alignItems: "center",
494
+ minHeight: LAYOUT.rowMinHeight,
495
+ paddingHorizontal: LAYOUT.padding,
496
+ paddingVertical: 12,
497
+ borderBottomWidth: StyleSheet.hairlineWidth,
498
+ borderBottomColor: colors.borderLight,
499
+ backgroundColor: colors.background,
500
+ marginHorizontal: LAYOUT.padding
501
+ },
502
+ rowKey: {
503
+ flex: 1,
504
+ fontSize: LAYOUT.fontSize,
505
+ fontWeight: "500",
506
+ color: colors.text
507
+ },
508
+ rowValue: {
509
+ fontSize: LAYOUT.fontSize - 1,
510
+ color: colors.textSecondary
511
+ },
512
+ rowActions: {
513
+ flexDirection: "row",
514
+ alignItems: "center",
515
+ marginLeft: LAYOUT.iconGap,
516
+ gap: LAYOUT.iconGap
517
+ },
518
+ rowButton: {
519
+ paddingVertical: 8,
520
+ paddingHorizontal: 12
521
+ },
522
+ rowButtonText: {
523
+ fontSize: 14,
524
+ fontWeight: "600",
525
+ color: colors.text
526
+ },
527
+ rowButtonDanger: {
528
+ color: colors.text
529
+ },
530
+ addButton: {
531
+ position: "absolute",
532
+ bottom: LAYOUT.padding + 16,
533
+ right: LAYOUT.padding + 16,
534
+ width: LAYOUT.fabSize,
535
+ height: LAYOUT.fabSize,
536
+ borderRadius: LAYOUT.fabSize / 2,
537
+ backgroundColor: colors.text,
538
+ alignItems: "center",
539
+ justifyContent: "center"
540
+ },
541
+ addButtonText: {
542
+ fontSize: 16,
543
+ fontWeight: "600",
544
+ color: colors.inverted
545
+ },
546
+ fab: {
547
+ position: "absolute",
548
+ bottom: LAYOUT.padding + 16,
549
+ right: LAYOUT.padding + 16,
550
+ width: LAYOUT.fabSize,
551
+ height: LAYOUT.fabSize,
552
+ borderRadius: LAYOUT.fabSize / 2,
553
+ backgroundColor: colors.text,
554
+ alignItems: "center",
555
+ justifyContent: "center"
556
+ },
557
+ formOverlay: {
558
+ flex: 1,
559
+ backgroundColor: "rgba(0,0,0,0.5)",
560
+ justifyContent: "flex-end",
561
+ alignItems: "center"
562
+ },
563
+ formModal: {
564
+ width: "100%",
565
+ maxWidth: LAYOUT.screenWidth,
566
+ backgroundColor: colors.background,
567
+ borderTopLeftRadius: LAYOUT.modalRadius,
568
+ borderTopRightRadius: LAYOUT.modalRadius,
569
+ padding: LAYOUT.padding,
570
+ paddingBottom: LAYOUT.padding + 34
571
+ },
572
+ formHeader: {
573
+ flexDirection: "row",
574
+ alignItems: "center",
575
+ justifyContent: "space-between",
576
+ marginBottom: LAYOUT.padding
577
+ },
578
+ formTitle: {
579
+ fontSize: 17,
580
+ fontWeight: "600",
581
+ color: colors.text,
582
+ flex: 1
583
+ },
584
+ formCloseButton: {
585
+ width: 44,
586
+ height: 44,
587
+ alignItems: "flex-end",
588
+ justifyContent: "center"
589
+ },
590
+ formStorageType: {
591
+ fontSize: 13,
592
+ color: colors.textSecondary,
593
+ marginBottom: 12
594
+ },
595
+ formLabel: {
596
+ fontSize: 12,
597
+ fontWeight: "600",
598
+ color: colors.textSecondary,
599
+ marginBottom: 6
600
+ },
601
+ formInput: {
602
+ borderWidth: 1,
603
+ borderColor: colors.border,
604
+ borderRadius: 10,
605
+ padding: 12,
606
+ fontSize: LAYOUT.fontSize,
607
+ marginBottom: LAYOUT.padding,
608
+ color: colors.text,
609
+ backgroundColor: colors.background
610
+ },
611
+ formInputDisabled: {
612
+ backgroundColor: colors.backgroundSecondary,
613
+ color: colors.textSecondary
614
+ },
615
+ formActions: {
616
+ flexDirection: "row",
617
+ justifyContent: "flex-end",
618
+ gap: 12,
619
+ marginTop: 8
620
+ },
621
+ formButton: {
622
+ paddingVertical: 12,
623
+ paddingHorizontal: 20,
624
+ borderRadius: 10,
625
+ minWidth: 100,
626
+ alignItems: "center"
627
+ },
628
+ formButtonCancel: {
629
+ backgroundColor: "transparent",
630
+ borderWidth: 1,
631
+ borderColor: colors.text
632
+ },
633
+ formButtonSubmit: {
634
+ backgroundColor: colors.text
635
+ },
636
+ formButtonText: {
637
+ fontSize: 16,
638
+ fontWeight: "600"
639
+ },
640
+ formButtonTextCancel: {
641
+ color: colors.text
642
+ },
643
+ formButtonTextSubmit: {
644
+ color: colors.inverted
645
+ },
646
+ confirmOverlay: {
647
+ flex: 1,
648
+ backgroundColor: "rgba(0,0,0,0.5)",
649
+ justifyContent: "flex-end",
650
+ alignItems: "center"
651
+ },
652
+ confirmModal: {
653
+ width: "100%",
654
+ maxWidth: LAYOUT.screenWidth,
655
+ backgroundColor: colors.background,
656
+ borderTopLeftRadius: LAYOUT.modalRadius,
657
+ borderTopRightRadius: LAYOUT.modalRadius,
658
+ padding: LAYOUT.padding,
659
+ paddingBottom: LAYOUT.padding + 34
660
+ },
661
+ confirmHeader: {
662
+ flexDirection: "row",
663
+ alignItems: "center",
664
+ justifyContent: "space-between",
665
+ marginBottom: 12
666
+ },
667
+ confirmTitle: {
668
+ fontSize: 17,
669
+ fontWeight: "600",
670
+ color: colors.text,
671
+ flex: 1
672
+ },
673
+ confirmMessage: {
674
+ fontSize: 15,
675
+ color: colors.textSecondary,
676
+ lineHeight: 22,
677
+ marginBottom: 20
678
+ },
679
+ confirmActions: {
680
+ flexDirection: "row",
681
+ gap: 12
682
+ },
683
+ confirmButton: {
684
+ flex: 1,
685
+ paddingVertical: 14,
686
+ borderRadius: 10,
687
+ alignItems: "center"
688
+ },
689
+ confirmButtonSecondary: {
690
+ backgroundColor: "transparent",
691
+ borderWidth: 1,
692
+ borderColor: colors.text
693
+ },
694
+ confirmButtonDanger: {
695
+ backgroundColor: colors.text
696
+ },
697
+ confirmButtonText: {
698
+ fontSize: 16,
699
+ fontWeight: "600"
700
+ },
701
+ confirmButtonTextSecondary: {
702
+ color: colors.text
703
+ },
704
+ confirmButtonTextDanger: {
705
+ color: colors.inverted
706
+ }
707
+ });
708
+
709
+ // src/components/IconButton.tsx
710
+ function IconButton({
711
+ name,
712
+ onPress,
713
+ size = LAYOUT.iconSize,
714
+ tintColor = theme.colors.text,
715
+ disabled = false,
716
+ hitSlop = LAYOUT.hitSlop,
717
+ style,
718
+ activeOpacity = 0.6
719
+ }) {
720
+ return /* @__PURE__ */ React6.createElement(
721
+ TouchableOpacity,
722
+ {
723
+ style: [styles2.iconButton, style],
724
+ onPress,
725
+ disabled,
726
+ hitSlop,
727
+ activeOpacity
728
+ },
729
+ /* @__PURE__ */ React6.createElement(
730
+ Icon,
731
+ {
732
+ name,
733
+ size,
734
+ tintColor: disabled ? theme.colors.textMuted : tintColor
735
+ }
736
+ )
737
+ );
738
+ }
739
+
740
+ // src/strings.ts
741
+ var strings = {
742
+ // StorageInspector
743
+ noAdapterAvailable: "No storage adapter available. Install at least one of: react-native-mmkv, @react-native-async-storage/async-storage, react-native-keychain, expo-secure-store",
744
+ // StorageSection
745
+ keychainHint: "No generic password items yet. Add a key using + above, or pass keychainKeys for internet credentials.",
746
+ secureStoreHint: "Secure Store has no list API. Pass secureStoreKeys prop with known keys, or add a key using + above.",
747
+ loading: "Loading\u2026",
748
+ noItems: "No items",
749
+ valueLabel: "Value",
750
+ emptyValue: "(empty)",
751
+ charCount: (n) => n === 1 ? "1 char" : `${n} chars`,
752
+ deleteItemTitle: (key) => `Delete ${key}?`,
753
+ deleteItemMessage: (key) => `This will permanently delete the ${key} storage item. Do you wish to continue?`,
754
+ clearAllTitle: (name) => `Clear All ${name}?`,
755
+ clearAllMessage: (count, name) => `This will permanently delete all ${count} ${name} items. Do you wish to continue?`,
756
+ // StorageList
757
+ storageNotAvailable: "This storage is not available.",
758
+ keychainHintShort: "No items yet. Add a key below, or pass keychainKeys for internet credentials.",
759
+ edit: "Edit",
760
+ delete: "Delete",
761
+ addItem: "Add item",
762
+ // ItemForm
763
+ keyRequired: "Key is required",
764
+ saveFailed: "Save failed",
765
+ editItemTitle: (key) => `Edit ${key}`,
766
+ addItemTitle: (storageName) => `Add ${storageName} Item`,
767
+ storageTypeLabel: (name) => `Storage Type: ${name}`,
768
+ keyLabel: "Key",
769
+ enterKeyPlaceholder: "Enter key",
770
+ enterValuePlaceholder: "Enter value",
771
+ cancel: "Cancel",
772
+ saving: "Saving\u2026",
773
+ save: "Save",
774
+ add: "Add",
775
+ // ConfirmModal defaults
776
+ confirmDelete: "Yes, delete",
777
+ cancelKeep: "No, keep it"
778
+ };
779
+
780
+ // src/components/ItemForm.tsx
781
+ function ItemForm({
782
+ visible,
783
+ storageName,
784
+ editingItem,
785
+ onSave,
786
+ onCancel
787
+ }) {
788
+ const [key, setKey] = useState("");
789
+ const [value, setValue] = useState("");
790
+ const [saving, setSaving] = useState(false);
791
+ const [error, setError] = useState(null);
792
+ const isEdit = editingItem !== null;
793
+ useEffect(() => {
794
+ if (visible) {
795
+ setKey(editingItem?.key ?? "");
796
+ setValue(editingItem?.value ?? "");
797
+ setError(null);
798
+ }
799
+ }, [visible, editingItem]);
800
+ const handleSubmit = async () => {
801
+ const k = key.trim();
802
+ if (!k) {
803
+ setError(strings.keyRequired);
804
+ return;
805
+ }
806
+ setSaving(true);
807
+ setError(null);
808
+ try {
809
+ await onSave(k, value);
810
+ onCancel();
811
+ } catch (e) {
812
+ setError(e instanceof Error ? e.message : strings.saveFailed);
813
+ } finally {
814
+ setSaving(false);
815
+ }
816
+ };
817
+ const title = isEdit ? strings.editItemTitle(editingItem?.key ?? "") : strings.addItemTitle(storageName);
818
+ return /* @__PURE__ */ React6.createElement(Modal, { visible, transparent: true, animationType: "slide", onRequestClose: onCancel }, /* @__PURE__ */ React6.createElement(View, { style: styles2.formOverlay }, /* @__PURE__ */ React6.createElement(
819
+ TouchableOpacity,
820
+ {
821
+ style: { flex: 1, width: "100%" },
822
+ activeOpacity: 1,
823
+ onPress: onCancel
824
+ }
825
+ ), /* @__PURE__ */ React6.createElement(View, { style: styles2.formModal }, /* @__PURE__ */ React6.createElement(View, { style: styles2.formHeader }, /* @__PURE__ */ React6.createElement(Text, { style: styles2.formTitle, numberOfLines: 1 }, title), /* @__PURE__ */ React6.createElement(
826
+ IconButton,
827
+ {
828
+ name: "close",
829
+ onPress: onCancel,
830
+ size: 24,
831
+ tintColor: theme.colors.textSecondary,
832
+ style: styles2.formCloseButton,
833
+ hitSlop: LAYOUT.hitSlopLarge
834
+ }
835
+ )), /* @__PURE__ */ React6.createElement(Text, { style: styles2.formStorageType }, strings.storageTypeLabel(storageName)), /* @__PURE__ */ React6.createElement(Text, { style: styles2.formLabel }, strings.keyLabel), /* @__PURE__ */ React6.createElement(
836
+ TextInput,
837
+ {
838
+ style: [styles2.formInput, isEdit && styles2.formInputDisabled],
839
+ value: key,
840
+ onChangeText: setKey,
841
+ placeholder: strings.enterKeyPlaceholder,
842
+ placeholderTextColor: theme.colors.textMuted,
843
+ editable: !isEdit,
844
+ autoCapitalize: "none",
845
+ multiline: true
846
+ }
847
+ ), /* @__PURE__ */ React6.createElement(Text, { style: styles2.formLabel }, strings.valueLabel), /* @__PURE__ */ React6.createElement(
848
+ TextInput,
849
+ {
850
+ style: styles2.formInput,
851
+ value,
852
+ onChangeText: setValue,
853
+ placeholder: strings.enterValuePlaceholder,
854
+ placeholderTextColor: theme.colors.textMuted,
855
+ multiline: true,
856
+ numberOfLines: 3
857
+ }
858
+ ), error ? /* @__PURE__ */ React6.createElement(Text, { style: [styles2.errorText, { marginBottom: 12 }] }, error) : null, /* @__PURE__ */ React6.createElement(View, { style: styles2.formActions }, /* @__PURE__ */ React6.createElement(
859
+ TouchableOpacity,
860
+ {
861
+ style: [styles2.formButton, styles2.formButtonCancel],
862
+ onPress: onCancel,
863
+ disabled: saving
864
+ },
865
+ /* @__PURE__ */ React6.createElement(Text, { style: [styles2.formButtonText, styles2.formButtonTextCancel] }, strings.cancel)
866
+ ), /* @__PURE__ */ React6.createElement(
867
+ TouchableOpacity,
868
+ {
869
+ style: [styles2.formButton, styles2.formButtonSubmit],
870
+ onPress: handleSubmit,
871
+ disabled: saving
872
+ },
873
+ /* @__PURE__ */ React6.createElement(Text, { style: [styles2.formButtonText, styles2.formButtonTextSubmit] }, saving ? strings.saving : isEdit ? strings.save : strings.add)
874
+ )))));
875
+ }
876
+ function ConfirmModal({
877
+ visible,
878
+ title,
879
+ message,
880
+ confirmLabel = strings.confirmDelete,
881
+ cancelLabel = strings.cancelKeep,
882
+ danger = true,
883
+ onConfirm,
884
+ onCancel
885
+ }) {
886
+ const handleConfirm = () => {
887
+ void Promise.resolve(onConfirm());
888
+ };
889
+ return /* @__PURE__ */ React6.createElement(Modal, { visible, transparent: true, animationType: "slide", onRequestClose: onCancel }, /* @__PURE__ */ React6.createElement(View, { style: styles2.confirmOverlay }, /* @__PURE__ */ React6.createElement(
890
+ TouchableOpacity,
891
+ {
892
+ style: { flex: 1, width: "100%" },
893
+ activeOpacity: 1,
894
+ onPress: onCancel
895
+ }
896
+ ), /* @__PURE__ */ React6.createElement(View, { style: styles2.confirmModal }, /* @__PURE__ */ React6.createElement(View, { style: styles2.confirmHeader }, /* @__PURE__ */ React6.createElement(Text, { style: styles2.confirmTitle }, title), /* @__PURE__ */ React6.createElement(
897
+ IconButton,
898
+ {
899
+ name: "close",
900
+ onPress: onCancel,
901
+ size: 24,
902
+ tintColor: theme.colors.textSecondary,
903
+ style: styles2.formCloseButton,
904
+ hitSlop: LAYOUT.hitSlopLarge
905
+ }
906
+ )), /* @__PURE__ */ React6.createElement(Text, { style: styles2.confirmMessage }, message), /* @__PURE__ */ React6.createElement(View, { style: styles2.confirmActions }, /* @__PURE__ */ React6.createElement(
907
+ TouchableOpacity,
908
+ {
909
+ style: [styles2.confirmButton, styles2.confirmButtonSecondary],
910
+ onPress: onCancel
911
+ },
912
+ /* @__PURE__ */ React6.createElement(Text, { style: [styles2.confirmButtonText, styles2.confirmButtonTextSecondary] }, cancelLabel)
913
+ ), /* @__PURE__ */ React6.createElement(
914
+ TouchableOpacity,
915
+ {
916
+ style: [
917
+ styles2.confirmButton,
918
+ danger ? styles2.confirmButtonDanger : styles2.formButtonSubmit
919
+ ],
920
+ onPress: handleConfirm
921
+ },
922
+ /* @__PURE__ */ React6.createElement(
923
+ Text,
924
+ {
925
+ style: [
926
+ styles2.confirmButtonText,
927
+ danger ? styles2.confirmButtonTextDanger : styles2.formButtonTextSubmit
928
+ ]
929
+ },
930
+ confirmLabel
931
+ )
932
+ )))));
933
+ }
934
+ function ItemRowActions({
935
+ item,
936
+ onCopy,
937
+ onEdit,
938
+ onDelete,
939
+ showChevron = false,
940
+ chevronDirection = "down"
941
+ }) {
942
+ return /* @__PURE__ */ React6.createElement(View, { style: styles2.itemRowActions }, /* @__PURE__ */ React6.createElement(IconButton, { name: "copy", onPress: () => onCopy(item) }), /* @__PURE__ */ React6.createElement(IconButton, { name: "edit", onPress: () => onEdit(item) }), /* @__PURE__ */ React6.createElement(IconButton, { name: "trash", onPress: () => onDelete(item) }), showChevron && /* @__PURE__ */ React6.createElement(View, { style: styles2.iconSlot }, /* @__PURE__ */ React6.createElement(
943
+ Icon,
944
+ {
945
+ name: chevronDirection === "up" ? "chevronUp" : "chevronDown",
946
+ size: LAYOUT.chevronSize,
947
+ tintColor: theme.colors.text
948
+ }
949
+ )));
950
+ }
951
+
952
+ // src/components/StorageSection.tsx
953
+ function StorageSection({
954
+ adapter,
955
+ keychainKeys,
956
+ onKeychainKeyAdded,
957
+ onSecureStoreKeyAdded,
958
+ defaultExpanded = true,
959
+ expanded: expandedProp,
960
+ onToggleExpanded,
961
+ refreshTrigger
962
+ }) {
963
+ const { items, loading, error, refresh } = useStorageItems(adapter);
964
+ const [expandedInternal, setExpandedInternal] = useState(defaultExpanded);
965
+ const expanded = expandedProp !== void 0 ? expandedProp : expandedInternal;
966
+ const handleToggleExpanded = () => {
967
+ if (onToggleExpanded) onToggleExpanded();
968
+ else setExpandedInternal((p) => !p);
969
+ };
970
+ useEffect(() => {
971
+ if (refreshTrigger !== void 0) refresh();
972
+ }, [refreshTrigger, refresh]);
973
+ const [expandedKeys, setExpandedKeys] = useState(/* @__PURE__ */ new Set());
974
+ const [formVisible, setFormVisible] = useState(false);
975
+ const [editingItem, setEditingItem] = useState(null);
976
+ const [deleteItem, setDeleteItem] = useState(null);
977
+ const [clearAllVisible, setClearAllVisible] = useState(false);
978
+ const handleAdd = () => {
979
+ setEditingItem(null);
980
+ setFormVisible(true);
981
+ };
982
+ const handleEdit = (item) => {
983
+ setEditingItem(item);
984
+ setFormVisible(true);
985
+ };
986
+ const handleSave = async (key, value) => {
987
+ const isNewKey = !editingItem || editingItem.key !== key;
988
+ await adapter.setItem(key, value);
989
+ if (adapter.type === "keychain" && isNewKey) {
990
+ onKeychainKeyAdded?.(key);
991
+ }
992
+ if (adapter.type === "expo-secure-store" && isNewKey) {
993
+ onSecureStoreKeyAdded?.(key);
994
+ }
995
+ await refresh();
996
+ };
997
+ const handleDeleteItem = async () => {
998
+ if (deleteItem) {
999
+ await adapter.removeItem(deleteItem.key);
1000
+ setDeleteItem(null);
1001
+ await refresh();
1002
+ }
1003
+ };
1004
+ const handleClearAll = async () => {
1005
+ for (const item of items) {
1006
+ await adapter.removeItem(item.key);
1007
+ }
1008
+ setClearAllVisible(false);
1009
+ await refresh();
1010
+ };
1011
+ const handleCopy = async (item) => {
1012
+ try {
1013
+ await Share.share({
1014
+ message: item.value,
1015
+ title: item.key
1016
+ });
1017
+ } catch {
1018
+ }
1019
+ };
1020
+ const isKeychain = adapter.type === "keychain";
1021
+ const isSecureStore = adapter.type === "expo-secure-store";
1022
+ const showKeychainHint = isKeychain && items.length === 0 && (keychainKeys?.length ?? 0) === 0;
1023
+ const showSecureStoreHint = isSecureStore && items.length === 0;
1024
+ if (!adapter.isAvailable()) return null;
1025
+ return /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(
1026
+ TouchableOpacity,
1027
+ {
1028
+ style: styles2.sectionHeader,
1029
+ onPress: handleToggleExpanded,
1030
+ activeOpacity: 0.7
1031
+ },
1032
+ /* @__PURE__ */ React6.createElement(View, { style: styles2.sectionHeaderLabelWrap }, /* @__PURE__ */ React6.createElement(Text, { style: styles2.sectionHeaderLabel }, adapter.name, /* @__PURE__ */ React6.createElement(Text, { style: styles2.sectionHeaderCount }, " (", items.length, ")"))),
1033
+ /* @__PURE__ */ React6.createElement(View, { style: styles2.storageRowActions }, /* @__PURE__ */ React6.createElement(IconButton, { name: "plus", onPress: handleAdd }), /* @__PURE__ */ React6.createElement(
1034
+ IconButton,
1035
+ {
1036
+ name: "trash",
1037
+ onPress: () => items.length > 0 && setClearAllVisible(true),
1038
+ disabled: items.length === 0
1039
+ }
1040
+ ), /* @__PURE__ */ React6.createElement(View, { style: styles2.iconSlot }, /* @__PURE__ */ React6.createElement(
1041
+ Icon,
1042
+ {
1043
+ name: expanded ? "chevronUp" : "chevronDown",
1044
+ size: LAYOUT.chevronSize,
1045
+ tintColor: theme.colors.text
1046
+ }
1047
+ )))
1048
+ ), expanded && /* @__PURE__ */ React6.createElement(React6.Fragment, null, showKeychainHint ? /* @__PURE__ */ React6.createElement(View, { style: styles2.keychainHint }, /* @__PURE__ */ React6.createElement(Text, { style: styles2.keychainHintText }, strings.keychainHint)) : null, showSecureStoreHint ? /* @__PURE__ */ React6.createElement(View, { style: styles2.keychainHint }, /* @__PURE__ */ React6.createElement(Text, { style: styles2.keychainHintText }, strings.secureStoreHint)) : null, error ? /* @__PURE__ */ React6.createElement(View, { style: styles2.error }, /* @__PURE__ */ React6.createElement(Text, { style: styles2.errorText }, error)) : null, loading ? /* @__PURE__ */ React6.createElement(View, { style: styles2.loading }, /* @__PURE__ */ React6.createElement(Text, { style: styles2.loadingText }, strings.loading)) : items.map((item) => {
1049
+ const isItemExpanded = expandedKeys.has(item.key);
1050
+ const charCount = item.value.length;
1051
+ const toggleItemExpanded = () => {
1052
+ setExpandedKeys((prev) => {
1053
+ const next = new Set(prev);
1054
+ if (next.has(item.key)) next.delete(item.key);
1055
+ else next.add(item.key);
1056
+ return next;
1057
+ });
1058
+ };
1059
+ return /* @__PURE__ */ React6.createElement(
1060
+ TouchableOpacity,
1061
+ {
1062
+ key: item.key,
1063
+ style: styles2.itemRow,
1064
+ onPress: toggleItemExpanded,
1065
+ activeOpacity: 0.7
1066
+ },
1067
+ /* @__PURE__ */ React6.createElement(View, { style: styles2.itemRowCollapsed }, /* @__PURE__ */ React6.createElement(View, { style: { flex: 1 } }, /* @__PURE__ */ React6.createElement(Text, { style: styles2.itemKey, numberOfLines: 1 }, item.key), /* @__PURE__ */ React6.createElement(Text, { style: styles2.itemChars }, strings.charCount(charCount))), !isItemExpanded ? /* @__PURE__ */ React6.createElement(
1068
+ ItemRowActions,
1069
+ {
1070
+ item,
1071
+ onCopy: handleCopy,
1072
+ onEdit: handleEdit,
1073
+ onDelete: setDeleteItem,
1074
+ showChevron: true,
1075
+ chevronDirection: "down"
1076
+ }
1077
+ ) : /* @__PURE__ */ React6.createElement(View, { style: styles2.iconSlot }, /* @__PURE__ */ React6.createElement(
1078
+ Icon,
1079
+ {
1080
+ name: "chevronUp",
1081
+ size: LAYOUT.chevronSize,
1082
+ tintColor: theme.colors.text
1083
+ }
1084
+ ))),
1085
+ isItemExpanded && /* @__PURE__ */ React6.createElement(View, { style: styles2.itemRowExpanded }, /* @__PURE__ */ React6.createElement(View, { style: styles2.valueBox }, /* @__PURE__ */ React6.createElement(Text, { style: styles2.valueBoxLabel }, strings.valueLabel), /* @__PURE__ */ React6.createElement(Text, { style: styles2.valueBoxText, selectable: true }, item.value || strings.emptyValue)), /* @__PURE__ */ React6.createElement(
1086
+ ItemRowActions,
1087
+ {
1088
+ item,
1089
+ onCopy: handleCopy,
1090
+ onEdit: handleEdit,
1091
+ onDelete: setDeleteItem
1092
+ }
1093
+ ))
1094
+ );
1095
+ }), !loading && items.length === 0 && !showKeychainHint && !showSecureStoreHint ? /* @__PURE__ */ React6.createElement(View, { style: styles2.empty }, /* @__PURE__ */ React6.createElement(Text, { style: styles2.emptyText }, strings.noItems)) : null), /* @__PURE__ */ React6.createElement(
1096
+ ItemForm,
1097
+ {
1098
+ visible: formVisible,
1099
+ storageName: adapter.name,
1100
+ editingItem,
1101
+ onSave: handleSave,
1102
+ onCancel: () => {
1103
+ setFormVisible(false);
1104
+ setEditingItem(null);
1105
+ }
1106
+ }
1107
+ ), /* @__PURE__ */ React6.createElement(
1108
+ ConfirmModal,
1109
+ {
1110
+ visible: deleteItem !== null,
1111
+ title: strings.deleteItemTitle(deleteItem?.key ?? ""),
1112
+ message: strings.deleteItemMessage(deleteItem?.key ?? ""),
1113
+ onConfirm: handleDeleteItem,
1114
+ onCancel: () => setDeleteItem(null)
1115
+ }
1116
+ ), /* @__PURE__ */ React6.createElement(
1117
+ ConfirmModal,
1118
+ {
1119
+ visible: clearAllVisible,
1120
+ title: strings.clearAllTitle(adapter.name),
1121
+ message: strings.clearAllMessage(items.length, adapter.name),
1122
+ onConfirm: handleClearAll,
1123
+ onCancel: () => setClearAllVisible(false)
1124
+ }
1125
+ ));
1126
+ }
1127
+
1128
+ // src/components/StorageInspector.tsx
1129
+ function StorageInspector({
1130
+ mmkvInstances = [],
1131
+ keychainKeys: keychainKeysProp,
1132
+ secureStoreKeys: secureStoreKeysProp,
1133
+ customAdapters = []
1134
+ }) {
1135
+ const [keychainKeysAdded, setKeychainKeysAdded] = useState([]);
1136
+ const [secureStoreKeysAdded, setSecureStoreKeysAdded] = useState([]);
1137
+ const [refreshKey, setRefreshKey] = useState(0);
1138
+ const [refreshing, setRefreshing] = useState(false);
1139
+ const [expandedIndices, setExpandedIndices] = useState(() => /* @__PURE__ */ new Set([0]));
1140
+ const keychainKeys = useMemo(
1141
+ () => [...keychainKeysProp ?? [], ...keychainKeysAdded],
1142
+ [keychainKeysProp, keychainKeysAdded]
1143
+ );
1144
+ const secureStoreKeys = useMemo(
1145
+ () => [...secureStoreKeysProp ?? [], ...secureStoreKeysAdded],
1146
+ [secureStoreKeysProp, secureStoreKeysAdded]
1147
+ );
1148
+ const adapters = useMemo(() => {
1149
+ const list = [];
1150
+ mmkvInstances.forEach((inst, i) => {
1151
+ list.push(
1152
+ createMMKVAdapter(inst, mmkvInstances.length > 1 ? `MMKV ${i + 1}` : "MMKV")
1153
+ );
1154
+ });
1155
+ const asyncAdapter = createAsyncStorageAdapter();
1156
+ if (asyncAdapter.isAvailable()) list.push(asyncAdapter);
1157
+ const keychainAdapter = createKeychainAdapter(keychainKeys);
1158
+ if (keychainAdapter.isAvailable()) list.push(keychainAdapter);
1159
+ const secureStoreAdapter = createSecureStoreAdapter(secureStoreKeys);
1160
+ if (secureStoreAdapter.isAvailable()) list.push(secureStoreAdapter);
1161
+ list.push(...customAdapters);
1162
+ return list;
1163
+ }, [mmkvInstances, keychainKeys, secureStoreKeys, customAdapters]);
1164
+ const handleKeychainKeyAdded = (key) => {
1165
+ setKeychainKeysAdded(
1166
+ (prev) => prev.includes(key) ? prev : [...prev, key]
1167
+ );
1168
+ };
1169
+ const handleSecureStoreKeyAdded = (key) => {
1170
+ setSecureStoreKeysAdded(
1171
+ (prev) => prev.includes(key) ? prev : [...prev, key]
1172
+ );
1173
+ };
1174
+ const handleRefresh = () => {
1175
+ setRefreshing(true);
1176
+ setRefreshKey((k) => k + 1);
1177
+ setTimeout(() => setRefreshing(false), 400);
1178
+ };
1179
+ return /* @__PURE__ */ React6.createElement(View, { style: styles2.container }, /* @__PURE__ */ React6.createElement(View, { style: styles2.content }, adapters.length > 0 ? /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(
1180
+ ScrollView,
1181
+ {
1182
+ style: styles2.scroll,
1183
+ contentContainerStyle: styles2.scrollContent,
1184
+ keyboardShouldPersistTaps: "handled",
1185
+ showsVerticalScrollIndicator: true,
1186
+ refreshControl: /* @__PURE__ */ React6.createElement(RefreshControl, { refreshing, onRefresh: handleRefresh })
1187
+ },
1188
+ adapters.map((adapter, index) => /* @__PURE__ */ React6.createElement(
1189
+ StorageSection,
1190
+ {
1191
+ key: `${adapter.type}-${index}`,
1192
+ adapter,
1193
+ keychainKeys: keychainKeysProp,
1194
+ onKeychainKeyAdded: handleKeychainKeyAdded,
1195
+ onSecureStoreKeyAdded: handleSecureStoreKeyAdded,
1196
+ expanded: expandedIndices.has(index),
1197
+ onToggleExpanded: () => {
1198
+ setExpandedIndices((prev) => {
1199
+ const next = new Set(prev);
1200
+ if (next.has(index)) next.delete(index);
1201
+ else next.add(index);
1202
+ return next;
1203
+ });
1204
+ },
1205
+ refreshTrigger: refreshKey
1206
+ }
1207
+ ))
1208
+ ), /* @__PURE__ */ React6.createElement(
1209
+ IconButton,
1210
+ {
1211
+ name: "refresh",
1212
+ onPress: handleRefresh,
1213
+ size: 24,
1214
+ tintColor: theme.colors.inverted,
1215
+ style: styles2.fab,
1216
+ activeOpacity: 0.85
1217
+ }
1218
+ )) : /* @__PURE__ */ React6.createElement(View, { style: styles2.empty }, /* @__PURE__ */ React6.createElement(Text, { style: styles2.emptyText }, strings.noAdapterAvailable))));
1219
+ }
1220
+
1221
+ export { StorageInspector, createAsyncStorageAdapter, createKeychainAdapter, createMMKVAdapter, createSecureStoreAdapter, strings, theme };
1222
+ //# sourceMappingURL=index.mjs.map
1223
+ //# sourceMappingURL=index.mjs.map