@buoy-gg/storage 7.0.41 → 7.0.42
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/README.md +11 -90
- package/lib/commonjs/index.js +1 -353
- package/lib/commonjs/preset.js +1 -85
- package/lib/commonjs/storage/components/DiffViewer/TreeDiffViewer.js +1 -36
- package/lib/commonjs/storage/components/DiffViewer/modes/ThemedSplitView.js +1 -12
- package/lib/commonjs/storage/components/DiffViewer/themes/diffThemes.js +1 -24
- package/lib/commonjs/storage/components/GameUIStorageBrowser.js +3 -1259
- package/lib/commonjs/storage/components/MMKVInstanceInfoPanel.js +1 -257
- package/lib/commonjs/storage/components/MMKVInstanceSelector.js +1 -419
- package/lib/commonjs/storage/components/SelectionActionBar.js +1 -207
- package/lib/commonjs/storage/components/StorageActionButtons.js +1 -242
- package/lib/commonjs/storage/components/StorageBrowserMode.js +1 -61
- package/lib/commonjs/storage/components/StorageEventActionButton.js +1 -121
- package/lib/commonjs/storage/components/StorageEventCard.js +1 -118
- package/lib/commonjs/storage/components/StorageEventDetailContent.js +1 -494
- package/lib/commonjs/storage/components/StorageEventFilterView.js +1 -160
- package/lib/commonjs/storage/components/StorageEventsSection.js +1 -24
- package/lib/commonjs/storage/components/StorageFilterCards.js +1 -231
- package/lib/commonjs/storage/components/StorageKeyCard.js +1 -520
- package/lib/commonjs/storage/components/StorageKeyDetailScreen.js +1 -579
- package/lib/commonjs/storage/components/StorageKeyRow.js +1 -559
- package/lib/commonjs/storage/components/StorageKeySection.js +1 -160
- package/lib/commonjs/storage/components/StorageKeyStats.js +1 -345
- package/lib/commonjs/storage/components/StorageModalWithTabs.js +1 -954
- package/lib/commonjs/storage/components/StorageSaveNotice.js +1 -171
- package/lib/commonjs/storage/components/StorageSection.js +1 -43
- package/lib/commonjs/storage/components/StorageTypeFilterBar.js +1 -144
- package/lib/commonjs/storage/hooks/useAsyncStorageKeys.js +1 -141
- package/lib/commonjs/storage/hooks/useMMKVInstances.js +1 -210
- package/lib/commonjs/storage/hooks/useMMKVKeys.js +1 -376
- package/lib/commonjs/storage/hooks/useSecureStoreKeys.js +1 -202
- package/lib/commonjs/storage/hooks/useStorageEvents.js +1 -61
- package/lib/commonjs/storage/stores/storageEventStore.js +1 -312
- package/lib/commonjs/storage/sync/storageSyncAdapter.js +1 -492
- package/lib/commonjs/storage/types.js +1 -5
- package/lib/commonjs/storage/utils/AsyncStorageListener.js +1 -691
- package/lib/commonjs/storage/utils/AsyncStorageListener.web.js +1 -89
- package/lib/commonjs/storage/utils/MMKVInstanceRegistry.js +1 -203
- package/lib/commonjs/storage/utils/MMKVListener.js +1 -416
- package/lib/commonjs/storage/utils/SecureStoreRegistry.js +1 -200
- package/lib/commonjs/storage/utils/asyncStorageCompat.js +1 -89
- package/lib/commonjs/storage/utils/browserStorageLifecycle.js +1 -10
- package/lib/commonjs/storage/utils/browserStorageLifecycle.web.js +1 -70
- package/lib/commonjs/storage/utils/clearAllStorage.js +1 -48
- package/lib/commonjs/storage/utils/deleteStorageKeys.js +1 -82
- package/lib/commonjs/storage/utils/lineDiff.js +1 -30
- package/lib/commonjs/storage/utils/mmkvAvailability.js +1 -62
- package/lib/commonjs/storage/utils/mmkvAvailability.web.js +1 -21
- package/lib/commonjs/storage/utils/mmkvTypeDetection.js +1 -154
- package/lib/commonjs/storage/utils/requiredStorageKeyScope.js +1 -17
- package/lib/commonjs/storage/utils/setStorageValue.js +1 -218
- package/lib/commonjs/storage/utils/snapshotProvider.js +1 -382
- package/lib/commonjs/storage/utils/storageActionHelpers.js +1 -46
- package/lib/commonjs/storage/utils/storageBrowserRefresh.js +1 -49
- package/lib/commonjs/storage/utils/storageLabels.js +1 -13
- package/lib/commonjs/storage/utils/storageLabels.web.js +1 -13
- package/lib/commonjs/storage/utils/storageOps.js +1 -53
- package/lib/commonjs/storage/utils/storageQueryUtils.js +1 -35
- package/lib/commonjs/storage/utils/storageTimeTravelUtils.js +1 -288
- package/lib/commonjs/storage/utils/valueType.js +1 -83
- package/lib/module/index.js +1 -114
- package/lib/module/preset.js +1 -82
- package/lib/module/storage/components/DiffViewer/TreeDiffViewer.js +1 -32
- package/lib/module/storage/components/DiffViewer/modes/ThemedSplitView.js +1 -9
- package/lib/module/storage/components/DiffViewer/themes/diffThemes.js +1 -10
- package/lib/module/storage/components/GameUIStorageBrowser.js +3 -1257
- package/lib/module/storage/components/MMKVInstanceInfoPanel.js +1 -253
- package/lib/module/storage/components/MMKVInstanceSelector.js +1 -415
- package/lib/module/storage/components/SelectionActionBar.js +1 -204
- package/lib/module/storage/components/StorageActionButtons.js +1 -238
- package/lib/module/storage/components/StorageBrowserMode.js +1 -57
- package/lib/module/storage/components/StorageEventActionButton.js +1 -118
- package/lib/module/storage/components/StorageEventCard.js +1 -113
- package/lib/module/storage/components/StorageEventDetailContent.js +1 -490
- package/lib/module/storage/components/StorageEventFilterView.js +1 -156
- package/lib/module/storage/components/StorageEventsSection.js +1 -20
- package/lib/module/storage/components/StorageFilterCards.js +1 -227
- package/lib/module/storage/components/StorageKeyCard.js +1 -517
- package/lib/module/storage/components/StorageKeyDetailScreen.js +1 -577
- package/lib/module/storage/components/StorageKeyRow.js +1 -554
- package/lib/module/storage/components/StorageKeySection.js +1 -155
- package/lib/module/storage/components/StorageKeyStats.js +1 -342
- package/lib/module/storage/components/StorageModalWithTabs.js +1 -949
- package/lib/module/storage/components/StorageSaveNotice.js +1 -168
- package/lib/module/storage/components/StorageSection.js +1 -40
- package/lib/module/storage/components/StorageTypeFilterBar.js +1 -139
- package/lib/module/storage/hooks/useAsyncStorageKeys.js +1 -136
- package/lib/module/storage/hooks/useMMKVInstances.js +1 -204
- package/lib/module/storage/hooks/useMMKVKeys.js +1 -371
- package/lib/module/storage/hooks/useSecureStoreKeys.js +1 -199
- package/lib/module/storage/hooks/useStorageEvents.js +1 -58
- package/lib/module/storage/stores/storageEventStore.js +1 -301
- package/lib/module/storage/sync/storageSyncAdapter.js +1 -486
- package/lib/module/storage/types.js +1 -3
- package/lib/module/storage/utils/AsyncStorageListener.js +1 -679
- package/lib/module/storage/utils/AsyncStorageListener.web.js +1 -76
- package/lib/module/storage/utils/MMKVInstanceRegistry.js +1 -197
- package/lib/module/storage/utils/MMKVListener.js +1 -403
- package/lib/module/storage/utils/SecureStoreRegistry.js +1 -194
- package/lib/module/storage/utils/asyncStorageCompat.js +1 -81
- package/lib/module/storage/utils/browserStorageLifecycle.js +1 -6
- package/lib/module/storage/utils/browserStorageLifecycle.web.js +1 -66
- package/lib/module/storage/utils/clearAllStorage.js +1 -43
- package/lib/module/storage/utils/deleteStorageKeys.js +1 -78
- package/lib/module/storage/utils/lineDiff.js +1 -12
- package/lib/module/storage/utils/mmkvAvailability.js +1 -56
- package/lib/module/storage/utils/mmkvAvailability.web.js +1 -15
- package/lib/module/storage/utils/mmkvTypeDetection.js +1 -148
- package/lib/module/storage/utils/requiredStorageKeyScope.js +1 -13
- package/lib/module/storage/utils/setStorageValue.js +1 -209
- package/lib/module/storage/utils/snapshotProvider.js +1 -380
- package/lib/module/storage/utils/storageActionHelpers.js +1 -42
- package/lib/module/storage/utils/storageBrowserRefresh.js +1 -44
- package/lib/module/storage/utils/storageLabels.js +1 -9
- package/lib/module/storage/utils/storageLabels.web.js +1 -9
- package/lib/module/storage/utils/storageOps.js +1 -46
- package/lib/module/storage/utils/storageQueryUtils.js +1 -30
- package/lib/module/storage/utils/storageTimeTravelUtils.js +1 -281
- package/lib/module/storage/utils/valueType.js +1 -76
- package/lib/web/index.mjs +2 -3
- package/package.json +5 -5
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/preset.d.ts.map +0 -1
- package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts.map +0 -1
- package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts.map +0 -1
- package/lib/typescript/storage/components/DiffViewer/themes/diffThemes.d.ts.map +0 -1
- package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts.map +0 -1
- package/lib/typescript/storage/components/MMKVInstanceInfoPanel.d.ts.map +0 -1
- package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts.map +0 -1
- package/lib/typescript/storage/components/SelectionActionBar.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageActionButtons.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageBrowserMode.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageEventActionButton.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageEventCard.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageEventDetailContent.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageEventFilterView.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageEventsSection.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageFilterCards.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageKeyCard.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageKeyDetailScreen.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageKeyRow.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageKeySection.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageKeyStats.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageModalWithTabs.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageSaveNotice.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageSection.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageTypeFilterBar.d.ts.map +0 -1
- package/lib/typescript/storage/hooks/useAsyncStorageKeys.d.ts.map +0 -1
- package/lib/typescript/storage/hooks/useMMKVInstances.d.ts.map +0 -1
- package/lib/typescript/storage/hooks/useMMKVKeys.d.ts.map +0 -1
- package/lib/typescript/storage/hooks/useSecureStoreKeys.d.ts.map +0 -1
- package/lib/typescript/storage/hooks/useStorageEvents.d.ts.map +0 -1
- package/lib/typescript/storage/stores/storageEventStore.d.ts.map +0 -1
- package/lib/typescript/storage/sync/storageSyncAdapter.d.ts.map +0 -1
- package/lib/typescript/storage/types.d.ts.map +0 -1
- package/lib/typescript/storage/utils/AsyncStorageListener.d.ts.map +0 -1
- package/lib/typescript/storage/utils/AsyncStorageListener.web.d.ts.map +0 -1
- package/lib/typescript/storage/utils/MMKVInstanceRegistry.d.ts.map +0 -1
- package/lib/typescript/storage/utils/MMKVListener.d.ts.map +0 -1
- package/lib/typescript/storage/utils/SecureStoreRegistry.d.ts.map +0 -1
- package/lib/typescript/storage/utils/asyncStorageCompat.d.ts.map +0 -1
- package/lib/typescript/storage/utils/browserStorageLifecycle.d.ts.map +0 -1
- package/lib/typescript/storage/utils/browserStorageLifecycle.web.d.ts.map +0 -1
- package/lib/typescript/storage/utils/clearAllStorage.d.ts.map +0 -1
- package/lib/typescript/storage/utils/deleteStorageKeys.d.ts.map +0 -1
- package/lib/typescript/storage/utils/lineDiff.d.ts.map +0 -1
- package/lib/typescript/storage/utils/mmkvAvailability.d.ts.map +0 -1
- package/lib/typescript/storage/utils/mmkvAvailability.web.d.ts.map +0 -1
- package/lib/typescript/storage/utils/mmkvTypeDetection.d.ts.map +0 -1
- package/lib/typescript/storage/utils/requiredStorageKeyScope.d.ts.map +0 -1
- package/lib/typescript/storage/utils/setStorageValue.d.ts.map +0 -1
- package/lib/typescript/storage/utils/snapshotProvider.d.ts.map +0 -1
- package/lib/typescript/storage/utils/storageActionHelpers.d.ts.map +0 -1
- package/lib/typescript/storage/utils/storageBrowserRefresh.d.ts.map +0 -1
- package/lib/typescript/storage/utils/storageLabels.d.ts.map +0 -1
- package/lib/typescript/storage/utils/storageLabels.web.d.ts.map +0 -1
- package/lib/typescript/storage/utils/storageOps.d.ts.map +0 -1
- package/lib/typescript/storage/utils/storageQueryUtils.d.ts.map +0 -1
- package/lib/typescript/storage/utils/storageTimeTravelUtils.d.ts.map +0 -1
- package/lib/typescript/storage/utils/valueType.d.ts.map +0 -1
|
@@ -1,155 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { useCallback, useState } from "react";
|
|
4
|
-
import { View, Text, StyleSheet } from "react-native";
|
|
5
|
-
import { StorageKeyRow } from "./StorageKeyRow";
|
|
6
|
-
import { SectionHeader, night } from "@buoy-gg/shared-ui";
|
|
7
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
|
-
/**
|
|
9
|
-
* Identifies a ROW, not a key name — the same name routinely exists in more
|
|
10
|
-
* than one backend. Shared with the browser so both sides agree on the id.
|
|
11
|
-
*/
|
|
12
|
-
export function storageRowId(storageKey) {
|
|
13
|
-
return storageKey.instanceId ? `${storageKey.storageType}-${storageKey.instanceId}-${storageKey.key}` : `${storageKey.storageType}-${storageKey.key}`;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Storage key section component following composition principles [[rule3]]
|
|
17
|
-
*
|
|
18
|
-
* Applied principles:
|
|
19
|
-
* - Decompose by Responsibility: Single purpose component for grouped storage keys
|
|
20
|
-
* - Prefer Composition over Configuration: Reuses patterns from EnvVarSection
|
|
21
|
-
* - Extract Reusable Logic: Shares expansion state management pattern
|
|
22
|
-
*/
|
|
23
|
-
export function StorageKeySection({
|
|
24
|
-
title,
|
|
25
|
-
count,
|
|
26
|
-
keys,
|
|
27
|
-
emptyMessage,
|
|
28
|
-
headerColor,
|
|
29
|
-
isSelectMode = false,
|
|
30
|
-
selectedKeys = new Set(),
|
|
31
|
-
onSelectionChange,
|
|
32
|
-
eventCountByKey,
|
|
33
|
-
onViewHistory,
|
|
34
|
-
onHideKey,
|
|
35
|
-
pinnedKeys,
|
|
36
|
-
onTogglePin,
|
|
37
|
-
onEditKey,
|
|
38
|
-
onToggleKey,
|
|
39
|
-
onDeleteKey,
|
|
40
|
-
editBlockedFor,
|
|
41
|
-
onRowRef,
|
|
42
|
-
onOpenKey
|
|
43
|
-
}) {
|
|
44
|
-
/**
|
|
45
|
-
* Identifies a ROW, not a key name.
|
|
46
|
-
*
|
|
47
|
-
* The same name routinely exists in more than one place — an app that keeps
|
|
48
|
-
* `auth.refreshToken` in both MMKV and the keychain has two rows called
|
|
49
|
-
* that, and they are different values in different stores.
|
|
50
|
-
*/
|
|
51
|
-
const getKeyIdentifier = useCallback(storageKey => storageRowId(storageKey), []);
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Which ROW is expanded — by identifier, not by key name.
|
|
55
|
-
*
|
|
56
|
-
* Keyed by name, tapping one of a pair of same-named rows opened BOTH of
|
|
57
|
-
* them: two cards, two value trees, and two Edit buttons, one of which
|
|
58
|
-
* writes to a store you weren't looking at.
|
|
59
|
-
*/
|
|
60
|
-
const [expandedKey, setExpandedKey] = useState(null);
|
|
61
|
-
const handleKeyPress = useCallback(storageKey => {
|
|
62
|
-
// Fiber-driven automation can invoke the ROW's onPress prop directly,
|
|
63
|
-
// handing this a GestureResponderEvent instead of the key the row's own
|
|
64
|
-
// touchable wrapper binds. Rendering an event as a key produced a
|
|
65
|
-
// convincing all-"undefined" detail screen; refuse anything that isn't
|
|
66
|
-
// a key.
|
|
67
|
-
if (!storageKey || typeof storageKey.key !== "string") return;
|
|
68
|
-
if (onOpenKey) {
|
|
69
|
-
// Navigate-to-detail hosts: the card is a door, not a drawer.
|
|
70
|
-
onOpenKey(storageKey);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
const id = getKeyIdentifier(storageKey);
|
|
74
|
-
setExpandedKey(prev => prev === id ? null : id);
|
|
75
|
-
}, [getKeyIdentifier, onOpenKey]);
|
|
76
|
-
if (keys.length === 0 && title === "Required Keys") {
|
|
77
|
-
return /*#__PURE__*/_jsxs(View, {
|
|
78
|
-
style: styles.sectionContainer,
|
|
79
|
-
children: [/*#__PURE__*/_jsxs(SectionHeader, {
|
|
80
|
-
children: [/*#__PURE__*/_jsx(SectionHeader.Title, {
|
|
81
|
-
children: title
|
|
82
|
-
}), /*#__PURE__*/_jsx(SectionHeader.Badge, {
|
|
83
|
-
count: 0,
|
|
84
|
-
color: headerColor
|
|
85
|
-
})]
|
|
86
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
87
|
-
style: styles.emptySection,
|
|
88
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
89
|
-
style: styles.emptySectionText,
|
|
90
|
-
children: emptyMessage
|
|
91
|
-
})
|
|
92
|
-
})]
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
if (keys.length === 0) return null;
|
|
96
|
-
return /*#__PURE__*/_jsxs(View, {
|
|
97
|
-
style: styles.sectionContainer,
|
|
98
|
-
children: [title ? /*#__PURE__*/_jsxs(SectionHeader, {
|
|
99
|
-
children: [/*#__PURE__*/_jsx(SectionHeader.Title, {
|
|
100
|
-
children: title
|
|
101
|
-
}), count >= 0 && /*#__PURE__*/_jsx(SectionHeader.Badge, {
|
|
102
|
-
count: count,
|
|
103
|
-
color: headerColor
|
|
104
|
-
})]
|
|
105
|
-
}) : null, /*#__PURE__*/_jsx(View, {
|
|
106
|
-
style: styles.sectionContent,
|
|
107
|
-
children: keys.map(storageKey => {
|
|
108
|
-
// Create unique key by combining storage type, instance ID (if present), and key name
|
|
109
|
-
const uniqueKey = getKeyIdentifier(storageKey);
|
|
110
|
-
return /*#__PURE__*/_jsx(View, {
|
|
111
|
-
ref: onRowRef ? node => onRowRef(uniqueKey, node) : undefined,
|
|
112
|
-
collapsable: false,
|
|
113
|
-
children: /*#__PURE__*/_jsx(StorageKeyRow, {
|
|
114
|
-
storageKey: storageKey,
|
|
115
|
-
isExpanded: !isSelectMode && expandedKey === uniqueKey,
|
|
116
|
-
onPress: handleKeyPress,
|
|
117
|
-
isSelectMode: isSelectMode,
|
|
118
|
-
isSelected: selectedKeys.has(uniqueKey),
|
|
119
|
-
onSelectionChange: onSelectionChange,
|
|
120
|
-
eventCount: eventCountByKey?.[storageKey.key],
|
|
121
|
-
onViewHistory: onViewHistory ? () => onViewHistory(storageKey.key) : undefined,
|
|
122
|
-
onHideKey: onHideKey,
|
|
123
|
-
onEditKey: onEditKey,
|
|
124
|
-
onToggleKey: onToggleKey,
|
|
125
|
-
onDeleteKey: onDeleteKey,
|
|
126
|
-
editBlockedReason: editBlockedFor?.(storageKey),
|
|
127
|
-
isPinned: pinnedKeys?.has(storageKey.key),
|
|
128
|
-
onTogglePin: onTogglePin
|
|
129
|
-
})
|
|
130
|
-
}, uniqueKey);
|
|
131
|
-
})
|
|
132
|
-
})]
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
const styles = StyleSheet.create({
|
|
136
|
-
sectionContainer: {
|
|
137
|
-
gap: 8
|
|
138
|
-
},
|
|
139
|
-
sectionContent: {
|
|
140
|
-
// No gap needed, StorageKeyRow has its own margins
|
|
141
|
-
},
|
|
142
|
-
emptySection: {
|
|
143
|
-
backgroundColor: night.color.surface,
|
|
144
|
-
borderRadius: 6,
|
|
145
|
-
padding: 16,
|
|
146
|
-
borderWidth: 1,
|
|
147
|
-
borderColor: night.color.border,
|
|
148
|
-
alignItems: "center"
|
|
149
|
-
},
|
|
150
|
-
emptySectionText: {
|
|
151
|
-
color: night.color.textTertiary,
|
|
152
|
-
fontSize: 11,
|
|
153
|
-
textAlign: "center"
|
|
154
|
-
}
|
|
155
|
-
});
|
|
1
|
+
"use strict";import{useCallback as x,useState as H}from"react";import{View as r,Text as _,StyleSheet as v}from"react-native";import{StorageKeyRow as z}from"./StorageKeyRow";import{SectionHeader as o,night as f}from"@buoy-gg/shared-ui";import{jsx as t,jsxs as l}from"react/jsx-runtime";export function storageRowId(n){return n.instanceId?`${n.storageType}-${n.instanceId}-${n.key}`:`${n.storageType}-${n.key}`}export function StorageKeySection({title:n,count:p,keys:d,emptyMessage:g,headerColor:h,isSelectMode:y=false,selectedKeys:T=new Set,onSelectionChange:C,eventCountByKey:b,onViewHistory:m,onHideKey:k,pinnedKeys:I,onTogglePin:$,onEditKey:j,onToggleKey:P,onDeleteKey:w,editBlockedFor:B,onRowRef:S,onOpenKey:s}){const a=x(e=>storageRowId(e),[]);const[E,R]=H(null);const q=x(e=>{if(!e||typeof e.key!=="string")return;if(s){s(e);return}const i=a(e);R(u=>u===i?null:i)},[a,s]);if(d.length===0&&n==="Required Keys"){return l(r,{style:c.sectionContainer,children:[l(o,{children:[t(o.Title,{children:n}),t(o.Badge,{count:0,color:h})]}),t(r,{style:c.emptySection,children:t(_,{style:c.emptySectionText,children:g})})]})}if(d.length===0)return null;return l(r,{style:c.sectionContainer,children:[n?l(o,{children:[t(o.Title,{children:n}),p>=0&&t(o.Badge,{count:p,color:h})]}):null,t(r,{style:c.sectionContent,children:d.map(e=>{const i=a(e);return t(r,{ref:S?u=>S(i,u):void 0,collapsable:false,children:t(z,{storageKey:e,isExpanded:!y&&E===i,onPress:q,isSelectMode:y,isSelected:T.has(i),onSelectionChange:C,eventCount:b?.[e.key],onViewHistory:m?()=>m(e.key):void 0,onHideKey:k,onEditKey:j,onToggleKey:P,onDeleteKey:w,editBlockedReason:B?.(e),isPinned:I?.has(e.key),onTogglePin:$})},i)})})]})}const c=v.create({sectionContainer:{gap:8},sectionContent:{},emptySection:{backgroundColor:f.color.surface,borderRadius:6,padding:16,borderWidth:1,borderColor:f.color.border,alignItems:"center"},emptySectionText:{color:f.color.textTertiary,fontSize:11,textAlign:"center"}});
|
|
@@ -1,342 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { storageLabels } from "../utils/storageLabels";
|
|
4
|
-
import { View, Text, StyleSheet } from "react-native";
|
|
5
|
-
import { AlertCircle, CheckCircle2, XCircle, Eye, Database, Shield } from "@buoy-gg/shared-ui";
|
|
6
|
-
import { night } from "@buoy-gg/shared-ui";
|
|
7
|
-
import { getStorageTypeHexColor } from "../utils/storageQueryUtils";
|
|
8
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
|
-
// Variable type configurations matching env vars design
|
|
10
|
-
const variableTypeData = [{
|
|
11
|
-
key: "valid",
|
|
12
|
-
label: "Valid Keys",
|
|
13
|
-
description: "Correctly stored and accessible",
|
|
14
|
-
icon: CheckCircle2,
|
|
15
|
-
color: "#10B981",
|
|
16
|
-
textColor: "#10B981",
|
|
17
|
-
bgColor: "rgba(16, 185, 129, 0.1)"
|
|
18
|
-
}, {
|
|
19
|
-
key: "missing",
|
|
20
|
-
label: "Missing Keys",
|
|
21
|
-
description: "Required but not found",
|
|
22
|
-
icon: AlertCircle,
|
|
23
|
-
color: "#EF4444",
|
|
24
|
-
textColor: "#EF4444",
|
|
25
|
-
bgColor: "rgba(239, 68, 68, 0.1)"
|
|
26
|
-
}, {
|
|
27
|
-
key: "wrongValue",
|
|
28
|
-
label: "Wrong Values",
|
|
29
|
-
description: "Stored but incorrect value",
|
|
30
|
-
icon: XCircle,
|
|
31
|
-
color: "#F97316",
|
|
32
|
-
textColor: "#F97316",
|
|
33
|
-
bgColor: "rgba(249, 115, 22, 0.1)"
|
|
34
|
-
}, {
|
|
35
|
-
key: "wrongType",
|
|
36
|
-
label: "Wrong Types",
|
|
37
|
-
description: "Value has incorrect data type",
|
|
38
|
-
icon: XCircle,
|
|
39
|
-
color: "#0891B2",
|
|
40
|
-
textColor: "#0891B2",
|
|
41
|
-
bgColor: "rgba(8, 145, 178, 0.1)"
|
|
42
|
-
}, {
|
|
43
|
-
key: "optional",
|
|
44
|
-
label: "Optional Keys",
|
|
45
|
-
description: "Available but not required",
|
|
46
|
-
icon: Eye,
|
|
47
|
-
color: "#8B5CF6",
|
|
48
|
-
textColor: "#8B5CF6",
|
|
49
|
-
bgColor: "rgba(139, 92, 246, 0.1)"
|
|
50
|
-
}];
|
|
51
|
-
|
|
52
|
-
// Storage type breakdown data
|
|
53
|
-
const storageTypeData = [{
|
|
54
|
-
key: "mmkv",
|
|
55
|
-
label: storageLabels.mmkv,
|
|
56
|
-
description: storageLabels.hasSecure ? "Synchronous key-value storage" : "Storage for this browser tab",
|
|
57
|
-
icon: Database
|
|
58
|
-
}, {
|
|
59
|
-
key: "async",
|
|
60
|
-
label: storageLabels.asyncFull,
|
|
61
|
-
description: storageLabels.hasSecure ? "React Native async storage" : "Persistent storage for this origin",
|
|
62
|
-
icon: Database
|
|
63
|
-
}, {
|
|
64
|
-
key: "secure",
|
|
65
|
-
label: "SecureStorage",
|
|
66
|
-
description: "Encrypted secure storage",
|
|
67
|
-
icon: Shield
|
|
68
|
-
}];
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Storage key stats component following composition principles [[rule3]]
|
|
72
|
-
*
|
|
73
|
-
* Applied principles:
|
|
74
|
-
* - Decompose by Responsibility: Single purpose component for storage stats display
|
|
75
|
-
* - Prefer Composition over Configuration: Reuses patterns from EnvVarStats
|
|
76
|
-
* - Extract Reusable Logic: Shares visualization patterns with env vars
|
|
77
|
-
*/
|
|
78
|
-
export function StorageKeyStatsSection({
|
|
79
|
-
stats
|
|
80
|
-
}) {
|
|
81
|
-
const {
|
|
82
|
-
totalCount,
|
|
83
|
-
missingCount,
|
|
84
|
-
wrongValueCount,
|
|
85
|
-
wrongTypeCount,
|
|
86
|
-
presentRequiredCount,
|
|
87
|
-
optionalCount,
|
|
88
|
-
mmkvCount,
|
|
89
|
-
asyncCount,
|
|
90
|
-
secureCount
|
|
91
|
-
} = stats;
|
|
92
|
-
|
|
93
|
-
// If no storage keys at all, show minimal stats
|
|
94
|
-
if (totalCount === 0) {
|
|
95
|
-
return /*#__PURE__*/_jsxs(View, {
|
|
96
|
-
style: styles.statsContainer,
|
|
97
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
98
|
-
style: styles.sectionTitle,
|
|
99
|
-
children: "STORAGE BREAKDOWN"
|
|
100
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
101
|
-
style: styles.emptyState,
|
|
102
|
-
children: /*#__PURE__*/_jsx(Text, {
|
|
103
|
-
style: styles.emptyStateText,
|
|
104
|
-
children: "No storage keys detected"
|
|
105
|
-
})
|
|
106
|
-
})]
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
return /*#__PURE__*/_jsxs(View, {
|
|
110
|
-
style: styles.statsContainer,
|
|
111
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
112
|
-
style: styles.breakdownSection,
|
|
113
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
114
|
-
style: styles.sectionTitle,
|
|
115
|
-
children: "KEY STATUS BREAKDOWN"
|
|
116
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
117
|
-
style: styles.breakdownList,
|
|
118
|
-
children: variableTypeData.map(item => {
|
|
119
|
-
let count = 0;
|
|
120
|
-
let shouldShow = false;
|
|
121
|
-
switch (item.key) {
|
|
122
|
-
case "valid":
|
|
123
|
-
count = presentRequiredCount;
|
|
124
|
-
shouldShow = count > 0;
|
|
125
|
-
break;
|
|
126
|
-
case "missing":
|
|
127
|
-
count = missingCount;
|
|
128
|
-
shouldShow = count > 0;
|
|
129
|
-
break;
|
|
130
|
-
case "wrongValue":
|
|
131
|
-
count = wrongValueCount;
|
|
132
|
-
shouldShow = count > 0;
|
|
133
|
-
break;
|
|
134
|
-
case "wrongType":
|
|
135
|
-
count = wrongTypeCount;
|
|
136
|
-
shouldShow = count > 0;
|
|
137
|
-
break;
|
|
138
|
-
case "optional":
|
|
139
|
-
count = optionalCount;
|
|
140
|
-
shouldShow = count > 0;
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
if (!shouldShow) return null;
|
|
144
|
-
const percentage = totalCount > 0 ? (count / totalCount * 100).toFixed(1) : "0";
|
|
145
|
-
const IconComponent = item.icon;
|
|
146
|
-
return /*#__PURE__*/_jsx(View, {
|
|
147
|
-
style: styles.breakdownItem,
|
|
148
|
-
children: /*#__PURE__*/_jsxs(View, {
|
|
149
|
-
style: styles.breakdownItemRow,
|
|
150
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
151
|
-
style: styles.breakdownItemLeft,
|
|
152
|
-
children: [/*#__PURE__*/_jsx(View, {
|
|
153
|
-
style: [styles.breakdownIcon, {
|
|
154
|
-
backgroundColor: item.bgColor
|
|
155
|
-
}],
|
|
156
|
-
children: /*#__PURE__*/_jsx(IconComponent, {
|
|
157
|
-
size: 14,
|
|
158
|
-
color: item.color
|
|
159
|
-
})
|
|
160
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
161
|
-
style: styles.breakdownItemInfo,
|
|
162
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
163
|
-
style: styles.breakdownItemLabel,
|
|
164
|
-
children: item.label
|
|
165
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
166
|
-
style: styles.breakdownItemDesc,
|
|
167
|
-
children: item.description
|
|
168
|
-
})]
|
|
169
|
-
})]
|
|
170
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
171
|
-
style: styles.breakdownItemRight,
|
|
172
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
173
|
-
style: [styles.breakdownCount, {
|
|
174
|
-
color: item.textColor
|
|
175
|
-
}],
|
|
176
|
-
children: count
|
|
177
|
-
}), /*#__PURE__*/_jsxs(Text, {
|
|
178
|
-
style: styles.breakdownPercentage,
|
|
179
|
-
children: [percentage, "%"]
|
|
180
|
-
})]
|
|
181
|
-
})]
|
|
182
|
-
})
|
|
183
|
-
}, item.key);
|
|
184
|
-
})
|
|
185
|
-
})]
|
|
186
|
-
}), (mmkvCount > 0 || asyncCount > 0 || secureCount > 0) && /*#__PURE__*/_jsxs(View, {
|
|
187
|
-
style: styles.breakdownSection,
|
|
188
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
189
|
-
style: styles.sectionTitle,
|
|
190
|
-
children: "STORAGE TYPE BREAKDOWN"
|
|
191
|
-
}), /*#__PURE__*/_jsx(View, {
|
|
192
|
-
style: styles.breakdownList,
|
|
193
|
-
children: storageTypeData.map(item => {
|
|
194
|
-
let count = 0;
|
|
195
|
-
let shouldShow = false;
|
|
196
|
-
switch (item.key) {
|
|
197
|
-
case "mmkv":
|
|
198
|
-
count = mmkvCount;
|
|
199
|
-
shouldShow = count > 0;
|
|
200
|
-
break;
|
|
201
|
-
case "async":
|
|
202
|
-
count = asyncCount;
|
|
203
|
-
shouldShow = count > 0;
|
|
204
|
-
break;
|
|
205
|
-
case "secure":
|
|
206
|
-
count = secureCount;
|
|
207
|
-
shouldShow = count > 0;
|
|
208
|
-
break;
|
|
209
|
-
}
|
|
210
|
-
if (!shouldShow) return null;
|
|
211
|
-
const percentage = totalCount > 0 ? (count / totalCount * 100).toFixed(1) : "0";
|
|
212
|
-
const IconComponent = item.icon;
|
|
213
|
-
const storageColor = getStorageTypeHexColor(item.key);
|
|
214
|
-
return /*#__PURE__*/_jsx(View, {
|
|
215
|
-
style: styles.breakdownItem,
|
|
216
|
-
children: /*#__PURE__*/_jsxs(View, {
|
|
217
|
-
style: styles.breakdownItemRow,
|
|
218
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
219
|
-
style: styles.breakdownItemLeft,
|
|
220
|
-
children: [/*#__PURE__*/_jsx(View, {
|
|
221
|
-
style: [styles.breakdownIcon, {
|
|
222
|
-
backgroundColor: `${storageColor}15`
|
|
223
|
-
}],
|
|
224
|
-
children: /*#__PURE__*/_jsx(IconComponent, {
|
|
225
|
-
size: 14,
|
|
226
|
-
color: storageColor
|
|
227
|
-
})
|
|
228
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
229
|
-
style: styles.breakdownItemInfo,
|
|
230
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
231
|
-
style: styles.breakdownItemLabel,
|
|
232
|
-
children: item.label
|
|
233
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
234
|
-
style: styles.breakdownItemDesc,
|
|
235
|
-
children: item.description
|
|
236
|
-
})]
|
|
237
|
-
})]
|
|
238
|
-
}), /*#__PURE__*/_jsxs(View, {
|
|
239
|
-
style: styles.breakdownItemRight,
|
|
240
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
241
|
-
style: [styles.breakdownCount, {
|
|
242
|
-
color: storageColor
|
|
243
|
-
}],
|
|
244
|
-
children: count
|
|
245
|
-
}), /*#__PURE__*/_jsxs(Text, {
|
|
246
|
-
style: styles.breakdownPercentage,
|
|
247
|
-
children: [percentage, "%"]
|
|
248
|
-
})]
|
|
249
|
-
})]
|
|
250
|
-
})
|
|
251
|
-
}, item.key);
|
|
252
|
-
})
|
|
253
|
-
})]
|
|
254
|
-
})]
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
const styles = StyleSheet.create({
|
|
258
|
-
statsContainer: {
|
|
259
|
-
marginBottom: 24,
|
|
260
|
-
backgroundColor: night.color.surface,
|
|
261
|
-
borderRadius: 8,
|
|
262
|
-
padding: 16,
|
|
263
|
-
borderWidth: 1,
|
|
264
|
-
borderColor: night.color.border
|
|
265
|
-
},
|
|
266
|
-
// Section titles
|
|
267
|
-
sectionTitle: {
|
|
268
|
-
color: night.color.textSecondary,
|
|
269
|
-
fontSize: 12,
|
|
270
|
-
fontWeight: "500",
|
|
271
|
-
marginBottom: 16,
|
|
272
|
-
textTransform: "uppercase",
|
|
273
|
-
letterSpacing: 0.5
|
|
274
|
-
},
|
|
275
|
-
// Breakdown section
|
|
276
|
-
breakdownSection: {
|
|
277
|
-
gap: 12,
|
|
278
|
-
marginBottom: 20
|
|
279
|
-
},
|
|
280
|
-
breakdownList: {
|
|
281
|
-
gap: 12
|
|
282
|
-
},
|
|
283
|
-
breakdownItem: {
|
|
284
|
-
backgroundColor: night.color.surfaceElevated,
|
|
285
|
-
padding: 12,
|
|
286
|
-
borderRadius: 8,
|
|
287
|
-
borderWidth: 1,
|
|
288
|
-
borderColor: night.color.border
|
|
289
|
-
},
|
|
290
|
-
breakdownItemRow: {
|
|
291
|
-
flexDirection: "row",
|
|
292
|
-
alignItems: "center",
|
|
293
|
-
justifyContent: "space-between"
|
|
294
|
-
},
|
|
295
|
-
breakdownItemLeft: {
|
|
296
|
-
flexDirection: "row",
|
|
297
|
-
alignItems: "center",
|
|
298
|
-
gap: 12,
|
|
299
|
-
flex: 1,
|
|
300
|
-
minWidth: 0
|
|
301
|
-
},
|
|
302
|
-
breakdownIcon: {
|
|
303
|
-
padding: 8,
|
|
304
|
-
borderRadius: 8
|
|
305
|
-
},
|
|
306
|
-
breakdownItemInfo: {
|
|
307
|
-
flex: 1,
|
|
308
|
-
minWidth: 0
|
|
309
|
-
},
|
|
310
|
-
breakdownItemLabel: {
|
|
311
|
-
color: night.color.text,
|
|
312
|
-
fontSize: 14,
|
|
313
|
-
fontWeight: "500"
|
|
314
|
-
},
|
|
315
|
-
breakdownItemDesc: {
|
|
316
|
-
color: night.color.textSecondary,
|
|
317
|
-
fontSize: 12
|
|
318
|
-
},
|
|
319
|
-
breakdownItemRight: {
|
|
320
|
-
alignItems: "flex-end"
|
|
321
|
-
},
|
|
322
|
-
breakdownCount: {
|
|
323
|
-
fontSize: 16,
|
|
324
|
-
fontWeight: "600"
|
|
325
|
-
},
|
|
326
|
-
breakdownPercentage: {
|
|
327
|
-
color: night.color.textTertiary,
|
|
328
|
-
fontSize: 10
|
|
329
|
-
},
|
|
330
|
-
// Empty state
|
|
331
|
-
emptyState: {
|
|
332
|
-
padding: 16,
|
|
333
|
-
backgroundColor: night.color.surfaceElevated,
|
|
334
|
-
borderRadius: 6,
|
|
335
|
-
alignItems: "center"
|
|
336
|
-
},
|
|
337
|
-
emptyStateText: {
|
|
338
|
-
color: night.color.textTertiary,
|
|
339
|
-
fontSize: 11,
|
|
340
|
-
textAlign: "center"
|
|
341
|
-
}
|
|
342
|
-
});
|
|
1
|
+
"use strict";import{storageLabels as d}from"../utils/storageLabels";import{View as r,Text as a,StyleSheet as T}from"react-native";import{AlertCircle as R,CheckCircle2 as v,XCircle as w,Eye as E,Database as m,Shield as B}from"@buoy-gg/shared-ui";import{night as i}from"@buoy-gg/shared-ui";import{getStorageTypeHexColor as W}from"../utils/storageQueryUtils";import{jsx as t,jsxs as l}from"react/jsx-runtime";const D=[{key:"valid",label:"Valid Keys",description:"Correctly stored and accessible",icon:v,color:"#10B981",textColor:"#10B981",bgColor:"rgba(16, 185, 129, 0.1)"},{key:"missing",label:"Missing Keys",description:"Required but not found",icon:R,color:"#EF4444",textColor:"#EF4444",bgColor:"rgba(239, 68, 68, 0.1)"},{key:"wrongValue",label:"Wrong Values",description:"Stored but incorrect value",icon:w,color:"#F97316",textColor:"#F97316",bgColor:"rgba(249, 115, 22, 0.1)"},{key:"wrongType",label:"Wrong Types",description:"Value has incorrect data type",icon:w,color:"#0891B2",textColor:"#0891B2",bgColor:"rgba(8, 145, 178, 0.1)"},{key:"optional",label:"Optional Keys",description:"Available but not required",icon:E,color:"#8B5CF6",textColor:"#8B5CF6",bgColor:"rgba(139, 92, 246, 0.1)"}];const L=[{key:"mmkv",label:d.mmkv,description:d.hasSecure?"Synchronous key-value storage":"Storage for this browser tab",icon:m},{key:"async",label:d.asyncFull,description:d.hasSecure?"React Native async storage":"Persistent storage for this origin",icon:m},{key:"secure",label:"SecureStorage",description:"Encrypted secure storage",icon:B}];export function StorageKeyStatsSection({stats:p}){const{totalCount:s,missingCount:C,wrongValueCount:f,wrongTypeCount:S,presentRequiredCount:I,optionalCount:x,mmkvCount:k,asyncCount:u,secureCount:h}=p;if(s===0){return l(r,{style:e.statsContainer,children:[t(a,{style:e.sectionTitle,children:"STORAGE BREAKDOWN"}),t(r,{style:e.emptyState,children:t(a,{style:e.emptyStateText,children:"No storage keys detected"})})]})}return l(r,{style:e.statsContainer,children:[l(r,{style:e.breakdownSection,children:[t(a,{style:e.sectionTitle,children:"KEY STATUS BREAKDOWN"}),t(r,{style:e.breakdownList,children:D.map(n=>{let o=0;let c=false;switch(n.key){case"valid":o=I;c=o>0;break;case"missing":o=C;c=o>0;break;case"wrongValue":o=f;c=o>0;break;case"wrongType":o=S;c=o>0;break;case"optional":o=x;c=o>0;break}if(!c)return null;const b=s>0?(o/s*100).toFixed(1):"0";const y=n.icon;return t(r,{style:e.breakdownItem,children:l(r,{style:e.breakdownItemRow,children:[l(r,{style:e.breakdownItemLeft,children:[t(r,{style:[e.breakdownIcon,{backgroundColor:n.bgColor}],children:t(y,{size:14,color:n.color})}),l(r,{style:e.breakdownItemInfo,children:[t(a,{style:e.breakdownItemLabel,children:n.label}),t(a,{style:e.breakdownItemDesc,children:n.description})]})]}),l(r,{style:e.breakdownItemRight,children:[t(a,{style:[e.breakdownCount,{color:n.textColor}],children:o}),l(a,{style:e.breakdownPercentage,children:[b,"%"]})]})]})},n.key)})})]}),(k>0||u>0||h>0)&&l(r,{style:e.breakdownSection,children:[t(a,{style:e.sectionTitle,children:"STORAGE TYPE BREAKDOWN"}),t(r,{style:e.breakdownList,children:L.map(n=>{let o=0;let c=false;switch(n.key){case"mmkv":o=k;c=o>0;break;case"async":o=u;c=o>0;break;case"secure":o=h;c=o>0;break}if(!c)return null;const b=s>0?(o/s*100).toFixed(1):"0";const y=n.icon;const g=W(n.key);return t(r,{style:e.breakdownItem,children:l(r,{style:e.breakdownItemRow,children:[l(r,{style:e.breakdownItemLeft,children:[t(r,{style:[e.breakdownIcon,{backgroundColor:`${g}15`}],children:t(y,{size:14,color:g})}),l(r,{style:e.breakdownItemInfo,children:[t(a,{style:e.breakdownItemLabel,children:n.label}),t(a,{style:e.breakdownItemDesc,children:n.description})]})]}),l(r,{style:e.breakdownItemRight,children:[t(a,{style:[e.breakdownCount,{color:g}],children:o}),l(a,{style:e.breakdownPercentage,children:[b,"%"]})]})]})},n.key)})})]})]})}const e=T.create({statsContainer:{marginBottom:24,backgroundColor:i.color.surface,borderRadius:8,padding:16,borderWidth:1,borderColor:i.color.border},sectionTitle:{color:i.color.textSecondary,fontSize:12,fontWeight:"500",marginBottom:16,textTransform:"uppercase",letterSpacing:.5},breakdownSection:{gap:12,marginBottom:20},breakdownList:{gap:12},breakdownItem:{backgroundColor:i.color.surfaceElevated,padding:12,borderRadius:8,borderWidth:1,borderColor:i.color.border},breakdownItemRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between"},breakdownItemLeft:{flexDirection:"row",alignItems:"center",gap:12,flex:1,minWidth:0},breakdownIcon:{padding:8,borderRadius:8},breakdownItemInfo:{flex:1,minWidth:0},breakdownItemLabel:{color:i.color.text,fontSize:14,fontWeight:"500"},breakdownItemDesc:{color:i.color.textSecondary,fontSize:12},breakdownItemRight:{alignItems:"flex-end"},breakdownCount:{fontSize:16,fontWeight:"600"},breakdownPercentage:{color:i.color.textTertiary,fontSize:10},emptyState:{padding:16,backgroundColor:i.color.surfaceElevated,borderRadius:6,alignItems:"center"},emptyStateText:{color:i.color.textTertiary,fontSize:11,textAlign:"center"}});
|