@buoy-gg/storage 7.0.39 → 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,410 +0,0 @@
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, night, FileJson, PillBadge, ToolBackground, useSafeAreaInsets, X, monoFont } 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(ToolBackground, {}), /*#__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
- testID: "buoy-storage-editor-scroll",
111
- style: styles.treeScroll,
112
- contentContainerStyle: styles.treeContent,
113
- keyboardShouldPersistTaps: "handled",
114
- children: [/*#__PURE__*/_jsx(View, {
115
- style: styles.treeCard,
116
- children: /*#__PURE__*/_jsx(DataViewer, {
117
- data: draft.value,
118
- title: "",
119
- rawMode: true,
120
- initialExpanded: true
121
- // Type filtering is a READING aid: the filtered view is a
122
- // projection whose row paths don't address the real document, so
123
- // the explorer stops reporting selection while one is active. An
124
- // editor whose actions silently go dead isn't worth the filter.
125
- ,
126
- showTypeFilter: false,
127
- onSelectionChange: editor.setSelection,
128
- selectPath: draft.selectPath
129
- // Its own handle root: the card that opened this editor is still
130
- // mounted underneath, rendering the same value in its preview tree.
131
- ,
132
- testIDPrefix: "buoy-storage-editor-row",
133
- onRequestInlineEdit: sel => editor.openValueEditor(sel.path)
134
- })
135
- }), /*#__PURE__*/_jsx(Text, {
136
- style: styles.treeHint,
137
- children: "Tap a row to select it \xB7 double-tap to edit its value"
138
- })]
139
- }), draft.error ? /*#__PURE__*/_jsx(Text, {
140
- style: styles.error,
141
- numberOfLines: 3,
142
- children: draft.error
143
- }) : null, /*#__PURE__*/_jsxs(View, {
144
- style: [styles.footer, {
145
- paddingBottom: bottomInset
146
- }],
147
- children: [/*#__PURE__*/_jsx(DataTreeActionDock, {
148
- root: draft.value,
149
- selection: selection,
150
- onEdit: draft.apply,
151
- onSelectPath: draft.selectAt
152
- // Booleans never reach this — the dock applies their flip directly.
153
- ,
154
- onEditValue: () => editor.openValueEditor(selection?.path ?? [])
155
- }), draft.isDirty ? /*#__PURE__*/_jsxs(View, {
156
- style: styles.commitRow,
157
- children: [/*#__PURE__*/_jsx(TouchableOpacity, {
158
- onPress: draft.discard,
159
- disabled: draft.isSaving,
160
- testID: "buoy-storage-editor-discard",
161
- accessibilityRole: "button",
162
- accessibilityLabel: "Discard changes",
163
- style: styles.discardButton,
164
- children: /*#__PURE__*/_jsx(Text, {
165
- style: styles.discardText,
166
- children: "Discard"
167
- })
168
- }), /*#__PURE__*/_jsx(TouchableOpacity, {
169
- onPress: editor.saveAndClose,
170
- disabled: draft.isSaving,
171
- testID: "buoy-storage-editor-save",
172
- accessibilityRole: "button",
173
- accessibilityLabel: "Save changes",
174
- style: [styles.saveButton, draft.isSaving && styles.saveDisabled],
175
- children: /*#__PURE__*/_jsx(Text, {
176
- style: styles.saveText,
177
- children: draft.isSaving ? "Saving…" : "Save changes"
178
- })
179
- })]
180
- }) : null]
181
- }), valuePath ? /*#__PURE__*/_jsx(StorageValueEditModal, {
182
- path: valuePath,
183
- value: getAtPath(draft.value, valuePath),
184
- onSave: editor.applyValue,
185
- onCancel: editor.closeValueEditor
186
- // It only reaches the draft here — the single write happens on Save.
187
- ,
188
- saveLabel: "Apply"
189
- }) : null]
190
- });
191
- }
192
-
193
- /* ------------------------------------------------------------------ *
194
- * Shared pieces
195
- * ------------------------------------------------------------------ */
196
-
197
- function EditorHeader({
198
- storageKey,
199
- state,
200
- dirty,
201
- onClose,
202
- onRaw
203
- }) {
204
- return /*#__PURE__*/_jsxs(View, {
205
- style: styles.header,
206
- children: [/*#__PURE__*/_jsx(TouchableOpacity, {
207
- onPress: onClose,
208
- testID: "buoy-storage-editor-close",
209
- accessibilityRole: "button",
210
- accessibilityLabel: "Close editor",
211
- style: styles.headerButton,
212
- hitSlop: {
213
- top: 8,
214
- bottom: 8,
215
- left: 8,
216
- right: 8
217
- },
218
- children: /*#__PURE__*/_jsx(X, {
219
- size: 16,
220
- color: night.color.textSecondary
221
- })
222
- }), /*#__PURE__*/_jsxs(View, {
223
- style: styles.headerTitle,
224
- children: [/*#__PURE__*/_jsx(Text
225
- // Which key this editor is pointed at. Worth a handle of its own:
226
- // the editor is reached by expanding a card in a list of hundreds,
227
- // and opening it on the wrong one looks exactly like opening it on
228
- // the right one until a write lands somewhere unexpected.
229
- , {
230
- testID: "buoy-storage-editor-key",
231
- style: styles.headerKey,
232
- numberOfLines: 1,
233
- children: storageKey.key
234
- }), /*#__PURE__*/_jsx(Text, {
235
- style: [styles.headerState, dirty && styles.headerDirty],
236
- children: state
237
- })]
238
- }), /*#__PURE__*/_jsxs(TouchableOpacity, {
239
- onPress: onRaw,
240
- testID: "buoy-storage-editor-raw",
241
- accessibilityRole: "button",
242
- accessibilityLabel: "Edit raw JSON",
243
- style: styles.headerButton,
244
- hitSlop: {
245
- top: 8,
246
- bottom: 8,
247
- left: 8,
248
- right: 8
249
- },
250
- children: [/*#__PURE__*/_jsx(FileJson, {
251
- size: 16,
252
- color: night.color.accent
253
- }), /*#__PURE__*/_jsx(Text, {
254
- style: styles.headerRawText,
255
- children: "Raw"
256
- })]
257
- })]
258
- });
259
- }
260
-
261
- /** `array · 3 items` — what the header says the draft currently is. */
262
- function summarize(value) {
263
- if (Array.isArray(value)) {
264
- return `array · ${value.length} item${value.length === 1 ? "" : "s"}`;
265
- }
266
- if (value !== null && typeof value === "object") {
267
- const n = Object.keys(value).length;
268
- return `object · ${n} key${n === 1 ? "" : "s"}`;
269
- }
270
- return typeof value;
271
- }
272
- function storageTypeColor(storageType) {
273
- switch (storageType) {
274
- case "mmkv":
275
- return macOSColors.semantic.info;
276
- case "async":
277
- return macOSColors.semantic.warning;
278
- case "secure":
279
- return macOSColors.semantic.success;
280
- default:
281
- return macOSColors.text.secondary;
282
- }
283
- }
284
- const styles = StyleSheet.create({
285
- screen: {
286
- flex: 1,
287
- // Opaque on purpose: transparency here showed the whole key list through
288
- // the editor, not just the sheet's star field. The screen paints its own
289
- // ToolBackground instead — see the mount site above.
290
- backgroundColor: night.color.bg
291
- },
292
- header: {
293
- flexDirection: "row",
294
- alignItems: "center",
295
- gap: 8,
296
- paddingHorizontal: 10,
297
- paddingVertical: 8,
298
- borderBottomWidth: 1,
299
- borderBottomColor: night.color.border
300
- },
301
- headerButton: {
302
- flexDirection: "row",
303
- alignItems: "center",
304
- gap: 4,
305
- paddingVertical: 6,
306
- paddingHorizontal: 4
307
- },
308
- headerRawText: {
309
- color: night.color.accent,
310
- fontSize: 12,
311
- fontWeight: "700"
312
- },
313
- headerTitle: {
314
- flex: 1,
315
- alignItems: "center",
316
- gap: 2
317
- },
318
- headerKey: {
319
- color: night.color.text,
320
- fontSize: 13,
321
- fontWeight: "600",
322
- fontFamily: monoFont
323
- },
324
- headerState: {
325
- color: night.color.textTertiary,
326
- fontSize: 10
327
- },
328
- headerDirty: {
329
- color: night.color.warning
330
- },
331
- metaRow: {
332
- flexDirection: "row",
333
- alignItems: "center",
334
- gap: 8,
335
- paddingHorizontal: 12,
336
- paddingVertical: 8
337
- },
338
- metaText: {
339
- color: night.color.textTertiary,
340
- fontSize: 11,
341
- fontFamily: monoFont
342
- },
343
- treeScroll: {
344
- flex: 1
345
- },
346
- treeContent: {
347
- paddingHorizontal: 12,
348
- paddingBottom: 16
349
- },
350
- treeCard: {
351
- backgroundColor: night.color.surface,
352
- borderRadius: 10,
353
- borderWidth: 1,
354
- borderColor: night.color.border,
355
- padding: 6
356
- },
357
- treeHint: {
358
- color: night.color.textTertiary,
359
- fontSize: 10,
360
- paddingTop: 8,
361
- paddingHorizontal: 4
362
- },
363
- error: {
364
- color: night.color.danger,
365
- fontSize: 11,
366
- fontFamily: monoFont,
367
- paddingHorizontal: 12,
368
- paddingBottom: 6
369
- },
370
- footer: {
371
- backgroundColor: night.color.surface
372
- },
373
- commitRow: {
374
- flexDirection: "row",
375
- gap: 8,
376
- paddingHorizontal: 10,
377
- paddingBottom: 12,
378
- paddingTop: 2
379
- },
380
- discardButton: {
381
- flex: 1,
382
- minHeight: 46,
383
- alignItems: "center",
384
- justifyContent: "center",
385
- borderRadius: 12,
386
- borderWidth: 1,
387
- borderColor: night.color.border
388
- },
389
- discardText: {
390
- color: night.color.textSecondary,
391
- fontSize: 14,
392
- fontWeight: "600"
393
- },
394
- saveButton: {
395
- flex: 1.6,
396
- minHeight: 46,
397
- alignItems: "center",
398
- justifyContent: "center",
399
- borderRadius: 12,
400
- backgroundColor: night.color.accent
401
- },
402
- saveDisabled: {
403
- opacity: 0.5
404
- },
405
- saveText: {
406
- color: night.color.onAccent,
407
- fontSize: 15,
408
- fontWeight: "700"
409
- }
410
- });
@@ -1,57 +0,0 @@
1
- "use strict";
2
-
3
- /**
4
- * Editing a key whose value is a single string, number or boolean.
5
- *
6
- * A tree of one row is not a tree, so there's nothing here to select, reorder
7
- * or append to — which means none of the structural editor applies. And with
8
- * one edit producing one write, there's nothing to buffer either: a draft would
9
- * only add a step between typing the value and storing it.
10
- *
11
- * So this is just the value modal over whatever the user was looking at, on
12
- * both the phone and the dashboard. Changing one string shouldn't black out the
13
- * screen it came from.
14
- */
15
-
16
- import { useCallback, useState } from "react";
17
- import { Alert } from "react-native";
18
- import { StorageValueEditModal } from "./StorageValueEditModal";
19
- import { jsx as _jsx } from "react/jsx-runtime";
20
- /**
21
- * The text `setStorageValue` should store.
22
- *
23
- * A string is stored AS ITSELF — `JSON.stringify` here was adding quotes a
24
- * plain string never had. AsyncStorage hid it (the browser reads values back
25
- * through `JSON.parse`, so the tool agreed with itself) but the app's own
26
- * `getItem` saw `"dark"` where it had written `dark`; MMKV stores strings
27
- * natively and showed the quotes right in the row, compounding on every edit.
28
- *
29
- * Everything else keeps JSON: for a number or a boolean that IS its text, and
30
- * containers never reach this editor.
31
- */
32
- function serializeScalar(value) {
33
- return typeof value === "string" ? value : JSON.stringify(value);
34
- }
35
- export function StorageScalarKeyEditor({
36
- storageKey,
37
- value,
38
- onSave,
39
- onClose
40
- }) {
41
- const [saving, setSaving] = useState(false);
42
- const save = useCallback(next => {
43
- if (saving) return;
44
- setSaving(true);
45
- onSave(serializeScalar(next)).then(onClose).catch(e => {
46
- setSaving(false);
47
- Alert.alert("Couldn't save", e instanceof Error ? e.message : String(e));
48
- });
49
- }, [onClose, onSave, saving]);
50
- return /*#__PURE__*/_jsx(StorageValueEditModal, {
51
- path: [storageKey.key],
52
- value: value,
53
- onSave: save,
54
- onCancel: onClose,
55
- busy: saving
56
- });
57
- }
@@ -1,20 +0,0 @@
1
- "use strict";
2
-
3
- /**
4
- * Storage's value-typing panel.
5
- *
6
- * The panel itself — top-pinned so the keyboard can't reach it, type preserved
7
- * by construction, raw-JSON shape check — lives in shared-ui's
8
- * {@link ValueEditModal}, shared with the Zustand store editor. This wrapper
9
- * only pins storage's testID namespace so the Detox suite's handles
10
- * (`buoy-storage-value-input`, `-save`, …) stay exactly what they were.
11
- */
12
-
13
- import { ValueEditModal } from "@buoy-gg/shared-ui/dataViewer";
14
- import { jsx as _jsx } from "react/jsx-runtime";
15
- export function StorageValueEditModal(props) {
16
- return /*#__PURE__*/_jsx(ValueEditModal, {
17
- ...props,
18
- testIDPrefix: "buoy-storage-value"
19
- });
20
- }
@@ -1,27 +0,0 @@
1
- "use strict";
2
-
3
- /**
4
- * Storage's view of the shared tree editor.
5
- *
6
- * Everything editing a key involves — buffered draft, selection, value modal,
7
- * dirty-close guard — lives in shared-ui's `useTreeEditor`, shared with the
8
- * Zustand store editor so the two can't drift. Storage's single write takes
9
- * the SERIALIZED value, so this wrapper is exactly the stringify.
10
- */
11
-
12
- import { useMemo } from "react";
13
- import { useTreeEditor } from "@buoy-gg/shared-ui/dataViewer";
14
- export function useKeyEditor({
15
- value,
16
- save,
17
- onClose,
18
- confirmDiscard
19
- }) {
20
- const saveValue = useMemo(() => next => save(JSON.stringify(next)), [save]);
21
- return useTreeEditor({
22
- value,
23
- save: saveValue,
24
- onClose,
25
- confirmDiscard
26
- });
27
- }
@@ -1,21 +0,0 @@
1
- "use strict";
2
-
3
- /**
4
- * Storage's view of the shared buffered tree draft.
5
- *
6
- * The draft itself lives in shared-ui (`useTreeDraft` there — one editor for
7
- * storage keys and zustand stores, so the rules can't drift). Storage's write
8
- * path takes the SERIALIZED value — `setItem(key, raw)` — so this wrapper is
9
- * exactly the stringify.
10
- */
11
-
12
- import { useMemo } from "react";
13
- import { useTreeDraft as useSharedTreeDraft } from "@buoy-gg/shared-ui/dataViewer";
14
- /**
15
- * @param liveValue the value as storage currently holds it (already parsed)
16
- * @param save persists the serialized draft; rejecting keeps edit mode open
17
- */
18
- export function useTreeDraft(liveValue, save) {
19
- const saveValue = useMemo(() => save ? value => save(JSON.stringify(value)) : undefined, [save]);
20
- return useSharedTreeDraft(liveValue, saveValue);
21
- }
@@ -1,18 +0,0 @@
1
- export type DiffCompareMethod = "chars" | "words" | "lines" | "trimmedLines";
2
- export interface DiffOptions {
3
- hideLineNumbers: boolean;
4
- disableWordDiff: boolean;
5
- showDiffOnly: boolean;
6
- compareMethod: DiffCompareMethod;
7
- contextLines: number;
8
- lineOffset: number;
9
- }
10
- interface DiffOptionsPanelProps {
11
- options: DiffOptions;
12
- onOptionsChange: (options: DiffOptions) => void;
13
- isExpanded: boolean;
14
- onToggleExpanded: () => void;
15
- }
16
- export declare function DiffOptionsPanel({ options, onOptionsChange, isExpanded, onToggleExpanded, }: DiffOptionsPanelProps): import("react").JSX.Element;
17
- export {};
18
- //# sourceMappingURL=DiffOptionsPanel.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DiffOptionsPanel.d.ts","sourceRoot":"","sources":["../../../../../src/storage/components/DiffViewer/DiffOptionsPanel.tsx"],"names":[],"mappings":"AAUA,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,cAAc,CAAC;AAE7E,MAAM,WAAW,WAAW;IAC1B,eAAe,EAAE,OAAO,CAAC;IACzB,eAAe,EAAE,OAAO,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,iBAAiB,CAAC;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,UAAU,qBAAqB;IAC7B,OAAO,EAAE,WAAW,CAAC;IACrB,eAAe,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IAChD,UAAU,EAAE,OAAO,CAAC;IACpB,gBAAgB,EAAE,MAAM,IAAI,CAAC;CAC9B;AA+BD,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,eAAe,EACf,UAAU,EACV,gBAAgB,GACjB,EAAE,qBAAqB,+BAwMvB"}
@@ -1,12 +0,0 @@
1
- import { ViewStyle } from "react-native";
2
- import type { DiffTheme } from "../themes/diffThemes";
3
- interface DiffSummaryProps {
4
- added: number;
5
- removed: number;
6
- modified: number;
7
- theme: DiffTheme;
8
- style?: ViewStyle;
9
- }
10
- export declare function DiffSummary({ added, removed, modified, theme, style, }: DiffSummaryProps): import("react").JSX.Element | null;
11
- export {};
12
- //# sourceMappingURL=DiffSummary.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DiffSummary.d.ts","sourceRoot":"","sources":["../../../../../../src/storage/components/DiffViewer/components/DiffSummary.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA0B,SAAS,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGtD,UAAU,gBAAgB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,CAAC;CACnB;AAED,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,OAAO,EACP,QAAQ,EACR,KAAK,EACL,KAAK,GACN,EAAE,gBAAgB,sCAiElB"}
@@ -1,42 +0,0 @@
1
- /**
2
- * Editing a key, on a screen of its own.
3
- *
4
- * Editing used to happen inside the expanded card in the key list: a tree a few
5
- * rows tall, an action bar wrapped onto three lines, and the rest of the list
6
- * still scrolling underneath. Every control was competing for the same ~200px.
7
- *
8
- * So the card now offers ONE edit button and the actual work happens here, with
9
- * the whole viewport: the tree gets the height, the six structural actions get
10
- * thumb-sized tiles docked at the bottom where they're always in the same
11
- * place, and manual JSON editing — the escape hatch, not the main path — moves
12
- * to a single button in the top-right corner.
13
- *
14
- * Typing a value happens in a modal pinned to the top of the screen, over the
15
- * tree rather than instead of it — see {@link StorageValueEditModal}.
16
- */
17
- import type { StorageKeyInfo } from "../types";
18
- interface StorageKeyEditorScreenProps {
19
- storageKey: StorageKeyInfo;
20
- /** Performs the write. Rejecting keeps the work on screen. */
21
- onSave: (raw: string) => Promise<void>;
22
- /** Leave the editor. Called only once any unsaved work is resolved. */
23
- onClose: () => void;
24
- /**
25
- * Pad the docked controls past the home indicator.
26
- *
27
- * These screens put their primary buttons flush against the bottom edge, so
28
- * without this the last row of tiles sits under the gesture bar. Off in a
29
- * floating window, whose own bottom edge is nowhere near the screen's.
30
- */
31
- applySafeAreaInset?: boolean;
32
- }
33
- /**
34
- * A container and a scalar are different editors, not one editor with a flag.
35
- *
36
- * A tree of one row is not a tree, so a scalar key skips the whole structural
37
- * editor and gets just the value modal. Splitting here keeps each editor's
38
- * state to what it actually needs — see {@link StorageScalarKeyEditor}.
39
- */
40
- export declare function StorageKeyEditorScreen(props: StorageKeyEditorScreenProps): import("react").JSX.Element;
41
- export {};
42
- //# sourceMappingURL=StorageKeyEditorScreen.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"StorageKeyEditorScreen.d.ts","sourceRoot":"","sources":["../../../../src/storage/components/StorageKeyEditorScreen.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAsBH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAO/C,UAAU,2BAA2B;IACnC,UAAU,EAAE,cAAc,CAAC;IAC3B,8DAA8D;IAC9D,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,uEAAuE;IACvE,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAOD;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,2BAA2B,+BAgBxE"}
@@ -1,24 +0,0 @@
1
- /**
2
- * Editing a key whose value is a single string, number or boolean.
3
- *
4
- * A tree of one row is not a tree, so there's nothing here to select, reorder
5
- * or append to — which means none of the structural editor applies. And with
6
- * one edit producing one write, there's nothing to buffer either: a draft would
7
- * only add a step between typing the value and storing it.
8
- *
9
- * So this is just the value modal over whatever the user was looking at, on
10
- * both the phone and the dashboard. Changing one string shouldn't black out the
11
- * screen it came from.
12
- */
13
- import type { StorageKeyInfo } from "../types";
14
- interface StorageScalarKeyEditorProps {
15
- storageKey: StorageKeyInfo;
16
- /** The value as storage holds it, already un-stringified. */
17
- value: unknown;
18
- /** Performs the write. Rejecting keeps the modal open with the draft intact. */
19
- onSave: (raw: string) => Promise<void>;
20
- onClose: () => void;
21
- }
22
- export declare function StorageScalarKeyEditor({ storageKey, value, onSave, onClose, }: StorageScalarKeyEditorProps): import("react").JSX.Element;
23
- export {};
24
- //# sourceMappingURL=StorageScalarKeyEditor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"StorageScalarKeyEditor.d.ts","sourceRoot":"","sources":["../../../../src/storage/components/StorageScalarKeyEditor.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG/C,UAAU,2BAA2B;IACnC,UAAU,EAAE,cAAc,CAAC;IAC3B,6DAA6D;IAC7D,KAAK,EAAE,OAAO,CAAC;IACf,gFAAgF;IAChF,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAkBD,wBAAgB,sBAAsB,CAAC,EACrC,UAAU,EACV,KAAK,EACL,MAAM,EACN,OAAO,GACR,EAAE,2BAA2B,+BA6B7B"}
@@ -1,14 +0,0 @@
1
- /**
2
- * Storage's value-typing panel.
3
- *
4
- * The panel itself — top-pinned so the keyboard can't reach it, type preserved
5
- * by construction, raw-JSON shape check — lives in shared-ui's
6
- * {@link ValueEditModal}, shared with the Zustand store editor. This wrapper
7
- * only pins storage's testID namespace so the Detox suite's handles
8
- * (`buoy-storage-value-input`, `-save`, …) stay exactly what they were.
9
- */
10
- import { type ValueEditModalProps } from "@buoy-gg/shared-ui/dataViewer";
11
- type StorageValueEditModalProps = Omit<ValueEditModalProps, "testIDPrefix">;
12
- export declare function StorageValueEditModal(props: StorageValueEditModalProps): import("react").JSX.Element;
13
- export {};
14
- //# sourceMappingURL=StorageValueEditModal.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"StorageValueEditModal.d.ts","sourceRoot":"","sources":["../../../../src/storage/components/StorageValueEditModal.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,+BAA+B,CAAC;AAEvC,KAAK,0BAA0B,GAAG,IAAI,CAAC,mBAAmB,EAAE,cAAc,CAAC,CAAC;AAE5E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,0BAA0B,+BAEtE"}