@buoy-gg/storage 7.0.40 → 7.0.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/README.md +4 -0
  2. package/lib/commonjs/index.js +8 -1
  3. package/lib/commonjs/preset.js +9 -4
  4. package/lib/commonjs/storage/components/GameUIStorageBrowser.js +3 -2
  5. package/lib/commonjs/storage/components/MMKVInstanceSelector.js +3 -2
  6. package/lib/commonjs/storage/components/StorageActionButtons.js +6 -5
  7. package/lib/commonjs/storage/components/StorageEventCard.js +2 -1
  8. package/lib/commonjs/storage/components/StorageEventFilterView.js +7 -6
  9. package/lib/commonjs/storage/components/StorageKeyStats.js +5 -4
  10. package/lib/commonjs/storage/components/StorageTypeFilterBar.js +4 -3
  11. package/lib/commonjs/storage/hooks/useSecureStoreKeys.js +55 -12
  12. package/lib/commonjs/storage/sync/storageSyncAdapter.js +15 -1
  13. package/lib/commonjs/storage/utils/AsyncStorageListener.web.js +89 -0
  14. package/lib/commonjs/storage/utils/browserStorageLifecycle.js +10 -0
  15. package/lib/commonjs/storage/utils/browserStorageLifecycle.web.js +70 -0
  16. package/lib/commonjs/storage/utils/mmkvAvailability.web.js +21 -0
  17. package/lib/commonjs/storage/utils/storageLabels.js +13 -0
  18. package/lib/commonjs/storage/utils/storageLabels.web.js +13 -0
  19. package/lib/module/index.js +3 -1
  20. package/lib/module/preset.js +11 -5
  21. package/lib/module/storage/components/GameUIStorageBrowser.js +3 -2
  22. package/lib/module/storage/components/MMKVInstanceSelector.js +4 -3
  23. package/lib/module/storage/components/StorageActionButtons.js +6 -5
  24. package/lib/module/storage/components/StorageEventCard.js +2 -1
  25. package/lib/module/storage/components/StorageEventFilterView.js +7 -6
  26. package/lib/module/storage/components/StorageKeyStats.js +5 -4
  27. package/lib/module/storage/components/StorageTypeFilterBar.js +4 -3
  28. package/lib/module/storage/hooks/useSecureStoreKeys.js +55 -12
  29. package/lib/module/storage/sync/storageSyncAdapter.js +12 -0
  30. package/lib/module/storage/utils/AsyncStorageListener.web.js +76 -0
  31. package/lib/module/storage/utils/browserStorageLifecycle.js +6 -0
  32. package/lib/module/storage/utils/browserStorageLifecycle.web.js +66 -0
  33. package/lib/module/storage/utils/mmkvAvailability.web.js +15 -0
  34. package/lib/module/storage/utils/storageLabels.js +9 -0
  35. package/lib/module/storage/utils/storageLabels.web.js +9 -0
  36. package/lib/typescript/index.d.ts +1 -0
  37. package/lib/typescript/index.d.ts.map +1 -1
  38. package/lib/typescript/preset.d.ts.map +1 -1
  39. package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts.map +1 -1
  40. package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts +0 -8
  41. package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts.map +1 -1
  42. package/lib/typescript/storage/components/StorageActionButtons.d.ts.map +1 -1
  43. package/lib/typescript/storage/components/StorageEventCard.d.ts +0 -7
  44. package/lib/typescript/storage/components/StorageEventCard.d.ts.map +1 -1
  45. package/lib/typescript/storage/components/StorageEventFilterView.d.ts.map +1 -1
  46. package/lib/typescript/storage/components/StorageKeyRow.d.ts +2 -6
  47. package/lib/typescript/storage/components/StorageKeyRow.d.ts.map +1 -1
  48. package/lib/typescript/storage/components/StorageKeyStats.d.ts.map +1 -1
  49. package/lib/typescript/storage/components/StorageTypeFilterBar.d.ts +0 -15
  50. package/lib/typescript/storage/components/StorageTypeFilterBar.d.ts.map +1 -1
  51. package/lib/typescript/storage/hooks/useSecureStoreKeys.d.ts +2 -2
  52. package/lib/typescript/storage/hooks/useSecureStoreKeys.d.ts.map +1 -1
  53. package/lib/typescript/storage/sync/storageSyncAdapter.d.ts +7 -13
  54. package/lib/typescript/storage/sync/storageSyncAdapter.d.ts.map +1 -1
  55. package/lib/typescript/storage/utils/AsyncStorageListener.web.d.ts +24 -0
  56. package/lib/typescript/storage/utils/AsyncStorageListener.web.d.ts.map +1 -0
  57. package/lib/typescript/storage/utils/browserStorageLifecycle.d.ts +3 -0
  58. package/lib/typescript/storage/utils/browserStorageLifecycle.d.ts.map +1 -0
  59. package/lib/typescript/storage/utils/browserStorageLifecycle.web.d.ts +2 -0
  60. package/lib/typescript/storage/utils/browserStorageLifecycle.web.d.ts.map +1 -0
  61. package/lib/typescript/storage/utils/mmkvAvailability.web.d.ts +4 -0
  62. package/lib/typescript/storage/utils/mmkvAvailability.web.d.ts.map +1 -0
  63. package/lib/typescript/storage/utils/storageLabels.d.ts +8 -0
  64. package/lib/typescript/storage/utils/storageLabels.d.ts.map +1 -0
  65. package/lib/typescript/storage/utils/storageLabels.web.d.ts +8 -0
  66. package/lib/typescript/storage/utils/storageLabels.web.d.ts.map +1 -0
  67. package/lib/web/index.mjs +5 -0
  68. package/package.json +40 -14
  69. package/lib/commonjs/storage/components/DiffViewer/DiffOptionsPanel.js +0 -356
  70. package/lib/commonjs/storage/components/DiffViewer/components/DiffSummary.js +0 -122
  71. package/lib/commonjs/storage/components/StorageKeyEditorScreen.js +0 -414
  72. package/lib/commonjs/storage/components/StorageScalarKeyEditor.js +0 -61
  73. package/lib/commonjs/storage/components/StorageValueEditModal.js +0 -24
  74. package/lib/commonjs/storage/hooks/useKeyEditor.js +0 -31
  75. package/lib/commonjs/storage/hooks/useTreeDraft.js +0 -25
  76. package/lib/module/storage/components/DiffViewer/DiffOptionsPanel.js +0 -352
  77. package/lib/module/storage/components/DiffViewer/components/DiffSummary.js +0 -118
  78. package/lib/module/storage/components/StorageKeyEditorScreen.js +0 -410
  79. package/lib/module/storage/components/StorageScalarKeyEditor.js +0 -57
  80. package/lib/module/storage/components/StorageValueEditModal.js +0 -20
  81. package/lib/module/storage/hooks/useKeyEditor.js +0 -27
  82. package/lib/module/storage/hooks/useTreeDraft.js +0 -21
  83. package/lib/typescript/storage/components/DiffViewer/DiffOptionsPanel.d.ts +0 -18
  84. package/lib/typescript/storage/components/DiffViewer/DiffOptionsPanel.d.ts.map +0 -1
  85. package/lib/typescript/storage/components/DiffViewer/components/DiffSummary.d.ts +0 -12
  86. package/lib/typescript/storage/components/DiffViewer/components/DiffSummary.d.ts.map +0 -1
  87. package/lib/typescript/storage/components/StorageKeyEditorScreen.d.ts +0 -42
  88. package/lib/typescript/storage/components/StorageKeyEditorScreen.d.ts.map +0 -1
  89. package/lib/typescript/storage/components/StorageScalarKeyEditor.d.ts +0 -24
  90. package/lib/typescript/storage/components/StorageScalarKeyEditor.d.ts.map +0 -1
  91. package/lib/typescript/storage/components/StorageValueEditModal.d.ts +0 -14
  92. package/lib/typescript/storage/components/StorageValueEditModal.d.ts.map +0 -1
  93. package/lib/typescript/storage/hooks/useKeyEditor.d.ts +0 -27
  94. package/lib/typescript/storage/hooks/useKeyEditor.d.ts.map +0 -1
  95. package/lib/typescript/storage/hooks/useTreeDraft.d.ts +0 -16
  96. package/lib/typescript/storage/hooks/useTreeDraft.d.ts.map +0 -1
