@buoy-gg/shared-ui 7.0.16 → 7.0.18

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 (111) hide show
  1. package/lib/commonjs/dataViewer/ThemedSplitView.js +622 -0
  2. package/lib/commonjs/dataViewer/index.js +32 -0
  3. package/lib/commonjs/dataViewer/objectDiff.js +304 -0
  4. package/lib/commonjs/hooks/index.js +7 -0
  5. package/lib/commonjs/hooks/safe-area-impl.js +1 -1
  6. package/lib/commonjs/hooks/usePersistedState.js +71 -0
  7. package/lib/commonjs/icons/index.js +14 -0
  8. package/lib/commonjs/index.js +61 -0
  9. package/lib/commonjs/storage/devToolsStorageKeys.js +31 -0
  10. package/lib/commonjs/sync/wireBudget.js +97 -0
  11. package/lib/commonjs/ui/components/HeaderSearchButton.js +6 -1
  12. package/lib/commonjs/ui/components/ModalHeader.js +69 -0
  13. package/lib/commonjs/ui/components/ToolButton.js +90 -0
  14. package/lib/commonjs/ui/components/index.js +7 -0
  15. package/lib/commonjs/ui/index.js +8 -0
  16. package/lib/commonjs/ui/toolTheme.js +96 -0
  17. package/lib/commonjs/utils/index.js +38 -0
  18. package/lib/commonjs/utils/persistentStorage.js +6 -3
  19. package/lib/commonjs/utils/stateSnapshotRegistry.js +71 -0
  20. package/lib/module/dataViewer/ThemedSplitView.js +617 -0
  21. package/lib/module/dataViewer/index.js +7 -1
  22. package/lib/module/dataViewer/objectDiff.js +297 -0
  23. package/lib/module/hooks/index.js +1 -0
  24. package/lib/module/hooks/safe-area-impl.js +1 -1
  25. package/lib/module/hooks/usePersistedState.js +68 -0
  26. package/lib/module/icons/index.js +1 -0
  27. package/lib/module/index.js +6 -1
  28. package/lib/module/storage/devToolsStorageKeys.js +31 -0
  29. package/lib/module/sync/wireBudget.js +92 -0
  30. package/lib/module/ui/components/HeaderSearchButton.js +6 -1
  31. package/lib/module/ui/components/ModalHeader.js +70 -2
  32. package/lib/module/ui/components/ToolButton.js +86 -0
  33. package/lib/module/ui/components/index.js +1 -0
  34. package/lib/module/ui/index.js +3 -0
  35. package/lib/module/ui/toolTheme.js +93 -0
  36. package/lib/module/utils/index.js +2 -0
  37. package/lib/module/utils/persistentStorage.js +6 -3
  38. package/lib/module/utils/stateSnapshotRegistry.js +64 -0
  39. package/lib/typescript/commonjs/dataViewer/ThemedSplitView.d.ts +28 -0
  40. package/lib/typescript/commonjs/dataViewer/ThemedSplitView.d.ts.map +1 -0
  41. package/lib/typescript/commonjs/dataViewer/index.d.ts +2 -0
  42. package/lib/typescript/commonjs/dataViewer/index.d.ts.map +1 -1
  43. package/lib/typescript/commonjs/dataViewer/objectDiff.d.ts +67 -0
  44. package/lib/typescript/commonjs/dataViewer/objectDiff.d.ts.map +1 -0
  45. package/lib/typescript/commonjs/hooks/index.d.ts +1 -0
  46. package/lib/typescript/commonjs/hooks/index.d.ts.map +1 -1
  47. package/lib/typescript/commonjs/hooks/safe-area-impl.d.ts +1 -1
  48. package/lib/typescript/commonjs/hooks/usePersistedState.d.ts +16 -0
  49. package/lib/typescript/commonjs/hooks/usePersistedState.d.ts.map +1 -0
  50. package/lib/typescript/commonjs/icons/index.d.ts +1 -0
  51. package/lib/typescript/commonjs/icons/index.d.ts.map +1 -1
  52. package/lib/typescript/commonjs/index.d.ts +3 -2
  53. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  54. package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts +28 -0
  55. package/lib/typescript/commonjs/storage/devToolsStorageKeys.d.ts.map +1 -1
  56. package/lib/typescript/commonjs/sync/wireBudget.d.ts +50 -0
  57. package/lib/typescript/commonjs/sync/wireBudget.d.ts.map +1 -0
  58. package/lib/typescript/commonjs/ui/components/HeaderSearchButton.d.ts +3 -1
  59. package/lib/typescript/commonjs/ui/components/HeaderSearchButton.d.ts.map +1 -1
  60. package/lib/typescript/commonjs/ui/components/ModalHeader.d.ts +13 -1
  61. package/lib/typescript/commonjs/ui/components/ModalHeader.d.ts.map +1 -1
  62. package/lib/typescript/commonjs/ui/components/ToolButton.d.ts +24 -0
  63. package/lib/typescript/commonjs/ui/components/ToolButton.d.ts.map +1 -0
  64. package/lib/typescript/commonjs/ui/components/index.d.ts +4 -0
  65. package/lib/typescript/commonjs/ui/components/index.d.ts.map +1 -1
  66. package/lib/typescript/commonjs/ui/index.d.ts +1 -0
  67. package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
  68. package/lib/typescript/commonjs/ui/toolTheme.d.ts +68 -0
  69. package/lib/typescript/commonjs/ui/toolTheme.d.ts.map +1 -0
  70. package/lib/typescript/commonjs/utils/index.d.ts +2 -0
  71. package/lib/typescript/commonjs/utils/index.d.ts.map +1 -1
  72. package/lib/typescript/commonjs/utils/persistentStorage.d.ts.map +1 -1
  73. package/lib/typescript/commonjs/utils/stateSnapshotRegistry.d.ts +111 -0
  74. package/lib/typescript/commonjs/utils/stateSnapshotRegistry.d.ts.map +1 -0
  75. package/lib/typescript/module/dataViewer/ThemedSplitView.d.ts +28 -0
  76. package/lib/typescript/module/dataViewer/ThemedSplitView.d.ts.map +1 -0
  77. package/lib/typescript/module/dataViewer/index.d.ts +2 -0
  78. package/lib/typescript/module/dataViewer/index.d.ts.map +1 -1
  79. package/lib/typescript/module/dataViewer/objectDiff.d.ts +67 -0
  80. package/lib/typescript/module/dataViewer/objectDiff.d.ts.map +1 -0
  81. package/lib/typescript/module/hooks/index.d.ts +1 -0
  82. package/lib/typescript/module/hooks/index.d.ts.map +1 -1
  83. package/lib/typescript/module/hooks/safe-area-impl.d.ts +1 -1
  84. package/lib/typescript/module/hooks/usePersistedState.d.ts +16 -0
  85. package/lib/typescript/module/hooks/usePersistedState.d.ts.map +1 -0
  86. package/lib/typescript/module/icons/index.d.ts +1 -0
  87. package/lib/typescript/module/icons/index.d.ts.map +1 -1
  88. package/lib/typescript/module/index.d.ts +3 -2
  89. package/lib/typescript/module/index.d.ts.map +1 -1
  90. package/lib/typescript/module/storage/devToolsStorageKeys.d.ts +28 -0
  91. package/lib/typescript/module/storage/devToolsStorageKeys.d.ts.map +1 -1
  92. package/lib/typescript/module/sync/wireBudget.d.ts +50 -0
  93. package/lib/typescript/module/sync/wireBudget.d.ts.map +1 -0
  94. package/lib/typescript/module/ui/components/HeaderSearchButton.d.ts +3 -1
  95. package/lib/typescript/module/ui/components/HeaderSearchButton.d.ts.map +1 -1
  96. package/lib/typescript/module/ui/components/ModalHeader.d.ts +13 -1
  97. package/lib/typescript/module/ui/components/ModalHeader.d.ts.map +1 -1
  98. package/lib/typescript/module/ui/components/ToolButton.d.ts +24 -0
  99. package/lib/typescript/module/ui/components/ToolButton.d.ts.map +1 -0
  100. package/lib/typescript/module/ui/components/index.d.ts +4 -0
  101. package/lib/typescript/module/ui/components/index.d.ts.map +1 -1
  102. package/lib/typescript/module/ui/index.d.ts +1 -0
  103. package/lib/typescript/module/ui/index.d.ts.map +1 -1
  104. package/lib/typescript/module/ui/toolTheme.d.ts +68 -0
  105. package/lib/typescript/module/ui/toolTheme.d.ts.map +1 -0
  106. package/lib/typescript/module/utils/index.d.ts +2 -0
  107. package/lib/typescript/module/utils/index.d.ts.map +1 -1
  108. package/lib/typescript/module/utils/persistentStorage.d.ts.map +1 -1
  109. package/lib/typescript/module/utils/stateSnapshotRegistry.d.ts +111 -0
  110. package/lib/typescript/module/utils/stateSnapshotRegistry.d.ts.map +1 -0
  111. package/package.json +4 -4
