@buoy-gg/zustand 7.0.38 → 7.0.40

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 (62) hide show
  1. package/lib/commonjs/index.js +105 -1
  2. package/lib/commonjs/preset.js +102 -1
  3. package/lib/commonjs/zustand/components/ZustandActionButton.js +118 -1
  4. package/lib/commonjs/zustand/components/ZustandDetailViewToggle.js +48 -1
  5. package/lib/commonjs/zustand/components/ZustandEventFilterView.js +43 -1
  6. package/lib/commonjs/zustand/components/ZustandIcon.js +18 -1
  7. package/lib/commonjs/zustand/components/ZustandModal.js +772 -1
  8. package/lib/commonjs/zustand/components/ZustandStateChangeItem.js +117 -1
  9. package/lib/commonjs/zustand/components/ZustandStateDetailContent.js +372 -1
  10. package/lib/commonjs/zustand/components/ZustandStateInfoView.js +488 -1
  11. package/lib/commonjs/zustand/components/ZustandStoreBrowser.js +204 -1
  12. package/lib/commonjs/zustand/components/ZustandStoreDetailContent.js +471 -1
  13. package/lib/commonjs/zustand/components/ZustandStoreEditorScreen.js +393 -1
  14. package/lib/commonjs/zustand/hooks/useZustandStateChanges.js +74 -1
  15. package/lib/commonjs/zustand/sync/zustandSyncAdapter.js +382 -1
  16. package/lib/commonjs/zustand/utils/buoyZustandMiddleware.js +284 -1
  17. package/lib/commonjs/zustand/utils/editableState.js +146 -1
  18. package/lib/commonjs/zustand/utils/snapshotProvider.js +209 -1
  19. package/lib/commonjs/zustand/utils/testIDs.js +82 -1
  20. package/lib/commonjs/zustand/utils/zustandStateStore.js +379 -1
  21. package/lib/module/index.js +90 -1
  22. package/lib/module/preset.js +98 -1
  23. package/lib/module/zustand/components/ZustandActionButton.js +114 -1
  24. package/lib/module/zustand/components/ZustandDetailViewToggle.js +43 -1
  25. package/lib/module/zustand/components/ZustandEventFilterView.js +39 -1
  26. package/lib/module/zustand/components/ZustandIcon.js +11 -1
  27. package/lib/module/zustand/components/ZustandModal.js +767 -1
  28. package/lib/module/zustand/components/ZustandStateChangeItem.js +113 -1
  29. package/lib/module/zustand/components/ZustandStateDetailContent.js +368 -1
  30. package/lib/module/zustand/components/ZustandStateInfoView.js +483 -1
  31. package/lib/module/zustand/components/ZustandStoreBrowser.js +200 -1
  32. package/lib/module/zustand/components/ZustandStoreDetailContent.js +469 -1
  33. package/lib/module/zustand/components/ZustandStoreEditorScreen.js +389 -1
  34. package/lib/module/zustand/hooks/useZustandStateChanges.js +70 -1
  35. package/lib/module/zustand/sync/zustandSyncAdapter.js +380 -1
  36. package/lib/module/zustand/utils/buoyZustandMiddleware.js +278 -1
  37. package/lib/module/zustand/utils/editableState.js +138 -1
  38. package/lib/module/zustand/utils/snapshotProvider.js +209 -1
  39. package/lib/module/zustand/utils/testIDs.js +74 -1
  40. package/lib/module/zustand/utils/zustandStateStore.js +375 -1
  41. package/lib/typescript/index.d.ts.map +1 -0
  42. package/lib/typescript/preset.d.ts.map +1 -0
  43. package/lib/typescript/zustand/components/ZustandActionButton.d.ts.map +1 -0
  44. package/lib/typescript/zustand/components/ZustandDetailViewToggle.d.ts.map +1 -0
  45. package/lib/typescript/zustand/components/ZustandEventFilterView.d.ts.map +1 -0
  46. package/lib/typescript/zustand/components/ZustandIcon.d.ts.map +1 -0
  47. package/lib/typescript/zustand/components/ZustandModal.d.ts.map +1 -0
  48. package/lib/typescript/zustand/components/ZustandStateChangeItem.d.ts.map +1 -0
  49. package/lib/typescript/zustand/components/ZustandStateDetailContent.d.ts.map +1 -0
  50. package/lib/typescript/zustand/components/ZustandStateInfoView.d.ts.map +1 -0
  51. package/lib/typescript/zustand/components/ZustandStoreBrowser.d.ts.map +1 -0
  52. package/lib/typescript/zustand/components/ZustandStoreDetailContent.d.ts.map +1 -0
  53. package/lib/typescript/zustand/components/ZustandStoreEditorScreen.d.ts.map +1 -0
  54. package/lib/typescript/zustand/hooks/useZustandStateChanges.d.ts.map +1 -0
  55. package/lib/typescript/zustand/sync/zustandSyncAdapter.d.ts.map +1 -0
  56. package/lib/typescript/zustand/types/index.d.ts.map +1 -0
  57. package/lib/typescript/zustand/utils/buoyZustandMiddleware.d.ts.map +1 -0
  58. package/lib/typescript/zustand/utils/editableState.d.ts.map +1 -0
  59. package/lib/typescript/zustand/utils/snapshotProvider.d.ts.map +1 -0
  60. package/lib/typescript/zustand/utils/testIDs.d.ts.map +1 -0
  61. package/lib/typescript/zustand/utils/zustandStateStore.d.ts.map +1 -0
  62. package/package.json +3 -3