@@ -1,414 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.StorageKeyEditorScreen = StorageKeyEditorScreen;
7
- var _react = require("react");
8
- var _reactNative = require("react-native");
9
- var _sharedUi = require("@buoy-gg/shared-ui");
10
- var _dataViewer = require("@buoy-gg/shared-ui/dataViewer");
11
- var _useKeyEditor = require("../hooks/useKeyEditor");
12
- var _StorageValueEditModal = require("./StorageValueEditModal");
13
- var _StorageScalarKeyEditor = require("./StorageScalarKeyEditor");
14
- var _storageQueryUtils = require("../utils/storageQueryUtils");
15
- var _valueType = require("../utils/valueType");
16
- var _jsxRuntime = require("react/jsx-runtime");
17
- /**
18
- * Editing a key, on a screen of its own.
19
- *
20
- * Editing used to happen inside the expanded card in the key list: a tree a few
21
- * rows tall, an action bar wrapped onto three lines, and the rest of the list
22
- * still scrolling underneath. Every control was competing for the same ~200px.
23
- *
24
- * So the card now offers ONE edit button and the actual work happens here, with
25
- * the whole viewport: the tree gets the height, the six structural actions get
26
- * thumb-sized tiles docked at the bottom where they're always in the same
27
- * place, and manual JSON editing — the escape hatch, not the main path — moves
28
- * to a single button in the top-right corner.
29
- *
30
- * Typing a value happens in a modal pinned to the top of the screen, over the
31
- * tree rather than instead of it — see {@link StorageValueEditModal}.
32
- */
33
-
34
- /** Props once the value has been un-stringified — see `parseStorageValue`. */
35
-
36
- /**
37
- * A container and a scalar are different editors, not one editor with a flag.
38
- *
39
- * A tree of one row is not a tree, so a scalar key skips the whole structural
40
- * editor and gets just the value modal. Splitting here keeps each editor's
41
- * state to what it actually needs — see {@link StorageScalarKeyEditor}.
42
- */
43
- function StorageKeyEditorScreen(props) {
44
- // Memo justified: this is a JSON.parse of the whole stored value, and the
45
- // browser underneath re-renders on every storage event the app emits.
46
- const raw = props.storageKey.value;
47
- const value = (0, _react.useMemo)(() => (0, _valueType.parseStorageValue)(raw), [raw]);
48
- return value !== null && typeof value === "object" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(StorageTreeEditor, {
49
- ...props,
50
- value: value
51
- }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_StorageScalarKeyEditor.StorageScalarKeyEditor, {
52
- storageKey: props.storageKey,
53
- value: value,
54
- onSave: props.onSave,
55
- onClose: props.onClose
56
- });
57
- }
58
-
59
- /* ------------------------------------------------------------------ *
60
- * Containers — tree + structural actions, buffered into a draft.
61
- * ------------------------------------------------------------------ */
62
-
63
- function StorageTreeEditor({
64
- storageKey,
65
- value,
66
- onSave,
67
- onClose,
68
- applySafeAreaInset
69
- }) {
70
- const insets = (0, _sharedUi.useSafeAreaInsets)();
71
- const bottomInset = applySafeAreaInset ? insets.bottom : 0;
72
- const editor = (0, _useKeyEditor.useKeyEditor)({
73
- value,
74
- save: onSave,
75
- onClose,
76
- confirmDiscard: choices => _reactNative.Alert.alert("Unsaved changes", `"${storageKey.key}" has edits that haven't been written to the device.`, [{
77
- text: "Keep editing",
78
- style: "cancel"
79
- }, {
80
- text: "Discard",
81
- style: "destructive",
82
- onPress: choices.discard
83
- }, {
84
- text: "Save",
85
- onPress: choices.save
86
- }])
87
- });
88
- const {
89
- draft,
90
- selection,
91
- valuePath
92
- } = editor;
93
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
94
- style: styles.screen,
95
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolBackground, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(EditorHeader, {
96
- storageKey: storageKey,
97
- state: draft.isSaving ? "Saving…" : draft.isDirty ? "Draft · unsaved" : "In sync with device",
98
- dirty: draft.isDirty,
99
- onClose: editor.requestClose
100
- // Manual editing of the WHOLE value — everything else on this screen is
101
- // structural, so raw JSON gets a corner rather than a tile.
102
- ,
103
- onRaw: editor.openRawEditor
104
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
105
- style: styles.metaRow,
106
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.PillBadge, {
107
- color: storageTypeColor(storageKey.storageType),
108
- children: (0, _storageQueryUtils.getStorageTypeLabel)(storageKey.storageType)
109
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
110
- style: styles.metaText,
111
- children: summarize(draft.value)
112
- })]
113
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, {
114
- testID: "buoy-storage-editor-scroll",
115
- style: styles.treeScroll,
116
- contentContainerStyle: styles.treeContent,
117
- keyboardShouldPersistTaps: "handled",
118
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
119
- style: styles.treeCard,
120
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.DataViewer, {
121
- data: draft.value,
122
- title: "",
123
- rawMode: true,
124
- initialExpanded: true
125
- // Type filtering is a READING aid: the filtered view is a
126
- // projection whose row paths don't address the real document, so
127
- // the explorer stops reporting selection while one is active. An
128
- // editor whose actions silently go dead isn't worth the filter.
129
- ,
130
- showTypeFilter: false,
131
- onSelectionChange: editor.setSelection,
132
- selectPath: draft.selectPath
133
- // Its own handle root: the card that opened this editor is still
134
- // mounted underneath, rendering the same value in its preview tree.
135
- ,
136
- testIDPrefix: "buoy-storage-editor-row",
137
- onRequestInlineEdit: sel => editor.openValueEditor(sel.path)
138
- })
139
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
140
- style: styles.treeHint,
141
- children: "Tap a row to select it \xB7 double-tap to edit its value"
142
- })]
143
- }), draft.error ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
144
- style: styles.error,
145
- numberOfLines: 3,
146
- children: draft.error
147
- }) : null, /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
148
- style: [styles.footer, {
149
- paddingBottom: bottomInset
150
- }],
151
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.DataTreeActionDock, {
152
- root: draft.value,
153
- selection: selection,
154
- onEdit: draft.apply,
155
- onSelectPath: draft.selectAt
156
- // Booleans never reach this — the dock applies their flip directly.
157
- ,
158
- onEditValue: () => editor.openValueEditor(selection?.path ?? [])
159
- }), draft.isDirty ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
160
- style: styles.commitRow,
161
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
162
- onPress: draft.discard,
163
- disabled: draft.isSaving,
164
- testID: "buoy-storage-editor-discard",
165
- accessibilityRole: "button",
166
- accessibilityLabel: "Discard changes",
167
- style: styles.discardButton,
168
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
169
- style: styles.discardText,
170
- children: "Discard"
171
- })
172
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
173
- onPress: editor.saveAndClose,
174
- disabled: draft.isSaving,
175
- testID: "buoy-storage-editor-save",
176
- accessibilityRole: "button",
177
- accessibilityLabel: "Save changes",
178
- style: [styles.saveButton, draft.isSaving && styles.saveDisabled],
179
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
180
- style: styles.saveText,
181
- children: draft.isSaving ? "Saving…" : "Save changes"
182
- })
183
- })]
184
- }) : null]
185
- }), valuePath ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_StorageValueEditModal.StorageValueEditModal, {
186
- path: valuePath,
187
- value: (0, _dataViewer.getAtPath)(draft.value, valuePath),
188
- onSave: editor.applyValue,
189
- onCancel: editor.closeValueEditor
190
- // It only reaches the draft here — the single write happens on Save.
191
- ,
192
- saveLabel: "Apply"
193
- }) : null]
194
- });
195
- }
196
-
197
- /* ------------------------------------------------------------------ *
198
- * Shared pieces
199
- * ------------------------------------------------------------------ */
200
-
201
- function EditorHeader({
202
- storageKey,
203
- state,
204
- dirty,
205
- onClose,
206
- onRaw
207
- }) {
208
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
209
- style: styles.header,
210
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
211
- onPress: onClose,
212
- testID: "buoy-storage-editor-close",
213
- accessibilityRole: "button",
214
- accessibilityLabel: "Close editor",
215
- style: styles.headerButton,
216
- hitSlop: {
217
- top: 8,
218
- bottom: 8,
219
- left: 8,
220
- right: 8
221
- },
222
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.X, {
223
- size: 16,
224
- color: _sharedUi.night.color.textSecondary
225
- })
226
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
227
- style: styles.headerTitle,
228
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text
229
- // Which key this editor is pointed at. Worth a handle of its own:
230
- // the editor is reached by expanding a card in a list of hundreds,
231
- // and opening it on the wrong one looks exactly like opening it on
232
- // the right one until a write lands somewhere unexpected.
233
- , {
234
- testID: "buoy-storage-editor-key",
235
- style: styles.headerKey,
236
- numberOfLines: 1,
237
- children: storageKey.key
238
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
239
- style: [styles.headerState, dirty && styles.headerDirty],
240
- children: state
241
- })]
242
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
243
- onPress: onRaw,
244
- testID: "buoy-storage-editor-raw",
245
- accessibilityRole: "button",
246
- accessibilityLabel: "Edit raw JSON",
247
- style: styles.headerButton,
248
- hitSlop: {
249
- top: 8,
250
- bottom: 8,
251
- left: 8,
252
- right: 8
253
- },
254
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.FileJson, {
255
- size: 16,
256
- color: _sharedUi.night.color.accent
257
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
258
- style: styles.headerRawText,
259
- children: "Raw"
260
- })]
261
- })]
262
- });
263
- }
264
-
265
- /** `array · 3 items` — what the header says the draft currently is. */
266
- function summarize(value) {
267
- if (Array.isArray(value)) {
268
- return `array · ${value.length} item${value.length === 1 ? "" : "s"}`;
269
- }
270
- if (value !== null && typeof value === "object") {
271
- const n = Object.keys(value).length;
272
- return `object · ${n} key${n === 1 ? "" : "s"}`;
273
- }
274
- return typeof value;
275
- }
276
- function storageTypeColor(storageType) {
277
- switch (storageType) {
278
- case "mmkv":
279
- return _sharedUi.macOSColors.semantic.info;
280
- case "async":
281
- return _sharedUi.macOSColors.semantic.warning;
282
- case "secure":
283
- return _sharedUi.macOSColors.semantic.success;
284
- default:
285
- return _sharedUi.macOSColors.text.secondary;
286
- }
287
- }
288
- const styles = _reactNative.StyleSheet.create({
289
- screen: {
290
- flex: 1,
291
- // Opaque on purpose: transparency here showed the whole key list through
292
- // the editor, not just the sheet's star field. The screen paints its own
293
- // ToolBackground instead — see the mount site above.
294
- backgroundColor: _sharedUi.night.color.bg
295
- },
296
- header: {
297
- flexDirection: "row",
298
- alignItems: "center",
299
- gap: 8,
300
- paddingHorizontal: 10,
301
- paddingVertical: 8,
302
- borderBottomWidth: 1,
303
- borderBottomColor: _sharedUi.night.color.border
304
- },
305
- headerButton: {
306
- flexDirection: "row",
307
- alignItems: "center",
308
- gap: 4,
309
- paddingVertical: 6,
310
- paddingHorizontal: 4
311
- },
312
- headerRawText: {
313
- color: _sharedUi.night.color.accent,
314
- fontSize: 12,
315
- fontWeight: "700"
316
- },
317
- headerTitle: {
318
- flex: 1,
319
- alignItems: "center",
320
- gap: 2
321
- },
322
- headerKey: {
323
- color: _sharedUi.night.color.text,
324
- fontSize: 13,
325
- fontWeight: "600",
326
- fontFamily: _sharedUi.monoFont
327
- },
328
- headerState: {
329
- color: _sharedUi.night.color.textTertiary,
330
- fontSize: 10
331
- },
332
- headerDirty: {
333
- color: _sharedUi.night.color.warning
334
- },
335
- metaRow: {
336
- flexDirection: "row",
337
- alignItems: "center",
338
- gap: 8,
339
- paddingHorizontal: 12,
340
- paddingVertical: 8
341
- },
342
- metaText: {
343
- color: _sharedUi.night.color.textTertiary,
344
- fontSize: 11,
345
- fontFamily: _sharedUi.monoFont
346
- },
347
- treeScroll: {
348
- flex: 1
349
- },
350
- treeContent: {
351
- paddingHorizontal: 12,
352
- paddingBottom: 16
353
- },
354
- treeCard: {
355
- backgroundColor: _sharedUi.night.color.surface,
356
- borderRadius: 10,
357
- borderWidth: 1,
358
- borderColor: _sharedUi.night.color.border,
359
- padding: 6
360
- },
361
- treeHint: {
362
- color: _sharedUi.night.color.textTertiary,
363
- fontSize: 10,
364
- paddingTop: 8,
365
- paddingHorizontal: 4
366
- },
367
- error: {
368
- color: _sharedUi.night.color.danger,
369
- fontSize: 11,
370
- fontFamily: _sharedUi.monoFont,
371
- paddingHorizontal: 12,
372
- paddingBottom: 6
373
- },
374
- footer: {
375
- backgroundColor: _sharedUi.night.color.surface
376
- },
377
- commitRow: {
378
- flexDirection: "row",
379
- gap: 8,
380
- paddingHorizontal: 10,
381
- paddingBottom: 12,
382
- paddingTop: 2
383
- },
384
- discardButton: {
385
- flex: 1,
386
- minHeight: 46,
387
- alignItems: "center",
388
- justifyContent: "center",
389
- borderRadius: 12,
390
- borderWidth: 1,
391
- borderColor: _sharedUi.night.color.border
392
- },
393
- discardText: {
394
- color: _sharedUi.night.color.textSecondary,
395
- fontSize: 14,
396
- fontWeight: "600"
397
- },
398
- saveButton: {
399
- flex: 1.6,
400
- minHeight: 46,
401
- alignItems: "center",
402
- justifyContent: "center",
403
- borderRadius: 12,
404
- backgroundColor: _sharedUi.night.color.accent
405
- },
406
- saveDisabled: {
407
- opacity: 0.5
408
- },
409
- saveText: {
410
- color: _sharedUi.night.color.onAccent,
411
- fontSize: 15,
412
- fontWeight: "700"
413
- }
414
- });
@@ -1,61 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.StorageScalarKeyEditor = StorageScalarKeyEditor;
7
- var _react = require("react");
8
- var _reactNative = require("react-native");
9
- var _StorageValueEditModal = require("./StorageValueEditModal");
10
- var _jsxRuntime = require("react/jsx-runtime");
11
- /**
12
- * Editing a key whose value is a single string, number or boolean.
13
- *
14
- * A tree of one row is not a tree, so there's nothing here to select, reorder
15
- * or append to — which means none of the structural editor applies. And with
16
- * one edit producing one write, there's nothing to buffer either: a draft would
17
- * only add a step between typing the value and storing it.
18
- *
19
- * So this is just the value modal over whatever the user was looking at, on
20
- * both the phone and the dashboard. Changing one string shouldn't black out the
21
- * screen it came from.
22
- */
23
-
24
- /**
25
- * The text `setStorageValue` should store.
26
- *
27
- * A string is stored AS ITSELF — `JSON.stringify` here was adding quotes a
28
- * plain string never had. AsyncStorage hid it (the browser reads values back
29
- * through `JSON.parse`, so the tool agreed with itself) but the app's own
30
- * `getItem` saw `"dark"` where it had written `dark`; MMKV stores strings
31
- * natively and showed the quotes right in the row, compounding on every edit.
32
- *
33
- * Everything else keeps JSON: for a number or a boolean that IS its text, and
34
- * containers never reach this editor.
35
- */
36
- function serializeScalar(value) {
37
- return typeof value === "string" ? value : JSON.stringify(value);
38
- }
39
- function StorageScalarKeyEditor({
40
- storageKey,
41
- value,
42
- onSave,
43
- onClose
44
- }) {
45
- const [saving, setSaving] = (0, _react.useState)(false);
46
- const save = (0, _react.useCallback)(next => {
47
- if (saving) return;
48
- setSaving(true);
49
- onSave(serializeScalar(next)).then(onClose).catch(e => {
50
- setSaving(false);
51
- _reactNative.Alert.alert("Couldn't save", e instanceof Error ? e.message : String(e));
52
- });
53
- }, [onClose, onSave, saving]);
54
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_StorageValueEditModal.StorageValueEditModal, {
55
- path: [storageKey.key],
56
- value: value,
57
- onSave: save,
58
- onCancel: onClose,
59
- busy: saving
60
- });
61
- }
@@ -1,24 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.StorageValueEditModal = StorageValueEditModal;
7
- var _dataViewer = require("@buoy-gg/shared-ui/dataViewer");
8
- var _jsxRuntime = require("react/jsx-runtime");
9
- /**
10
- * Storage's value-typing panel.
11
- *
12
- * The panel itself — top-pinned so the keyboard can't reach it, type preserved
13
- * by construction, raw-JSON shape check — lives in shared-ui's
14
- * {@link ValueEditModal}, shared with the Zustand store editor. This wrapper
15
- * only pins storage's testID namespace so the Detox suite's handles
16
- * (`buoy-storage-value-input`, `-save`, …) stay exactly what they were.
17
- */
18
-
19
- function StorageValueEditModal(props) {
20
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.ValueEditModal, {
21
- ...props,
22
- testIDPrefix: "buoy-storage-value"
23
- });
24
- }
@@ -1,31 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.useKeyEditor = useKeyEditor;
7
- var _react = require("react");
8
- var _dataViewer = require("@buoy-gg/shared-ui/dataViewer");
9
- /**
10
- * Storage's view of the shared tree editor.
11
- *
12
- * Everything editing a key involves — buffered draft, selection, value modal,
13
- * dirty-close guard — lives in shared-ui's `useTreeEditor`, shared with the
14
- * Zustand store editor so the two can't drift. Storage's single write takes
15
- * the SERIALIZED value, so this wrapper is exactly the stringify.
16
- */
17
-
18
- function useKeyEditor({
19
- value,
20
- save,
21
- onClose,
22
- confirmDiscard
23
- }) {
24
- const saveValue = (0, _react.useMemo)(() => next => save(JSON.stringify(next)), [save]);
25
- return (0, _dataViewer.useTreeEditor)({
26
- value,
27
- save: saveValue,
28
- onClose,
29
- confirmDiscard
30
- });
31
- }
@@ -1,25 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.useTreeDraft = useTreeDraft;
7
- var _react = require("react");
8
- var _dataViewer = require("@buoy-gg/shared-ui/dataViewer");
9
- /**
10
- * Storage's view of the shared buffered tree draft.
11
- *
12
- * The draft itself lives in shared-ui (`useTreeDraft` there — one editor for
13
- * storage keys and zustand stores, so the rules can't drift). Storage's write
14
- * path takes the SERIALIZED value — `setItem(key, raw)` — so this wrapper is
15
- * exactly the stringify.
16
- */
17
-
18
- /**
19
- * @param liveValue the value as storage currently holds it (already parsed)
20
- * @param save persists the serialized draft; rejecting keeps edit mode open
21
- */
22
- function useTreeDraft(liveValue, save) {
23
- const saveValue = (0, _react.useMemo)(() => save ? value => save(JSON.stringify(value)) : undefined, [save]);
24
- return (0, _dataViewer.useTreeDraft)(liveValue, saveValue);
25
- }