@@ -12,12 +12,17 @@ function HeaderSearchButton({
12
12
  onPress,
13
13
  size = 14,
14
14
  color = _index2.gameUIColors.secondary,
15
- style
15
+ style,
16
+ accessibilityLabel = "Search",
17
+ testID
16
18
  }) {
17
19
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
18
20
  onPress: onPress,
19
21
  style: [styles.button, style],
20
22
  activeOpacity: 0.7,
23
+ accessibilityRole: "button",
24
+ accessibilityLabel: accessibilityLabel,
25
+ testID: testID,
21
26
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.Search, {
22
27
  size: size,
23
28
  color: color
@@ -5,9 +5,11 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.Actions = Actions;
7
7
  exports.Content = Content;
8
+ exports.HeaderSearch = HeaderSearch;
8
9
  exports.ModalHeader = ModalHeader;
9
10
  exports.Navigation = Navigation;
10
11
  var _reactNative = require("react-native");
12
+ var _react = require("react");
11
13
  var _index = require("../../icons/index.js");
12
14
  var _gameUIColors = require("../gameUI/constants/gameUIColors.js");
13
15
  var _jsxRuntime = require("react/jsx-runtime");
@@ -118,10 +120,51 @@ function Actions({
118
120
  }
119
121
  Actions.displayName = "ModalHeaderActions";
120
122
 
123
+ // Expanding search input for the header. Render this IN PLACE OF
124
+ // `ModalHeader.Content` while search is active — it fills the same flex slot.
125
+ // Extracts the idiom env/network/storage each hand-rolled (~50 lines apiece).
126
+
127
+ function HeaderSearch({
128
+ value,
129
+ onChangeText,
130
+ onCancel,
131
+ placeholder = "Search...",
132
+ autoFocus = true
133
+ }) {
134
+ const inputRef = (0, _react.useRef)(null);
135
+ (0, _react.useEffect)(() => {
136
+ if (autoFocus) inputRef.current?.focus();
137
+ }, [autoFocus]);
138
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
139
+ style: styles.searchContainer,
140
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_index.Search, {
141
+ size: 12,
142
+ color: _gameUIColors.buoyColors.textSecondary
143
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TextInput, {
144
+ ref: inputRef,
145
+ style: styles.searchInput,
146
+ placeholder: placeholder,
147
+ placeholderTextColor: _gameUIColors.buoyColors.textMuted,
148
+ value: value,
149
+ onChangeText: onChangeText,
150
+ autoCorrect: false,
151
+ autoCapitalize: "none"
152
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
153
+ onPress: onCancel,
154
+ style: styles.searchCancelButton,
155
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_index.X, {
156
+ size: 12,
157
+ color: _gameUIColors.buoyColors.textSecondary
158
+ })
159
+ })]
160
+ });
161
+ }
162
+
121
163
  // Attach sub-components to the main component