@@ -1 +1,204 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.ZustandStoreBrowser=ZustandStoreBrowser;var _react=require("react"),_reactNative=require("react-native"),_sharedUi=require("@buoy-gg/shared-ui"),_zustandStateStore=require("../utils/zustandStateStore"),_testIDs=require("../utils/testIDs"),_jsxRuntime=require("react/jsx-runtime");function getKeysPreview(e){try{const t=e.api.getState();if(t&&"object"==typeof t&&!0===t.__buoyStateOnDevice)return"on device";if(t&&"object"==typeof t){const e=Object.keys(t).filter(e=>"function"!=typeof t[e]);return 0===e.length?"no data keys":e.length<=3?e.join(", "):`${e.slice(0,2).join(", ")} +${e.length-2}`}return""}catch{return""}}function LoadingBrowserState(){return(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{testID:`${_testIDs.ZUSTAND_TEST_ID}-stores-loading`,otto:"loading",title:"Loading stores…",message:"Waiting for the device to send its registered stores."})}function EmptyBrowserState(){return(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{testID:`${_testIDs.ZUSTAND_TEST_ID}-stores-empty`,otto:"scanning",title:"No stores registered",message:"Use watchStores() to register your Zustand stores.\nThey will appear here with their current state."})}function ZustandStoreBrowser({stores:e,searchQuery:t,isLoading:s=!1,onOpenStore:r}){const o=(0,_react.useMemo)(()=>{if(!t)return e;const s=t.toLowerCase();return e.filter(e=>e.name.toLowerCase().includes(s)||e.persistName&&e.persistName.toLowerCase().includes(s))},[e,t]);return 0!==o.length||t?0===o.length&&t?(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{testID:`${_testIDs.ZUSTAND_TEST_ID}-stores-no-match`,...(0,_sharedUi.resolveListEmptyState)({subject:"stores",verb:"registered",search:t,total:e.length,waiting:{otto:"scanning",title:"No stores registered",message:"Use watchStores() to register your Zustand stores."}})}):(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.container,contentContainerStyle:styles.scrollContent,showsVerticalScrollIndicator:!0,testID:`${_testIDs.ZUSTAND_TEST_ID}-stores-scroll`,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.sectionHeader,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.sectionTitle,children:"STORES"}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.sectionCountBadge,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.sectionCountText,testID:`${_testIDs.ZUSTAND_TEST_ID}-stores-count`,children:o.length})})]}),o.map(e=>{const t=getKeysPreview(e),s=_zustandStateStore.zustandStateStore.getStoreColor(e.name),o=(0,_testIDs.storeRowTestID)(e.name);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.storeRowWrapper,children:[(0,_jsxRuntime.jsx)(_sharedUi.CompactRow,{statusDotColor:s,statusLabel:e.isPersisted?"persisted":"in-memory",primaryText:e.name,secondaryText:t||void 0,showChevron:!0,onPress:()=>r(e.name),testID:o,statusTestID:`${o}-backing`,primaryTestID:`${o}-name`,secondaryTestID:`${o}-keys`}),e.stateChangeCount>0&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.absCountBadge,{backgroundColor:s+"22",borderColor:s+"55"}],pointerEvents:"none",children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.absCountText,{color:s}],testID:`${o}-count`,children:String(e.stateChangeCount)})})]},e.name)})]}):s?(0,_jsxRuntime.jsx)(LoadingBrowserState,{}):(0,_jsxRuntime.jsx)(EmptyBrowserState,{})}const styles=_reactNative.StyleSheet.create({container:{flex:1},storeRowWrapper:{position:"relative"},absCountBadge:{position:"absolute",top:4,right:10,paddingHorizontal:5,paddingVertical:1,borderRadius:4,borderWidth:1,zIndex:1},absCountText:{fontSize:9,fontWeight:"700",fontFamily:_sharedUi.monoFont},scrollContent:{paddingTop:8,paddingBottom:20},sectionHeader:{flexDirection:"row",alignItems:"center",paddingHorizontal:16,paddingVertical:8,gap:8},sectionTitle:{fontSize:11,fontWeight:"700",letterSpacing:.5,color:_sharedUi.night.color.textTertiary},sectionCountBadge:{backgroundColor:_sharedUi.night.color.accentFill,paddingHorizontal:8,paddingVertical:2,borderRadius:4},sectionCountText:{fontSize:10,fontWeight:"700",color:_sharedUi.night.color.accent,fontFamily:_sharedUi.monoFont}});
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ZustandStoreBrowser = ZustandStoreBrowser;
7
+ var _react = require("react");
8
+ var _reactNative = require("react-native");
9
+ var _sharedUi = require("@buoy-gg/shared-ui");
10
+ var _zustandStateStore = require("../utils/zustandStateStore");
11
+ var _testIDs = require("../utils/testIDs");
12
+ var _jsxRuntime = require("react/jsx-runtime");
13
+ /**
14
+ * ZustandStoreBrowser
15
+ *
16
+ * Browse tab — lists all registered Zustand stores. Tapping a card opens the
17
+ * store's detail screen (ZustandStoreDetailContent): live state editor on
18
+ * top, store details and the read-only tree below — the React Query
19
+ * interaction, replacing the old expand-in-place card.
20
+ */
21
+
22
+ /**
23
+ * Get a preview of the store's top-level keys
24
+ */
25
+ function getKeysPreview(store) {
26
+ try {
27
+ const state = store.api.getState();
28
+ if (state && typeof state === "object" && state.__buoyStateOnDevice === true) {
29
+ return "on device";
30
+ }
31
+ if (state && typeof state === "object") {
32
+ const keys = Object.keys(state);
33
+ const dataKeys = keys.filter(k => {
34
+ const val = state[k];
35
+ return typeof val !== "function";
36
+ });
37
+ if (dataKeys.length === 0) return "no data keys";
38
+ if (dataKeys.length <= 3) return dataKeys.join(", ");
39
+ return `${dataKeys.slice(0, 2).join(", ")} +${dataKeys.length - 2}`;
40
+ }
41
+ return "";
42
+ } catch {
43
+ return "";
44
+ }
45
+ }
46
+ function LoadingBrowserState() {
47
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolEmptyState, {
48
+ testID: `${_testIDs.ZUSTAND_TEST_ID}-stores-loading`
49
+ // Replaces the spinner rather than joining it: two animated things
50
+ // stacked is clutter, and `loading` IS the indeterminate spinner in
51
+ // mascot form.
52
+ ,
53
+ otto: "loading",
54
+ title: "Loading stores\u2026",
55
+ message: "Waiting for the device to send its registered stores."
56
+ });
57
+ }
58
+ function EmptyBrowserState() {
59
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolEmptyState, {
60
+ testID: `${_testIDs.ZUSTAND_TEST_ID}-stores-empty`
61
+ // scanning = "scanning for targets… and finding none". The registry is
62
+ // discovered, not configured, so an empty one is a scan result.
63
+ ,
64
+ otto: "scanning",
65
+ title: "No stores registered",
66
+ message: "Use watchStores() to register your Zustand stores.\nThey will appear here with their current state."
67
+ });
68
+ }
69
+ function ZustandStoreBrowser({
70
+ stores,
71
+ searchQuery,
72
+ isLoading = false,
73
+ onOpenStore
74
+ }) {
75
+ // Filter stores by search query
76
+ const filteredStores = (0, _react.useMemo)(() => {
77
+ if (!searchQuery) return stores;
78
+ const search = searchQuery.toLowerCase();
79
+ return stores.filter(s => s.name.toLowerCase().includes(search) || s.persistName && s.persistName.toLowerCase().includes(search));
80
+ }, [stores, searchQuery]);
81
+ if (filteredStores.length === 0 && !searchQuery) {
82
+ return isLoading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(LoadingBrowserState, {}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(EmptyBrowserState, {});
83
+ }
84
+ if (filteredStores.length === 0 && searchQuery) {
85
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ToolEmptyState, {
86
+ testID: `${_testIDs.ZUSTAND_TEST_ID}-stores-no-match`,
87
+ ...(0, _sharedUi.resolveListEmptyState)({
88
+ subject: "stores",
89
+ verb: "registered",
90
+ search: searchQuery,
91
+ total: stores.length,
92
+ waiting: {
93
+ otto: "scanning",
94
+ title: "No stores registered",
95
+ message: "Use watchStores() to register your Zustand stores."
96
+ }
97
+ })
98
+ });
99
+ }
100
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.ScrollView, {
101
+ style: styles.container,
102
+ contentContainerStyle: styles.scrollContent,
103
+ showsVerticalScrollIndicator: true,
104
+ testID: `${_testIDs.ZUSTAND_TEST_ID}-stores-scroll`,
105
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
106
+ style: styles.sectionHeader,
107
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
108
+ style: styles.sectionTitle,
109
+ children: "STORES"
110
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
111
+ style: styles.sectionCountBadge,
112
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
113
+ style: styles.sectionCountText,
114
+ testID: `${_testIDs.ZUSTAND_TEST_ID}-stores-count`,
115
+ children: filteredStores.length
116
+ })
117
+ })]
118
+ }), filteredStores.map(store => {
119
+ const keysPreview = getKeysPreview(store);
120
+ const storeColor = _zustandStateStore.zustandStateStore.getStoreColor(store.name);
121
+ const rowID = (0, _testIDs.storeRowTestID)(store.name);
122
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
123
+ style: styles.storeRowWrapper,
124
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.CompactRow, {
125
+ statusDotColor: storeColor,
126
+ statusLabel: store.isPersisted ? "persisted" : "in-memory",
127
+ primaryText: store.name,
128
+ secondaryText: keysPreview || undefined,
129
+ showChevron: true,
130
+ onPress: () => onOpenStore(store.name),
131
+ testID: rowID,
132
+ statusTestID: `${rowID}-backing`,
133
+ primaryTestID: `${rowID}-name`,
134
+ secondaryTestID: `${rowID}-keys`
135
+ }), store.stateChangeCount > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
136
+ style: [styles.absCountBadge, {
137
+ backgroundColor: storeColor + "22",
138
+ borderColor: storeColor + "55"
139
+ }],
140
+ pointerEvents: "none",
141
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
142
+ style: [styles.absCountText, {
143
+ color: storeColor
144
+ }],
145
+ testID: `${rowID}-count`,
146
+ children: String(store.stateChangeCount)
147
+ })
148
+ })]
149
+ }, store.name);
150
+ })]
151
+ });
152
+ }
153
+ const styles = _reactNative.StyleSheet.create({
154
+ container: {
155
+ flex: 1
156
+ },
157
+ storeRowWrapper: {
158
+ position: "relative"
159
+ },
160
+ absCountBadge: {
161
+ position: "absolute",
162
+ top: 4,
163
+ right: 10,
164
+ paddingHorizontal: 5,
165
+ paddingVertical: 1,
166
+ borderRadius: 4,
167
+ borderWidth: 1,
168
+ zIndex: 1
169
+ },
170
+ absCountText: {
171
+ fontSize: 9,
172
+ fontWeight: "700",
173
+ fontFamily: _sharedUi.monoFont
174
+ },
175
+ scrollContent: {
176
+ paddingTop: 8,
177
+ paddingBottom: 20
178
+ },
179
+ sectionHeader: {
180
+ flexDirection: "row",
181
+ alignItems: "center",
182
+ paddingHorizontal: 16,
183
+ paddingVertical: 8,
184
+ gap: 8
185
+ },
186
+ sectionTitle: {
187
+ fontSize: 11,
188
+ fontWeight: "700",
189
+ letterSpacing: 0.5,
190
+ color: _sharedUi.night.color.textTertiary
191
+ },
192
+ sectionCountBadge: {
193
+ backgroundColor: _sharedUi.night.color.accentFill,
194
+ paddingHorizontal: 8,
195
+ paddingVertical: 2,
196
+ borderRadius: 4
197
+ },
198
+ sectionCountText: {
199
+ fontSize: 10,
200
+ fontWeight: "700",
201
+ color: _sharedUi.night.color.accent,
202
+ fontFamily: _sharedUi.monoFont
203
+ }
204
+ });