@buoy-gg/storage 7.0.3 → 7.0.5
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/lib/commonjs/index.js +77 -1
- package/lib/commonjs/storage/components/DiffViewer/TreeDiffViewer.js +10 -3
- package/lib/commonjs/storage/components/DiffViewer/modes/ThemedSplitView.js +26 -8
- package/lib/commonjs/storage/components/GameUIStorageBrowser.js +263 -115
- package/lib/commonjs/storage/components/GameUIStorageStats.js +7 -7
- package/lib/commonjs/storage/components/MMKVInstanceInfoPanel.js +1 -1
- package/lib/commonjs/storage/components/MMKVInstanceSelector.js +1 -1
- package/lib/commonjs/storage/components/SelectionActionBar.js +2 -36
- package/lib/commonjs/storage/components/StorageActions.js +6 -6
- package/lib/commonjs/storage/components/StorageBrowserMode.js +16 -2
- package/lib/commonjs/storage/components/StorageEventDetailContent.js +106 -149
- package/lib/commonjs/storage/components/StorageEventListener.js +13 -13
- package/lib/commonjs/storage/components/StorageFilterCards.js +13 -135
- package/lib/commonjs/storage/components/StorageKeyCard.js +1 -1
- package/lib/commonjs/storage/components/StorageKeyEditorScreen.js +392 -0
- package/lib/commonjs/storage/components/StorageKeyRow.js +53 -15
- package/lib/commonjs/storage/components/StorageKeySection.js +10 -4
- package/lib/commonjs/storage/components/StorageKeyStats.js +10 -10
- package/lib/commonjs/storage/components/StorageModalWithTabs.js +272 -129
- package/lib/commonjs/storage/components/StorageScalarKeyEditor.js +46 -0
- package/lib/commonjs/storage/components/StorageTypeFilterBar.js +141 -0
- package/lib/commonjs/storage/components/StorageValueEditModal.js +361 -0
- package/lib/commonjs/storage/hooks/useKeyEditor.js +104 -0
- package/lib/commonjs/storage/hooks/useMeasuredWidth.js +74 -0
- package/lib/commonjs/storage/hooks/useSecureStoreKeys.js +70 -15
- package/lib/commonjs/storage/hooks/useTreeDraft.js +107 -0
- package/lib/commonjs/storage/index.js +29 -0
- package/lib/commonjs/storage/stores/storageEventStore.js +4 -2
- package/lib/commonjs/storage/sync/storageSyncAdapter.js +125 -3
- package/lib/commonjs/storage/utils/AsyncStorageListener.js +76 -12
- package/lib/commonjs/storage/utils/MMKVInstanceRegistry.js +10 -9
- package/lib/commonjs/storage/utils/MMKVListener.js +40 -4
- package/lib/commonjs/storage/utils/SecureStoreRegistry.js +52 -1
- package/lib/commonjs/storage/utils/deleteStorageKeys.js +53 -0
- package/lib/commonjs/storage/utils/index.js +13 -0
- package/lib/commonjs/storage/utils/lineDiff.js +21 -354
- package/lib/commonjs/storage/utils/setStorageValue.js +218 -0
- package/lib/commonjs/storage/utils/storageBrowserRefresh.js +49 -0
- package/lib/commonjs/storage/utils/storageOps.js +53 -0
- package/lib/commonjs/storage/utils/storageTimeTravelUtils.js +60 -38
- package/lib/commonjs/storage/utils/valueType.js +24 -0
- package/lib/module/index.js +18 -1
- package/lib/module/storage/components/DiffViewer/TreeDiffViewer.js +10 -3
- package/lib/module/storage/components/DiffViewer/modes/ThemedSplitView.js +26 -8
- package/lib/module/storage/components/GameUIStorageBrowser.js +266 -118
- package/lib/module/storage/components/GameUIStorageStats.js +7 -7
- package/lib/module/storage/components/MMKVInstanceInfoPanel.js +1 -1
- package/lib/module/storage/components/MMKVInstanceSelector.js +1 -1
- package/lib/module/storage/components/SelectionActionBar.js +2 -36
- package/lib/module/storage/components/StorageActions.js +7 -7
- package/lib/module/storage/components/StorageBrowserMode.js +16 -2
- package/lib/module/storage/components/StorageEventDetailContent.js +110 -151
- package/lib/module/storage/components/StorageEventListener.js +14 -14
- package/lib/module/storage/components/StorageFilterCards.js +13 -135
- package/lib/module/storage/components/StorageKeyCard.js +1 -1
- package/lib/module/storage/components/StorageKeyEditorScreen.js +388 -0
- package/lib/module/storage/components/StorageKeyRow.js +55 -17
- package/lib/module/storage/components/StorageKeySection.js +11 -5
- package/lib/module/storage/components/StorageKeyStats.js +11 -10
- package/lib/module/storage/components/StorageModalWithTabs.js +272 -130
- package/lib/module/storage/components/StorageScalarKeyEditor.js +42 -0
- package/lib/module/storage/components/StorageTypeFilterBar.js +136 -0
- package/lib/module/storage/components/StorageValueEditModal.js +357 -0
- package/lib/module/storage/hooks/useKeyEditor.js +100 -0
- package/lib/module/storage/hooks/useMeasuredWidth.js +71 -0
- package/lib/module/storage/hooks/useSecureStoreKeys.js +71 -16
- package/lib/module/storage/hooks/useTreeDraft.js +103 -0
- package/lib/module/storage/index.js +3 -0
- package/lib/module/storage/stores/storageEventStore.js +4 -2
- package/lib/module/storage/sync/storageSyncAdapter.js +125 -3
- package/lib/module/storage/utils/AsyncStorageListener.js +76 -12
- package/lib/module/storage/utils/MMKVInstanceRegistry.js +8 -7
- package/lib/module/storage/utils/MMKVListener.js +40 -4
- package/lib/module/storage/utils/SecureStoreRegistry.js +52 -1
- package/lib/module/storage/utils/deleteStorageKeys.js +49 -0
- package/lib/module/storage/utils/index.js +3 -0
- package/lib/module/storage/utils/lineDiff.js +7 -354
- package/lib/module/storage/utils/setStorageValue.js +209 -0
- package/lib/module/storage/utils/storageBrowserRefresh.js +44 -0
- package/lib/module/storage/utils/storageOps.js +46 -0
- package/lib/module/storage/utils/storageTimeTravelUtils.js +61 -40
- package/lib/module/storage/utils/valueType.js +23 -0
- package/lib/typescript/index.d.ts +12 -1
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts +4 -1
- package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts.map +1 -1
- package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts +7 -1
- package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts.map +1 -1
- package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts +27 -1
- package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts.map +1 -1
- package/lib/typescript/storage/components/SelectionActionBar.d.ts.map +1 -1
- package/lib/typescript/storage/components/StorageBrowserMode.d.ts +17 -1
- package/lib/typescript/storage/components/StorageBrowserMode.d.ts.map +1 -1
- package/lib/typescript/storage/components/StorageEventDetailContent.d.ts +4 -1
- package/lib/typescript/storage/components/StorageEventDetailContent.d.ts.map +1 -1
- package/lib/typescript/storage/components/StorageFilterCards.d.ts +9 -3
- package/lib/typescript/storage/components/StorageFilterCards.d.ts.map +1 -1
- package/lib/typescript/storage/components/StorageKeyEditorScreen.d.ts +42 -0
- package/lib/typescript/storage/components/StorageKeyEditorScreen.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageKeyRow.d.ts +17 -0
- package/lib/typescript/storage/components/StorageKeyRow.d.ts.map +1 -1
- package/lib/typescript/storage/components/StorageKeySection.d.ts +7 -1
- package/lib/typescript/storage/components/StorageKeySection.d.ts.map +1 -1
- package/lib/typescript/storage/components/StorageKeyStats.d.ts.map +1 -1
- package/lib/typescript/storage/components/StorageModalWithTabs.d.ts +28 -1
- package/lib/typescript/storage/components/StorageModalWithTabs.d.ts.map +1 -1
- package/lib/typescript/storage/components/StorageScalarKeyEditor.d.ts +24 -0
- package/lib/typescript/storage/components/StorageScalarKeyEditor.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageTypeFilterBar.d.ts +29 -0
- package/lib/typescript/storage/components/StorageTypeFilterBar.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageValueEditModal.d.ts +36 -0
- package/lib/typescript/storage/components/StorageValueEditModal.d.ts.map +1 -0
- package/lib/typescript/storage/hooks/useKeyEditor.d.ts +51 -0
- package/lib/typescript/storage/hooks/useKeyEditor.d.ts.map +1 -0
- package/lib/typescript/storage/hooks/useMeasuredWidth.d.ts +37 -0
- package/lib/typescript/storage/hooks/useMeasuredWidth.d.ts.map +1 -0
- package/lib/typescript/storage/hooks/useSecureStoreKeys.d.ts +8 -1
- package/lib/typescript/storage/hooks/useSecureStoreKeys.d.ts.map +1 -1
- package/lib/typescript/storage/hooks/useTreeDraft.d.ts +67 -0
- package/lib/typescript/storage/hooks/useTreeDraft.d.ts.map +1 -0
- package/lib/typescript/storage/index.d.ts +2 -0
- package/lib/typescript/storage/index.d.ts.map +1 -1
- package/lib/typescript/storage/sync/storageSyncAdapter.d.ts +41 -0
- package/lib/typescript/storage/sync/storageSyncAdapter.d.ts.map +1 -1
- package/lib/typescript/storage/utils/AsyncStorageListener.d.ts +15 -0
- package/lib/typescript/storage/utils/AsyncStorageListener.d.ts.map +1 -1
- package/lib/typescript/storage/utils/MMKVInstanceRegistry.d.ts.map +1 -1
- package/lib/typescript/storage/utils/MMKVListener.d.ts +7 -0
- package/lib/typescript/storage/utils/MMKVListener.d.ts.map +1 -1
- package/lib/typescript/storage/utils/SecureStoreRegistry.d.ts +20 -0
- package/lib/typescript/storage/utils/SecureStoreRegistry.d.ts.map +1 -1
- package/lib/typescript/storage/utils/deleteStorageKeys.d.ts +27 -0
- package/lib/typescript/storage/utils/deleteStorageKeys.d.ts.map +1 -0
- package/lib/typescript/storage/utils/index.d.ts +1 -0
- package/lib/typescript/storage/utils/index.d.ts.map +1 -1
- package/lib/typescript/storage/utils/lineDiff.d.ts +7 -31
- package/lib/typescript/storage/utils/lineDiff.d.ts.map +1 -1
- package/lib/typescript/storage/utils/setStorageValue.d.ts +64 -0
- package/lib/typescript/storage/utils/setStorageValue.d.ts.map +1 -0
- package/lib/typescript/storage/utils/storageBrowserRefresh.d.ts +28 -0
- package/lib/typescript/storage/utils/storageBrowserRefresh.d.ts.map +1 -0
- package/lib/typescript/storage/utils/storageOps.d.ts +25 -0
- package/lib/typescript/storage/utils/storageOps.d.ts.map +1 -0
- package/lib/typescript/storage/utils/storageTimeTravelUtils.d.ts +15 -5
- package/lib/typescript/storage/utils/storageTimeTravelUtils.d.ts.map +1 -1
- package/lib/typescript/storage/utils/valueType.d.ts +13 -0
- package/lib/typescript/storage/utils/valueType.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { View, Text, StyleSheet, TouchableOpacity } from "react-native";
|
|
4
|
+
import { StorageTypeFilterBar } from "./StorageTypeFilterBar";
|
|
4
5
|
import { macOSColors } from "@buoy-gg/shared-ui";
|
|
5
6
|
import { isMMKVAvailable } from "../utils/mmkvAvailability";
|
|
6
7
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -18,7 +19,8 @@ export function StorageFilterCards({
|
|
|
18
19
|
activeFilter = "all",
|
|
19
20
|
onFilterChange,
|
|
20
21
|
activeStorageType = "all",
|
|
21
|
-
onStorageTypeChange
|
|
22
|
+
onStorageTypeChange,
|
|
23
|
+
showStatus = true
|
|
22
24
|
}) {
|
|
23
25
|
// Use tabStats if provided (for filtered counts), otherwise fall back to stats
|
|
24
26
|
const displayStats = tabStats || {
|
|
@@ -32,7 +34,7 @@ export function StorageFilterCards({
|
|
|
32
34
|
};
|
|
33
35
|
return /*#__PURE__*/_jsxs(View, {
|
|
34
36
|
style: styles.container,
|
|
35
|
-
children: [/*#__PURE__*/_jsxs(View, {
|
|
37
|
+
children: [showStatus ? /*#__PURE__*/_jsxs(View, {
|
|
36
38
|
style: styles.filtersRow,
|
|
37
39
|
children: [/*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
38
40
|
style: [styles.filterChip, activeFilter === "all" && [styles.filterChipActive, {
|
|
@@ -86,101 +88,15 @@ export function StorageFilterCards({
|
|
|
86
88
|
children: "Issues"
|
|
87
89
|
})]
|
|
88
90
|
})]
|
|
89
|
-
}), onStorageTypeChange && /*#__PURE__*/
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
onPress: () => onStorageTypeChange?.("all"),
|
|
99
|
-
activeOpacity: 0.8,
|
|
100
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
101
|
-
style: [styles.typePillLabel, activeStorageType === "all" && {
|
|
102
|
-
color: macOSColors.text.primary,
|
|
103
|
-
fontWeight: "600"
|
|
104
|
-
}],
|
|
105
|
-
children: "All Types"
|
|
106
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
107
|
-
style: [styles.typePillValue, activeStorageType === "all" && {
|
|
108
|
-
color: macOSColors.text.primary
|
|
109
|
-
}, activeStorageType !== "all" && {
|
|
110
|
-
color: macOSColors.text.muted
|
|
111
|
-
}],
|
|
112
|
-
children: displayStats.totalCount
|
|
113
|
-
})]
|
|
114
|
-
}), /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
115
|
-
style: [styles.typePill, {
|
|
116
|
-
borderColor: macOSColors.border.default
|
|
117
|
-
}, activeStorageType === "async" && [styles.typePillActive, {
|
|
118
|
-
backgroundColor: macOSColors.semantic.warning + "15",
|
|
119
|
-
borderColor: macOSColors.semantic.warning + "40"
|
|
120
|
-
}]],
|
|
121
|
-
onPress: () => onStorageTypeChange?.("async"),
|
|
122
|
-
activeOpacity: 0.8,
|
|
123
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
124
|
-
style: [styles.typePillLabel, activeStorageType === "async" && {
|
|
125
|
-
color: macOSColors.semantic.warning,
|
|
126
|
-
fontWeight: "600"
|
|
127
|
-
}],
|
|
128
|
-
children: "Async"
|
|
129
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
130
|
-
style: [styles.typePillValue, activeStorageType === "async" ? {
|
|
131
|
-
color: macOSColors.semantic.warning
|
|
132
|
-
} : {
|
|
133
|
-
color: macOSColors.text.muted
|
|
134
|
-
}],
|
|
135
|
-
children: displayStats.asyncCount
|
|
136
|
-
})]
|
|
137
|
-
}), /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
138
|
-
style: [styles.typePill, {
|
|
139
|
-
borderColor: macOSColors.border.default
|
|
140
|
-
}, activeStorageType === "mmkv" && [styles.typePillActive, {
|
|
141
|
-
backgroundColor: macOSColors.semantic.info + "15",
|
|
142
|
-
borderColor: macOSColors.semantic.info + "40"
|
|
143
|
-
}]],
|
|
144
|
-
onPress: () => onStorageTypeChange?.("mmkv"),
|
|
145
|
-
activeOpacity: 0.8,
|
|
146
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
147
|
-
style: [styles.typePillLabel, activeStorageType === "mmkv" && {
|
|
148
|
-
color: macOSColors.semantic.info,
|
|
149
|
-
fontWeight: "600"
|
|
150
|
-
}],
|
|
151
|
-
children: "MMKV"
|
|
152
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
153
|
-
style: [styles.typePillValue, activeStorageType === "mmkv" ? {
|
|
154
|
-
color: macOSColors.semantic.info
|
|
155
|
-
} : {
|
|
156
|
-
color: macOSColors.text.muted
|
|
157
|
-
}],
|
|
158
|
-
children: displayStats.mmkvCount
|
|
159
|
-
})]
|
|
160
|
-
}), /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
161
|
-
style: [styles.typePill, {
|
|
162
|
-
borderColor: macOSColors.border.default
|
|
163
|
-
}, activeStorageType === "secure" && [styles.typePillActive, {
|
|
164
|
-
backgroundColor: macOSColors.semantic.success + "15",
|
|
165
|
-
borderColor: macOSColors.semantic.success + "40"
|
|
166
|
-
}]],
|
|
167
|
-
onPress: () => onStorageTypeChange?.("secure"),
|
|
168
|
-
activeOpacity: 0.8,
|
|
169
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
170
|
-
style: [styles.typePillLabel, activeStorageType === "secure" && {
|
|
171
|
-
color: macOSColors.semantic.success,
|
|
172
|
-
fontWeight: "600"
|
|
173
|
-
}],
|
|
174
|
-
children: "Secure"
|
|
175
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
176
|
-
style: [styles.typePillValue, activeStorageType === "secure" ? {
|
|
177
|
-
color: macOSColors.semantic.success
|
|
178
|
-
} : {
|
|
179
|
-
color: macOSColors.text.muted
|
|
180
|
-
}],
|
|
181
|
-
children: displayStats.secureCount
|
|
182
|
-
})]
|
|
183
|
-
})]
|
|
91
|
+
}) : null, onStorageTypeChange && /*#__PURE__*/_jsx(StorageTypeFilterBar, {
|
|
92
|
+
active: activeStorageType,
|
|
93
|
+
onChange: onStorageTypeChange,
|
|
94
|
+
counts: {
|
|
95
|
+
all: displayStats.totalCount,
|
|
96
|
+
async: displayStats.asyncCount,
|
|
97
|
+
mmkv: displayStats.mmkvCount,
|
|
98
|
+
secure: displayStats.secureCount
|
|
99
|
+
}
|
|
184
100
|
})]
|
|
185
101
|
});
|
|
186
102
|
}
|
|
@@ -298,43 +214,5 @@ const styles = StyleSheet.create({
|
|
|
298
214
|
fontWeight: "600",
|
|
299
215
|
fontFamily: "monospace",
|
|
300
216
|
lineHeight: 20
|
|
301
|
-
},
|
|
302
|
-
// Storage type pills
|
|
303
|
-
typesRow: {
|
|
304
|
-
flexDirection: "row",
|
|
305
|
-
gap: 8,
|
|
306
|
-
marginTop: 2
|
|
307
|
-
},
|
|
308
|
-
typePill: {
|
|
309
|
-
flex: 1,
|
|
310
|
-
backgroundColor: macOSColors.background.input + "80",
|
|
311
|
-
borderRadius: 8,
|
|
312
|
-
borderWidth: 1,
|
|
313
|
-
borderColor: macOSColors.border.default + "30",
|
|
314
|
-
paddingVertical: 6,
|
|
315
|
-
paddingHorizontal: 8,
|
|
316
|
-
alignItems: "center",
|
|
317
|
-
justifyContent: "center",
|
|
318
|
-
minHeight: 32
|
|
319
|
-
},
|
|
320
|
-
typePillActive: {
|
|
321
|
-
borderWidth: 1,
|
|
322
|
-
transform: [{
|
|
323
|
-
scale: 1.005
|
|
324
|
-
}]
|
|
325
|
-
},
|
|
326
|
-
typePillLabel: {
|
|
327
|
-
fontSize: 9,
|
|
328
|
-
color: macOSColors.text.secondary,
|
|
329
|
-
textTransform: "uppercase",
|
|
330
|
-
letterSpacing: 0.4,
|
|
331
|
-
fontWeight: "500",
|
|
332
|
-
marginBottom: 1
|
|
333
|
-
},
|
|
334
|
-
typePillValue: {
|
|
335
|
-
fontSize: 12,
|
|
336
|
-
fontWeight: "600",
|
|
337
|
-
fontFamily: "monospace",
|
|
338
|
-
lineHeight: 14
|
|
339
217
|
}
|
|
340
218
|
});
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Editing a key, on a screen of its own.
|
|
5
|
+
*
|
|
6
|
+
* Editing used to happen inside the expanded card in the key list: a tree a few
|
|
7
|
+
* rows tall, an action bar wrapped onto three lines, and the rest of the list
|
|
8
|
+
* still scrolling underneath. Every control was competing for the same ~200px.
|
|
9
|
+
*
|
|
10
|
+
* So the card now offers ONE edit button and the actual work happens here, with
|
|
11
|
+
* the whole viewport: the tree gets the height, the six structural actions get
|
|
12
|
+
* thumb-sized tiles docked at the bottom where they're always in the same
|
|
13
|
+
* place, and manual JSON editing — the escape hatch, not the main path — moves
|
|
14
|
+
* to a single button in the top-right corner.
|
|
15
|
+
*
|
|
16
|
+
* Typing a value happens in a modal pinned to the top of the screen, over the
|
|
17
|
+
* tree rather than instead of it — see {@link StorageValueEditModal}.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { useMemo } from "react";
|
|
21
|
+
import { Alert, ScrollView, StyleSheet, Text, TouchableOpacity, View } from "react-native";
|
|
22
|
+
import { macOSColors, FileJson, PillBadge, useSafeAreaInsets, X } from "@buoy-gg/shared-ui";
|
|
23
|
+
import { DataViewer, DataTreeActionDock, getAtPath } from "@buoy-gg/shared-ui/dataViewer";
|
|
24
|
+
import { useKeyEditor } from "../hooks/useKeyEditor";
|
|
25
|
+
import { StorageValueEditModal } from "./StorageValueEditModal";
|
|
26
|
+
import { StorageScalarKeyEditor } from "./StorageScalarKeyEditor";
|
|
27
|
+
import { getStorageTypeLabel } from "../utils/storageQueryUtils";
|
|
28
|
+
import { parseStorageValue } from "../utils/valueType";
|
|
29
|
+
|
|
30
|
+
/** Props once the value has been un-stringified — see `parseStorageValue`. */
|
|
31
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
32
|
+
/**
|
|
33
|
+
* A container and a scalar are different editors, not one editor with a flag.
|
|
34
|
+
*
|
|
35
|
+
* A tree of one row is not a tree, so a scalar key skips the whole structural
|
|
36
|
+
* editor and gets just the value modal. Splitting here keeps each editor's
|
|
37
|
+
* state to what it actually needs — see {@link StorageScalarKeyEditor}.
|
|
38
|
+
*/
|
|
39
|
+
export function StorageKeyEditorScreen(props) {
|
|
40
|
+
// Memo justified: this is a JSON.parse of the whole stored value, and the
|
|
41
|
+
// browser underneath re-renders on every storage event the app emits.
|
|
42
|
+
const raw = props.storageKey.value;
|
|
43
|
+
const value = useMemo(() => parseStorageValue(raw), [raw]);
|
|
44
|
+
return value !== null && typeof value === "object" ? /*#__PURE__*/_jsx(StorageTreeEditor, {
|
|
45
|
+
...props,
|
|
46
|
+
value: value
|
|
47
|
+
}) : /*#__PURE__*/_jsx(StorageScalarKeyEditor, {
|
|
48
|
+
storageKey: props.storageKey,
|
|
49
|
+
value: value,
|
|
50
|
+
onSave: props.onSave,
|
|
51
|
+
onClose: props.onClose
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* ------------------------------------------------------------------ *
|
|
56
|
+
* Containers — tree + structural actions, buffered into a draft.
|
|
57
|
+
* ------------------------------------------------------------------ */
|
|
58
|
+
|
|
59
|
+
function StorageTreeEditor({
|
|
60
|
+
storageKey,
|
|
61
|
+
value,
|
|
62
|
+
onSave,
|
|
63
|
+
onClose,
|
|
64
|
+
applySafeAreaInset
|
|
65
|
+
}) {
|
|
66
|
+
const insets = useSafeAreaInsets();
|
|
67
|
+
const bottomInset = applySafeAreaInset ? insets.bottom : 0;
|
|
68
|
+
const editor = useKeyEditor({
|
|
69
|
+
value,
|
|
70
|
+
save: onSave,
|
|
71
|
+
onClose,
|
|
72
|
+
confirmDiscard: choices => Alert.alert("Unsaved changes", `"${storageKey.key}" has edits that haven't been written to the device.`, [{
|
|
73
|
+
text: "Keep editing",
|
|
74
|
+
style: "cancel"
|
|
75
|
+
}, {
|
|
76
|
+
text: "Discard",
|
|
77
|
+
style: "destructive",
|
|
78
|
+
onPress: choices.discard
|
|
79
|
+
}, {
|
|
80
|
+
text: "Save",
|
|
81
|
+
onPress: choices.save
|
|
82
|
+
}])
|
|
83
|
+
});
|
|
84
|
+
const {
|
|
85
|
+
draft,
|
|
86
|
+
selection,
|
|
87
|
+
valuePath
|
|
88
|
+
} = editor;
|
|
89
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
90
|
+
style: styles.screen,
|
|
91
|
+
children: [/*#__PURE__*/_jsx(EditorHeader, {
|
|
92
|
+
storageKey: storageKey,
|
|
93
|
+
state: draft.isSaving ? "Saving…" : draft.isDirty ? "Draft · unsaved" : "In sync with device",
|
|
94
|
+
dirty: draft.isDirty,
|
|
95
|
+
onClose: editor.requestClose
|
|
96
|
+
// Manual editing of the WHOLE value — everything else on this screen is
|
|
97
|
+
// structural, so raw JSON gets a corner rather than a tile.
|
|
98
|
+
,
|
|
99
|
+
onRaw: editor.openRawEditor
|
|
100
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
101
|
+
style: styles.metaRow,
|
|
102
|
+
children: [/*#__PURE__*/_jsx(PillBadge, {
|
|
103
|
+
color: storageTypeColor(storageKey.storageType),
|
|
104
|
+
children: getStorageTypeLabel(storageKey.storageType)
|
|
105
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
106
|
+
style: styles.metaText,
|
|
107
|
+
children: summarize(draft.value)
|
|
108
|
+
})]
|
|
109
|
+
}), /*#__PURE__*/_jsxs(ScrollView, {
|
|
110
|
+
style: styles.treeScroll,
|
|
111
|
+
contentContainerStyle: styles.treeContent,
|
|
112
|
+
keyboardShouldPersistTaps: "handled",
|
|
113
|
+
children: [/*#__PURE__*/_jsx(View, {
|
|
114
|
+
style: styles.treeCard,
|
|
115
|
+
children: /*#__PURE__*/_jsx(DataViewer, {
|
|
116
|
+
data: draft.value,
|
|
117
|
+
title: "",
|
|
118
|
+
rawMode: true,
|
|
119
|
+
initialExpanded: true
|
|
120
|
+
// Type filtering is a READING aid: the filtered view is a
|
|
121
|
+
// projection whose row paths don't address the real document, so
|
|
122
|
+
// the explorer stops reporting selection while one is active. An
|
|
123
|
+
// editor whose actions silently go dead isn't worth the filter.
|
|
124
|
+
,
|
|
125
|
+
showTypeFilter: false,
|
|
126
|
+
onSelectionChange: editor.setSelection,
|
|
127
|
+
selectPath: draft.selectPath,
|
|
128
|
+
onRequestInlineEdit: sel => editor.openValueEditor(sel.path)
|
|
129
|
+
})
|
|
130
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
131
|
+
style: styles.treeHint,
|
|
132
|
+
children: "Tap a row to select it \xB7 double-tap to edit its value"
|
|
133
|
+
})]
|
|
134
|
+
}), draft.error ? /*#__PURE__*/_jsx(Text, {
|
|
135
|
+
style: styles.error,
|
|
136
|
+
numberOfLines: 3,
|
|
137
|
+
children: draft.error
|
|
138
|
+
}) : null, /*#__PURE__*/_jsxs(View, {
|
|
139
|
+
style: [styles.footer, {
|
|
140
|
+
paddingBottom: bottomInset
|
|
141
|
+
}],
|
|
142
|
+
children: [/*#__PURE__*/_jsx(DataTreeActionDock, {
|
|
143
|
+
root: draft.value,
|
|
144
|
+
selection: selection,
|
|
145
|
+
onEdit: draft.apply,
|
|
146
|
+
onSelectPath: draft.selectAt
|
|
147
|
+
// Booleans never reach this — the dock applies their flip directly.
|
|
148
|
+
,
|
|
149
|
+
onEditValue: () => editor.openValueEditor(selection?.path ?? [])
|
|
150
|
+
}), draft.isDirty ? /*#__PURE__*/_jsxs(View, {
|
|
151
|
+
style: styles.commitRow,
|
|
152
|
+
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
153
|
+
onPress: draft.discard,
|
|
154
|
+
disabled: draft.isSaving,
|
|
155
|
+
accessibilityLabel: "Discard changes",
|
|
156
|
+
style: styles.discardButton,
|
|
157
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
158
|
+
style: styles.discardText,
|
|
159
|
+
children: "Discard"
|
|
160
|
+
})
|
|
161
|
+
}), /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
162
|
+
onPress: editor.saveAndClose,
|
|
163
|
+
disabled: draft.isSaving,
|
|
164
|
+
accessibilityLabel: "Save changes",
|
|
165
|
+
style: [styles.saveButton, draft.isSaving && styles.saveDisabled],
|
|
166
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
167
|
+
style: styles.saveText,
|
|
168
|
+
children: draft.isSaving ? "Saving…" : "Save changes"
|
|
169
|
+
})
|
|
170
|
+
})]
|
|
171
|
+
}) : null]
|
|
172
|
+
}), valuePath ? /*#__PURE__*/_jsx(StorageValueEditModal, {
|
|
173
|
+
path: valuePath,
|
|
174
|
+
value: getAtPath(draft.value, valuePath),
|
|
175
|
+
onSave: editor.applyValue,
|
|
176
|
+
onCancel: editor.closeValueEditor
|
|
177
|
+
// It only reaches the draft here — the single write happens on Save.
|
|
178
|
+
,
|
|
179
|
+
saveLabel: "Apply"
|
|
180
|
+
}) : null]
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* ------------------------------------------------------------------ *
|
|
185
|
+
* Shared pieces
|
|
186
|
+
* ------------------------------------------------------------------ */
|
|
187
|
+
|
|
188
|
+
function EditorHeader({
|
|
189
|
+
storageKey,
|
|
190
|
+
state,
|
|
191
|
+
dirty,
|
|
192
|
+
onClose,
|
|
193
|
+
onRaw
|
|
194
|
+
}) {
|
|
195
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
196
|
+
style: styles.header,
|
|
197
|
+
children: [/*#__PURE__*/_jsx(TouchableOpacity, {
|
|
198
|
+
onPress: onClose,
|
|
199
|
+
accessibilityLabel: "Close editor",
|
|
200
|
+
style: styles.headerButton,
|
|
201
|
+
hitSlop: {
|
|
202
|
+
top: 8,
|
|
203
|
+
bottom: 8,
|
|
204
|
+
left: 8,
|
|
205
|
+
right: 8
|
|
206
|
+
},
|
|
207
|
+
children: /*#__PURE__*/_jsx(X, {
|
|
208
|
+
size: 16,
|
|
209
|
+
color: macOSColors.text.secondary
|
|
210
|
+
})
|
|
211
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
212
|
+
style: styles.headerTitle,
|
|
213
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
214
|
+
style: styles.headerKey,
|
|
215
|
+
numberOfLines: 1,
|
|
216
|
+
children: storageKey.key
|
|
217
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
218
|
+
style: [styles.headerState, dirty && styles.headerDirty],
|
|
219
|
+
children: state
|
|
220
|
+
})]
|
|
221
|
+
}), /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
222
|
+
onPress: onRaw,
|
|
223
|
+
accessibilityLabel: "Edit raw JSON",
|
|
224
|
+
style: styles.headerButton,
|
|
225
|
+
hitSlop: {
|
|
226
|
+
top: 8,
|
|
227
|
+
bottom: 8,
|
|
228
|
+
left: 8,
|
|
229
|
+
right: 8
|
|
230
|
+
},
|
|
231
|
+
children: [/*#__PURE__*/_jsx(FileJson, {
|
|
232
|
+
size: 16,
|
|
233
|
+
color: macOSColors.semantic.info
|
|
234
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
235
|
+
style: styles.headerRawText,
|
|
236
|
+
children: "Raw"
|
|
237
|
+
})]
|
|
238
|
+
})]
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** `array · 3 items` — what the header says the draft currently is. */
|
|
243
|
+
function summarize(value) {
|
|
244
|
+
if (Array.isArray(value)) {
|
|
245
|
+
return `array · ${value.length} item${value.length === 1 ? "" : "s"}`;
|
|
246
|
+
}
|
|
247
|
+
if (value !== null && typeof value === "object") {
|
|
248
|
+
const n = Object.keys(value).length;
|
|
249
|
+
return `object · ${n} key${n === 1 ? "" : "s"}`;
|
|
250
|
+
}
|
|
251
|
+
return typeof value;
|
|
252
|
+
}
|
|
253
|
+
function storageTypeColor(storageType) {
|
|
254
|
+
switch (storageType) {
|
|
255
|
+
case "mmkv":
|
|
256
|
+
return macOSColors.semantic.info;
|
|
257
|
+
case "async":
|
|
258
|
+
return macOSColors.semantic.warning;
|
|
259
|
+
case "secure":
|
|
260
|
+
return macOSColors.semantic.success;
|
|
261
|
+
default:
|
|
262
|
+
return macOSColors.text.secondary;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const styles = StyleSheet.create({
|
|
266
|
+
screen: {
|
|
267
|
+
flex: 1,
|
|
268
|
+
backgroundColor: macOSColors.background.base
|
|
269
|
+
},
|
|
270
|
+
header: {
|
|
271
|
+
flexDirection: "row",
|
|
272
|
+
alignItems: "center",
|
|
273
|
+
gap: 8,
|
|
274
|
+
paddingHorizontal: 10,
|
|
275
|
+
paddingVertical: 8,
|
|
276
|
+
borderBottomWidth: 1,
|
|
277
|
+
borderBottomColor: macOSColors.border.default
|
|
278
|
+
},
|
|
279
|
+
headerButton: {
|
|
280
|
+
flexDirection: "row",
|
|
281
|
+
alignItems: "center",
|
|
282
|
+
gap: 4,
|
|
283
|
+
paddingVertical: 6,
|
|
284
|
+
paddingHorizontal: 4
|
|
285
|
+
},
|
|
286
|
+
headerRawText: {
|
|
287
|
+
color: macOSColors.semantic.info,
|
|
288
|
+
fontSize: 12,
|
|
289
|
+
fontWeight: "700"
|
|
290
|
+
},
|
|
291
|
+
headerTitle: {
|
|
292
|
+
flex: 1,
|
|
293
|
+
alignItems: "center",
|
|
294
|
+
gap: 2
|
|
295
|
+
},
|
|
296
|
+
headerKey: {
|
|
297
|
+
color: macOSColors.text.primary,
|
|
298
|
+
fontSize: 13,
|
|
299
|
+
fontWeight: "600",
|
|
300
|
+
fontFamily: "monospace"
|
|
301
|
+
},
|
|
302
|
+
headerState: {
|
|
303
|
+
color: macOSColors.text.muted,
|
|
304
|
+
fontSize: 10
|
|
305
|
+
},
|
|
306
|
+
headerDirty: {
|
|
307
|
+
color: macOSColors.semantic.warning
|
|
308
|
+
},
|
|
309
|
+
metaRow: {
|
|
310
|
+
flexDirection: "row",
|
|
311
|
+
alignItems: "center",
|
|
312
|
+
gap: 8,
|
|
313
|
+
paddingHorizontal: 12,
|
|
314
|
+
paddingVertical: 8
|
|
315
|
+
},
|
|
316
|
+
metaText: {
|
|
317
|
+
color: macOSColors.text.muted,
|
|
318
|
+
fontSize: 11,
|
|
319
|
+
fontFamily: "monospace"
|
|
320
|
+
},
|
|
321
|
+
treeScroll: {
|
|
322
|
+
flex: 1
|
|
323
|
+
},
|
|
324
|
+
treeContent: {
|
|
325
|
+
paddingHorizontal: 12,
|
|
326
|
+
paddingBottom: 16
|
|
327
|
+
},
|
|
328
|
+
treeCard: {
|
|
329
|
+
backgroundColor: macOSColors.background.card,
|
|
330
|
+
borderRadius: 10,
|
|
331
|
+
borderWidth: 1,
|
|
332
|
+
borderColor: macOSColors.border.default,
|
|
333
|
+
padding: 6
|
|
334
|
+
},
|
|
335
|
+
treeHint: {
|
|
336
|
+
color: macOSColors.text.muted,
|
|
337
|
+
fontSize: 10,
|
|
338
|
+
paddingTop: 8,
|
|
339
|
+
paddingHorizontal: 4
|
|
340
|
+
},
|
|
341
|
+
error: {
|
|
342
|
+
color: macOSColors.semantic.error,
|
|
343
|
+
fontSize: 11,
|
|
344
|
+
fontFamily: "monospace",
|
|
345
|
+
paddingHorizontal: 12,
|
|
346
|
+
paddingBottom: 6
|
|
347
|
+
},
|
|
348
|
+
footer: {
|
|
349
|
+
backgroundColor: macOSColors.background.card
|
|
350
|
+
},
|
|
351
|
+
commitRow: {
|
|
352
|
+
flexDirection: "row",
|
|
353
|
+
gap: 8,
|
|
354
|
+
paddingHorizontal: 10,
|
|
355
|
+
paddingBottom: 12,
|
|
356
|
+
paddingTop: 2
|
|
357
|
+
},
|
|
358
|
+
discardButton: {
|
|
359
|
+
flex: 1,
|
|
360
|
+
minHeight: 46,
|
|
361
|
+
alignItems: "center",
|
|
362
|
+
justifyContent: "center",
|
|
363
|
+
borderRadius: 12,
|
|
364
|
+
borderWidth: 1,
|
|
365
|
+
borderColor: macOSColors.border.default
|
|
366
|
+
},
|
|
367
|
+
discardText: {
|
|
368
|
+
color: macOSColors.text.secondary,
|
|
369
|
+
fontSize: 14,
|
|
370
|
+
fontWeight: "600"
|
|
371
|
+
},
|
|
372
|
+
saveButton: {
|
|
373
|
+
flex: 1.6,
|
|
374
|
+
minHeight: 46,
|
|
375
|
+
alignItems: "center",
|
|
376
|
+
justifyContent: "center",
|
|
377
|
+
borderRadius: 12,
|
|
378
|
+
backgroundColor: macOSColors.semantic.success
|
|
379
|
+
},
|
|
380
|
+
saveDisabled: {
|
|
381
|
+
opacity: 0.5
|
|
382
|
+
},
|
|
383
|
+
saveText: {
|
|
384
|
+
color: macOSColors.background.base,
|
|
385
|
+
fontSize: 15,
|
|
386
|
+
fontWeight: "700"
|
|
387
|
+
}
|
|
388
|
+
});
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import { memo } from "react";
|
|
4
4
|
import { View, Text, StyleSheet, TouchableOpacity } from "react-native";
|
|
5
|
-
import { macOSColors, CompactRow, TypeBadge, HardDrive, Square, CheckSquare, EyeOff, Pin, ExpandedInfoRow, PillBadge } from "@buoy-gg/shared-ui";
|
|
5
|
+
import { macOSColors, CompactRow, TypeBadge, HardDrive, Square, CheckSquare, Edit3, EyeOff, Pin, ExpandedInfoRow, PillBadge } from "@buoy-gg/shared-ui";
|
|
6
6
|
import { getStorageTypeLabel } from "../utils/storageQueryUtils";
|
|
7
|
-
import { getValueTypeLabel, getValueTypeWithPreview } from "../utils/valueType";
|
|
7
|
+
import { getValueTypeLabel, getValueTypeWithPreview, parseStorageValue } from "../utils/valueType";
|
|
8
8
|
import { DataViewer } from "@buoy-gg/shared-ui/dataViewer";
|
|
9
9
|
|
|
10
10
|
// MMKV Instance color palette - consistent colors per instance
|
|
@@ -86,8 +86,12 @@ export const StorageKeyRow = /*#__PURE__*/memo(function StorageKeyRow({
|
|
|
86
86
|
onViewHistory,
|
|
87
87
|
onHideKey,
|
|
88
88
|
isPinned = false,
|
|
89
|
-
onTogglePin
|
|
89
|
+
onTogglePin,
|
|
90
|
+
onEditKey,
|
|
91
|
+
onToggleKey,
|
|
92
|
+
editBlockedReason
|
|
90
93
|
}) {
|
|
94
|
+
const canEdit = onEditKey != null && editBlockedReason == null;
|
|
91
95
|
const config = getStatusConfig(storageKey.status);
|
|
92
96
|
const hasValue = storageKey.value !== undefined && storageKey.value !== null;
|
|
93
97
|
|
|
@@ -101,18 +105,12 @@ export const StorageKeyRow = /*#__PURE__*/memo(function StorageKeyRow({
|
|
|
101
105
|
// Show storage type as secondary text
|
|
102
106
|
const storageTypeLabel = getStorageTypeLabel(storageKey.storageType);
|
|
103
107
|
|
|
104
|
-
//
|
|
105
|
-
|
|
108
|
+
// Shared with the editor screen, so the card and the thing it opens can't
|
|
109
|
+
// disagree about whether a key holds a container.
|
|
110
|
+
const parsedValue = parseStorageValue(storageKey.value);
|
|
106
111
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (typeof storageKey.value === "string" && isJsonData) {
|
|
110
|
-
try {
|
|
111
|
-
parsedValue = JSON.parse(storageKey.value);
|
|
112
|
-
} catch {
|
|
113
|
-
// Keep original if parse fails
|
|
114
|
-
}
|
|
115
|
-
}
|
|
112
|
+
/** The tree only renders for containers. */
|
|
113
|
+
const showsTree = parsedValue !== null && typeof parsedValue === "object";
|
|
116
114
|
|
|
117
115
|
// Create expanded content for value and storage details
|
|
118
116
|
const expandedContent = /*#__PURE__*/_jsxs(View, {
|
|
@@ -152,7 +150,7 @@ export const StorageKeyRow = /*#__PURE__*/memo(function StorageKeyRow({
|
|
|
152
150
|
children: "view history \u2192"
|
|
153
151
|
})
|
|
154
152
|
})]
|
|
155
|
-
}),
|
|
153
|
+
}), showsTree ? /*#__PURE__*/_jsx(View, {
|
|
156
154
|
style: styles.dataViewerContainer,
|
|
157
155
|
children: /*#__PURE__*/_jsx(DataViewer, {
|
|
158
156
|
data: parsedValue,
|
|
@@ -207,9 +205,34 @@ export const StorageKeyRow = /*#__PURE__*/memo(function StorageKeyRow({
|
|
|
207
205
|
style: styles.expandedDescription,
|
|
208
206
|
children: storageKey.description
|
|
209
207
|
})]
|
|
210
|
-
}) : null,
|
|
208
|
+
}) : null, editBlockedReason ? /*#__PURE__*/_jsxs(View, {
|
|
209
|
+
style: styles.expandedRow,
|
|
210
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
211
|
+
style: styles.expandedLabel,
|
|
212
|
+
children: "Edit:"
|
|
213
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
214
|
+
style: styles.expandedDescription,
|
|
215
|
+
children: editBlockedReason
|
|
216
|
+
})]
|
|
217
|
+
}) : null, onTogglePin || onHideKey || canEdit ? /*#__PURE__*/_jsxs(View, {
|
|
211
218
|
style: styles.actionRow,
|
|
212
|
-
children: [
|
|
219
|
+
children: [canEdit ? /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
220
|
+
style: styles.editButton,
|
|
221
|
+
onPress: () => isBoolean && onToggleKey ? onToggleKey(storageKey) : onEditKey?.(storageKey),
|
|
222
|
+
hitSlop: {
|
|
223
|
+
top: 6,
|
|
224
|
+
bottom: 6,
|
|
225
|
+
left: 6,
|
|
226
|
+
right: 6
|
|
227
|
+
},
|
|
228
|
+
children: [/*#__PURE__*/_jsx(Edit3, {
|
|
229
|
+
size: 13,
|
|
230
|
+
color: macOSColors.background.base
|
|
231
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
232
|
+
style: styles.editButtonText,
|
|
233
|
+
children: isBoolean && onToggleKey ? "Toggle" : "Edit"
|
|
234
|
+
})]
|
|
235
|
+
}) : null, onTogglePin ? /*#__PURE__*/_jsxs(TouchableOpacity, {
|
|
213
236
|
style: [styles.actionChip, isPinned && styles.actionChipActive],
|
|
214
237
|
onPress: () => onTogglePin(storageKey.key),
|
|
215
238
|
hitSlop: {
|
|
@@ -431,6 +454,21 @@ const styles = StyleSheet.create({
|
|
|
431
454
|
backgroundColor: macOSColors.semantic.info + "15",
|
|
432
455
|
borderColor: macOSColors.semantic.info + "44"
|
|
433
456
|
},
|
|
457
|
+
/** Filled, and first — the one action in this row that changes anything. */
|
|
458
|
+
editButton: {
|
|
459
|
+
flexDirection: "row",
|
|
460
|
+
alignItems: "center",
|
|
461
|
+
gap: 6,
|
|
462
|
+
paddingVertical: 8,
|
|
463
|
+
paddingHorizontal: 14,
|
|
464
|
+
borderRadius: 8,
|
|
465
|
+
backgroundColor: macOSColors.semantic.success
|
|
466
|
+
},
|
|
467
|
+
editButtonText: {
|
|
468
|
+
color: macOSColors.background.base,
|
|
469
|
+
fontSize: 12,
|
|
470
|
+
fontWeight: "700"
|
|
471
|
+
},
|
|
434
472
|
actionChipText: {
|
|
435
473
|
fontSize: 11,
|
|
436
474
|
fontWeight: "600",
|