122
164
  ModalHeader.Navigation = Navigation;
123
165
  ModalHeader.Content = Content;
124
166
  ModalHeader.Actions = Actions;
167
+ ModalHeader.Search = HeaderSearch;
125
168
  const styles = _reactNative.StyleSheet.create({
126
169
  headerContainer: {
127
170
  flexDirection: "row",
@@ -169,5 +212,31 @@ const styles = _reactNative.StyleSheet.create({
169
212
  },
170
213
  headerContentNoMargin: {
171
214
  marginHorizontal: 0
215
+ },
216
+ searchContainer: {
217
+ flexDirection: "row",
218
+ alignItems: "center",
219
+ flex: 1,
220
+ backgroundColor: _gameUIColors.buoyColors.input,
221
+ borderRadius: 6,
222
+ paddingHorizontal: 10,
223
+ paddingVertical: 4,
224
+ marginHorizontal: 12,
225
+ marginVertical: 4,
226
+ height: 32,
227
+ borderWidth: 1,
228
+ borderColor: _gameUIColors.buoyColors.border
229
+ },
230
+ searchInput: {
231
+ flex: 1,
232
+ marginLeft: 8,
233
+ fontSize: 13,
234
+ color: _gameUIColors.buoyColors.text,
235
+ padding: 0,
236
+ height: "100%"
237
+ },
238
+ searchCancelButton: {
239
+ padding: 4,
240
+ marginLeft: 4
172
241
  }
173
242
  });
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ToolButton = ToolButton;
7
+ var _reactNative = require("react-native");
8
+ var _gameUIColors = require("../gameUI/constants/gameUIColors.js");
9
+ var _jsxRuntime = require("react/jsx-runtime");
10
+ /**
11
+ * The shared action button for dev-tool surfaces. Fills the gap where every
12
+ * tool hand-styled its own TouchableOpacity for "Clear", "Apply", "Reset".
13
+ */
14
+ function ToolButton({
15
+ label,
16
+ onPress,
17
+ variant = "primary",
18
+ size = "medium",
19
+ disabled = false,
20
+ icon,
21
+ style
22
+ }) {
23
+ const palette = VARIANTS[variant];
24
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
25
+ accessibilityRole: "button",
26
+ accessibilityLabel: label,
27
+ onPress: onPress,
28
+ disabled: disabled,
29
+ style: [styles.base, size === "small" ? styles.small : styles.medium, {
30
+ backgroundColor: palette.background,
31
+ borderColor: palette.border,
32
+ borderWidth: variant === "ghost" ? 0 : 1
33
+ }, disabled && styles.disabled, style],
34
+ children: [icon, /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
35
+ style: [styles.label, size === "small" && styles.labelSmall, {
36
+ color: palette.text
37
+ }],
38
+ children: label
39
+ })]
40
+ });
41
+ }
42
+ const VARIANTS = {
43
+ primary: {
44
+ background: _gameUIColors.buoyColors.primary + "22",
45
+ border: _gameUIColors.buoyColors.primary + "66",
46
+ text: _gameUIColors.buoyColors.primary
47
+ },
48
+ danger: {
49
+ background: _gameUIColors.gameUIColors.error + "15",
50
+ border: _gameUIColors.gameUIColors.error + "60",
51
+ text: _gameUIColors.gameUIColors.error
52
+ },
53
+ warning: {
54
+ background: _gameUIColors.gameUIColors.warning + "15",
55
+ border: _gameUIColors.gameUIColors.warning + "60",
56
+ text: _gameUIColors.gameUIColors.warning
57
+ },
58
+ ghost: {
59
+ background: "transparent",
60
+ border: "transparent",
61
+ text: _gameUIColors.buoyColors.textSecondary
62
+ }
63
+ };
64
+ const styles = _reactNative.StyleSheet.create({
65
+ base: {
66
+ flexDirection: "row",
67
+ alignItems: "center",
68
+ justifyContent: "center",
69
+ gap: 6,
70
+ borderRadius: 8
71
+ },
72
+ medium: {
73
+ paddingVertical: 8,
74
+ paddingHorizontal: 14
75
+ },
76
+ small: {
77
+ paddingVertical: 5,
78
+ paddingHorizontal: 10
79
+ },
80
+ disabled: {
81
+ opacity: 0.4
82
+ },
83
+ label: {
84
+ fontSize: 12,
85
+ fontWeight: "600"
86
+ },
87
+ labelSmall: {
88
+ fontSize: 11
89
+ }
90
+ });
@@ -297,6 +297,12 @@ Object.defineProperty(exports, "TimeDisplay", {
297
297
  return _TimeDisplay.TimeDisplay;
298
298
  }
299
299
  });
300
+ Object.defineProperty(exports, "ToolButton", {
301
+ enumerable: true,
302
+ get: function () {
303
+ return _ToolButton.ToolButton;
304
+ }
305
+ });
300
306
  Object.defineProperty(exports, "ToolbarClearButton", {
301
307
  enumerable: true,
302
308
  get: function () {
@@ -352,6 +358,7 @@ var _FilterComponents = require("./FilterComponents.js");
352
358
  var _CompactFilterChips = require("./CompactFilterChips.js");
353
359
  var _Badge = require("./Badge.js");
354
360
  var _TabSelector = require("./TabSelector.js");
361
+ var _ToolButton = require("./ToolButton.js");
355
362
  var _EventListItem = require("./EventListItem.js");
356
363
  var _StatsCard = require("./StatsCard.js");
357
364
  var _CompactRow = require("./CompactRow.js");
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  var _exportNames = {
7
+ toolTheme: true,
7
8
  CyberpunkSectionButton: true
8
9
  };
9
10
  Object.defineProperty(exports, "CyberpunkSectionButton", {
@@ -12,6 +13,12 @@ Object.defineProperty(exports, "CyberpunkSectionButton", {
12
13
  return _CyberpunkSectionButton.CyberpunkSectionButton;
13
14
  }
14
15
  });
16
+ Object.defineProperty(exports, "toolTheme", {
17
+ enumerable: true,
18
+ get: function () {
19
+ return _toolTheme.toolTheme;
20
+ }
21
+ });
15
22
  var _index = require("./components/index.js");
16
23
  Object.keys(_index).forEach(function (key) {
17
24
  if (key === "default" || key === "__esModule") return;
@@ -24,6 +31,7 @@ Object.keys(_index).forEach(function (key) {
24
31
  }
25
32
  });
26
33
  });
34
+ var _toolTheme = require("./toolTheme.js");
27
35
  var _CyberpunkSectionButton = require("./console/CyberpunkSectionButton.js");
28
36
  var _index2 = require("./gameUI/index.js");
29
37
  Object.keys(_index2).forEach(function (key) {
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.toolTheme = void 0;
7
+ var _gameUIColors = require("./gameUI/constants/gameUIColors.js");
8
+ /**
9
+ * Semantic design tokens for dev-tool surfaces — the single documented entry
10
+ * point for custom-tool authors (and, over time, internal tools).
11
+ *
12
+ * Buoy historically grew three color systems (`buoyColors`, `gameUIColors`,
13
+ * `macOSColors`) with tribal knowledge about which to use where. `toolTheme`
14
+ * encodes that knowledge: surfaces/text come from the brand palette, semantic
15
+ * status colors from the gameUI palette. Consumers should not need to know
16
+ * that split exists.
17
+ */
18
+ const toolTheme = exports.toolTheme = {
19
+ colors: {
20
+ /** Modal/page background. */
21
+ surface: _gameUIColors.buoyColors.base,
22
+ /** Card / row background, one step above surface. */
23
+ card: _gameUIColors.buoyColors.card,
24
+ /** Pressed/hover background. */
25
+ hover: _gameUIColors.buoyColors.hover,
26
+ /** Text-input background. */
27
+ input: _gameUIColors.buoyColors.input,
28
+ border: _gameUIColors.buoyColors.border,
29
+ borderStrong: _gameUIColors.buoyColors.borderStrong,
30
+ text: _gameUIColors.buoyColors.text,
31
+ textSecondary: _gameUIColors.buoyColors.textSecondary,
32
+ textMuted: _gameUIColors.buoyColors.textMuted,
33
+ /** Buoy teal — primary accent. */
34
+ accent: _gameUIColors.buoyColors.primary,
35
+ success: _gameUIColors.gameUIColors.success,
36
+ warning: _gameUIColors.gameUIColors.warning,
37
+ error: _gameUIColors.gameUIColors.error,
38
+ info: _gameUIColors.gameUIColors.info
39
+ },
40
+ /**
41
+ * Text presets matching the styles internal tools re-declare per file.
42
+ * Spread into a style: `style={[toolTheme.text.label, { color: ... }]}`.
43
+ */
44
+ text: {
45
+ /** Modal/section titles. */
46
+ title: {
47
+ fontSize: 14,
48
+ fontWeight: "600",
49
+ color: _gameUIColors.buoyColors.text
50
+ },
51
+ /** Default body copy. */
52
+ body: {
53
+ fontSize: 13,
54
+ color: _gameUIColors.buoyColors.text
55
+ },
56
+ /** Secondary copy under a primary line. */
57
+ subtitle: {
58
+ fontSize: 12,
59
+ color: _gameUIColors.buoyColors.textSecondary
60
+ },
61
+ /** ALL-CAPS section labels ("LOCAL OVERRIDES"). */
62
+ label: {
63
+ fontSize: 10,
64
+ fontWeight: "700",
65
+ color: _gameUIColors.buoyColors.textMuted,
66
+ letterSpacing: 1.2,
67
+ fontFamily: "monospace"
68
+ },
69
+ /** Monospace values (keys, ids, payload snippets). */
70
+ mono: {
71
+ fontSize: 11,
72
+ color: _gameUIColors.buoyColors.textSecondary,
73
+ fontFamily: "monospace"
74
+ },
75
+ /** Timestamps and fine print. */
76
+ small: {
77
+ fontSize: 9,
78
+ color: _gameUIColors.buoyColors.textMuted,
79
+ fontFamily: "monospace"
80
+ }
81
+ },
82
+ /** 4-based spacing scale used across tool surfaces. */
83
+ spacing: {
84
+ xs: 4,
85
+ sm: 8,
86
+ md: 12,
87
+ lg: 16,
88
+ xl: 24
89
+ },
90
+ radius: {
91
+ sm: 6,
92
+ md: 8,
93
+ lg: 12,
94
+ pill: 9999
95
+ }
96
+ };
@@ -81,6 +81,18 @@ Object.defineProperty(exports, "getSafeRouter", {
81
81
  return _safeExpoRouter.getSafeRouter;
82
82
  }
83
83
  });
84
+ Object.defineProperty(exports, "getStateSnapshotProvider", {
85
+ enumerable: true,
86
+ get: function () {
87
+ return _stateSnapshotRegistry.getStateSnapshotProvider;
88
+ }
89
+ });
90
+ Object.defineProperty(exports, "getStateSnapshotProviders", {
91
+ enumerable: true,
92
+ get: function () {
93
+ return _stateSnapshotRegistry.getStateSnapshotProviders;
94
+ }
95
+ });
84
96
  Object.defineProperty(exports, "getStorageBackendType", {
85
97
  enumerable: true,
86
98
  get: function () {
@@ -171,6 +183,12 @@ Object.defineProperty(exports, "persistentStorage", {
171
183
  return _persistentStorage.persistentStorage;
172
184
  }
173
185
  });
186
+ Object.defineProperty(exports, "registerStateSnapshotProvider", {
187
+ enumerable: true,
188
+ get: function () {
189
+ return _stateSnapshotRegistry.registerStateSnapshotProvider;
190
+ }
191
+ });
174
192
  Object.defineProperty(exports, "reloadApp", {
175
193
  enumerable: true,
176
194
  get: function () {
@@ -201,6 +219,12 @@ Object.defineProperty(exports, "setRenderCaptureProvider", {
201
219
  return _renderCaptureRegistry.setRenderCaptureProvider;
202
220
  }
203
221
  });
222
+ Object.defineProperty(exports, "subscribeToStateSnapshotProviders", {
223
+ enumerable: true,
224
+ get: function () {
225
+ return _stateSnapshotRegistry.subscribeToStateSnapshotProviders;
226
+ }
227
+ });
204
228
  Object.defineProperty(exports, "subscribeToSubscriberCountChanges", {
205
229
  enumerable: true,
206
230
  get: function () {
@@ -213,6 +237,18 @@ Object.defineProperty(exports, "subscriberCountNotifier", {
213
237
  return _subscriberCountNotifier.subscriberCountNotifier;
214
238
  }
215
239
  });
240
+ Object.defineProperty(exports, "superJsonDeserialize", {
241
+ enumerable: true,
242
+ get: function () {
243
+ return _minimalSuperJSON.deserialize;
244
+ }
245
+ });
246
+ Object.defineProperty(exports, "superJsonSerialize", {
247
+ enumerable: true,
248
+ get: function () {
249
+ return _minimalSuperJSON.serialize;
250
+ }
251
+ });
216
252
  Object.defineProperty(exports, "truncateText", {
217
253
  enumerable: true,
218
254
  get: function () {
@@ -252,6 +288,8 @@ var _typeHelpers = require("./typeHelpers.js");
252
288
  var _valueFormatting = require("./valueFormatting.js");
253
289
  var _loadOptionalModule = require("./loadOptionalModule.js");
254
290
  var _renderCaptureRegistry = require("./renderCaptureRegistry.js");
291
+ var _stateSnapshotRegistry = require("./stateSnapshotRegistry.js");
292
+ var _minimalSuperJSON = require("./minimalSuperJSON.js");
255
293
  var _reloadApp = require("./reloadApp.js");
256
294
  var _subscribable = require("./subscribable.js");
257
295
  var _subscriberCountNotifier = require("./subscriberCountNotifier.js");
@@ -492,6 +492,12 @@ async function initStorage() {
492
492
  await migrateFromAsyncStorage();
493
493
  }
494
494
  storageBackend = "filesystem";
495
+ } else if (isWebEnvironment()) {
496
+ // Prefer localStorage on web (marketing site, RN-web, Electron renderer)
497
+ // BEFORE AsyncStorage. Hosts often alias AsyncStorage to a demo/remote
498
+ // shim that must not own buoy prefs — and must not trip the "fallback"
499
+ // warning on every page load.
500
+ storageBackend = "localstorage";
495
501
  } else {
496
502
  // Try AsyncStorage (React Native)
497
503
  const asyncStorage = loadAsyncStorage();
@@ -501,9 +507,6 @@ async function initStorage() {
501
507
  initWarningShown = true;
502
508
  console.warn("[React Buoy] Using AsyncStorage fallback. " + "Settings may be lost if AsyncStorage is cleared. " + "Install expo-file-system for persistent storage.");
503
509
  }
504
- } else if (isWebEnvironment()) {
505
- // Try localStorage (Web)
506
- storageBackend = "localstorage";
507
510
  } else {
508
511
  storageBackend = "memory";
509
512
  if (!initWarningShown) {
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getStateSnapshotProvider = getStateSnapshotProvider;
7
+ exports.getStateSnapshotProviders = getStateSnapshotProviders;
8
+ exports.registerStateSnapshotProvider = registerStateSnapshotProvider;
9
+ exports.subscribeToStateSnapshotProviders = subscribeToStateSnapshotProviders;
10
+ /**
11
+ * Cross-package bridge for app-state snapshot & restore (Time Machine).
12
+ *
13
+ * Each state tool (`@buoy-gg/storage`, `@buoy-gg/redux`, `@buoy-gg/zustand`,
14
+ * `@buoy-gg/jotai`, `@buoy-gg/react-query`) registers a provider here at
15
+ * module init (or from its app-lifetime sync hook); `@buoy-gg/time-machine`
16
+ * consumes the registry. Neither side imports the other — same
17
+ * optional-capability pattern as renderCaptureRegistry.
18
+ *
19
+ * Apps can also register custom providers for state Buoy doesn't know about.
20
+ */
21
+
22
+ /**
23
+ * Per-item verdict in a Restore Preview. The critical distinction:
24
+ * "changed" means the restore WILL apply this difference; "wont-apply" means
25
+ * a difference exists (or an item does) that restore can NOT apply, with the
26
+ * reason. A preview that shows raw diffs without this distinction lies.
27
+ */
28
+
29
+ // beyond diff budgets; treated as changed, not rendered
30
+
31
+ const providers = new Map();
32
+ const listeners = new Set();
33
+ function notify() {
34
+ listeners.forEach(l => {
35
+ try {
36
+ l();
37
+ } catch {
38
+ // listener errors must not break registration
39
+ }
40
+ });
41
+ }
42
+
43
+ /**
44
+ * Register a provider. Last registration wins for a given id.
45
+ * Returns an unregister function (only removes the provider if it is still
46
+ * the registered one for that id).
47
+ */
48
+ function registerStateSnapshotProvider(provider) {
49
+ providers.set(provider.id, provider);
50
+ notify();
51
+ return () => {
52
+ if (providers.get(provider.id) === provider) {
53
+ providers.delete(provider.id);
54
+ notify();
55
+ }
56
+ };
57
+ }
58
+ function getStateSnapshotProviders() {
59
+ return Array.from(providers.values());
60
+ }
61
+ function getStateSnapshotProvider(id) {
62
+ return providers.get(id) ?? null;
63
+ }
64
+
65
+ /** Notifies when providers register/unregister (query registers late). */
66
+ function subscribeToStateSnapshotProviders(listener) {
67
+ listeners.add(listener);
68
+ return () => {
69
+ listeners.delete(listener);
70
+ };
71
+ }