@buoy-gg/zustand 7.0.29 → 7.0.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/zustand/components/ZustandActionButton.js +3 -1
- package/lib/commonjs/zustand/components/ZustandDetailViewToggle.js +7 -0
- package/lib/commonjs/zustand/components/ZustandEventFilterView.js +19 -4
- package/lib/commonjs/zustand/components/ZustandModal.js +173 -32
- package/lib/commonjs/zustand/components/ZustandStateChangeItem.js +36 -37
- package/lib/commonjs/zustand/components/ZustandStateDetailContent.js +22 -5
- package/lib/commonjs/zustand/components/ZustandStateInfoView.js +30 -7
- package/lib/commonjs/zustand/components/ZustandStoreBrowser.js +23 -126
- package/lib/commonjs/zustand/components/ZustandStoreDetailContent.js +471 -0
- package/lib/commonjs/zustand/components/ZustandStoreEditorScreen.js +393 -0
- package/lib/commonjs/zustand/sync/zustandSyncAdapter.js +54 -0
- package/lib/commonjs/zustand/utils/buoyZustandMiddleware.js +71 -7
- package/lib/commonjs/zustand/utils/editableState.js +139 -0
- package/lib/commonjs/zustand/utils/snapshotProvider.js +10 -37
- package/lib/commonjs/zustand/utils/testIDs.js +82 -0
- package/lib/commonjs/zustand/utils/zustandStateStore.js +16 -3
- package/lib/module/zustand/components/ZustandActionButton.js +3 -1
- package/lib/module/zustand/components/ZustandDetailViewToggle.js +7 -0
- package/lib/module/zustand/components/ZustandEventFilterView.js +19 -4
- package/lib/module/zustand/components/ZustandModal.js +173 -32
- package/lib/module/zustand/components/ZustandStateChangeItem.js +36 -37
- package/lib/module/zustand/components/ZustandStateDetailContent.js +22 -5
- package/lib/module/zustand/components/ZustandStateInfoView.js +30 -7
- package/lib/module/zustand/components/ZustandStoreBrowser.js +26 -129
- package/lib/module/zustand/components/ZustandStoreDetailContent.js +469 -0
- package/lib/module/zustand/components/ZustandStoreEditorScreen.js +389 -0
- package/lib/module/zustand/sync/zustandSyncAdapter.js +54 -0
- package/lib/module/zustand/utils/buoyZustandMiddleware.js +71 -7
- package/lib/module/zustand/utils/editableState.js +131 -0
- package/lib/module/zustand/utils/snapshotProvider.js +4 -30
- package/lib/module/zustand/utils/testIDs.js +74 -0
- package/lib/module/zustand/utils/zustandStateStore.js +16 -3
- package/lib/typescript/zustand/components/ZustandActionButton.d.ts +2 -1
- package/lib/typescript/zustand/components/ZustandActionButton.d.ts.map +1 -1
- package/lib/typescript/zustand/components/ZustandDetailViewToggle.d.ts.map +1 -1
- package/lib/typescript/zustand/components/ZustandEventFilterView.d.ts.map +1 -1
- package/lib/typescript/zustand/components/ZustandModal.d.ts.map +1 -1
- package/lib/typescript/zustand/components/ZustandStateChangeItem.d.ts +6 -0
- package/lib/typescript/zustand/components/ZustandStateChangeItem.d.ts.map +1 -1
- package/lib/typescript/zustand/components/ZustandStateDetailContent.d.ts.map +1 -1
- package/lib/typescript/zustand/components/ZustandStateInfoView.d.ts.map +1 -1
- package/lib/typescript/zustand/components/ZustandStoreBrowser.d.ts +7 -9
- package/lib/typescript/zustand/components/ZustandStoreBrowser.d.ts.map +1 -1
- package/lib/typescript/zustand/components/ZustandStoreDetailContent.d.ts +40 -0
- package/lib/typescript/zustand/components/ZustandStoreDetailContent.d.ts.map +1 -0
- package/lib/typescript/zustand/components/ZustandStoreEditorScreen.d.ts +42 -0
- package/lib/typescript/zustand/components/ZustandStoreEditorScreen.d.ts.map +1 -0
- package/lib/typescript/zustand/sync/zustandSyncAdapter.d.ts +35 -0
- package/lib/typescript/zustand/sync/zustandSyncAdapter.d.ts.map +1 -1
- package/lib/typescript/zustand/types/index.d.ts +13 -0
- package/lib/typescript/zustand/types/index.d.ts.map +1 -1
- package/lib/typescript/zustand/utils/buoyZustandMiddleware.d.ts +31 -3
- package/lib/typescript/zustand/utils/buoyZustandMiddleware.d.ts.map +1 -1
- package/lib/typescript/zustand/utils/editableState.d.ts +65 -0
- package/lib/typescript/zustand/utils/editableState.d.ts.map +1 -0
- package/lib/typescript/zustand/utils/testIDs.d.ts +54 -0
- package/lib/typescript/zustand/utils/testIDs.d.ts.map +1 -0
- package/lib/typescript/zustand/utils/zustandStateStore.d.ts +1 -0
- package/lib/typescript/zustand/utils/zustandStateStore.d.ts.map +1 -1
- package/package.json +3 -3
|
@@ -12,6 +12,7 @@ var _dataViewer = require("@buoy-gg/shared-ui/dataViewer");
|
|
|
12
12
|
var _ZustandDetailViewToggle = require("./ZustandDetailViewToggle");
|
|
13
13
|
var _ZustandStateInfoView = require("./ZustandStateInfoView");
|
|
14
14
|
var _zustandStateStore = require("../utils/zustandStateStore");
|
|
15
|
+
var _testIDs = require("../utils/testIDs");
|
|
15
16
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
16
17
|
/**
|
|
17
18
|
* ZustandStateDetailContent
|
|
@@ -121,6 +122,7 @@ function ZustandStateDetailContent({
|
|
|
121
122
|
const parsed = (0, _sharedUi.parseValue)(change.nextState);
|
|
122
123
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
123
124
|
style: styles.contentCard,
|
|
125
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-state-card`,
|
|
124
126
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
125
127
|
style: styles.valueHeader,
|
|
126
128
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
@@ -142,6 +144,7 @@ function ZustandStateDetailContent({
|
|
|
142
144
|
style: styles.typeBadge,
|
|
143
145
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
144
146
|
style: styles.typeText,
|
|
147
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-state-type`,
|
|
145
148
|
children: stateType.toUpperCase()
|
|
146
149
|
})
|
|
147
150
|
})]
|
|
@@ -193,7 +196,14 @@ function ZustandStateDetailContent({
|
|
|
193
196
|
const handleFooterNext = (0, _react.useCallback)(() => {
|
|
194
197
|
onIndexChange(Math.max(0, selectedIndex - 1));
|
|
195
198
|
}, [selectedIndex, onIndexChange]);
|
|
196
|
-
|
|
199
|
+
|
|
200
|
+
// The diff compares THIS change's prevState/nextState — both live on the
|
|
201
|
+
// change itself, so it needs no siblings. Gating on `changes.length` greyed
|
|
202
|
+
// DIFF out for every zustand event opened from the Events timeline, which
|
|
203
|
+
// hands this component a one-element array. Only a change with no captured
|
|
204
|
+
// previous state (initial creation) has nothing to compare.
|
|
205
|
+
const diffDisabled = change.prevState === undefined;
|
|
206
|
+
const showInternalFooter = !disableInternalFooter && totalChanges > 1;
|
|
197
207
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
198
208
|
style: styles.container,
|
|
199
209
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_ZustandDetailViewToggle.ZustandDetailViewToggle, {
|
|
@@ -201,7 +211,7 @@ function ZustandStateDetailContent({
|
|
|
201
211
|
onViewChange: setActiveView,
|
|
202
212
|
diffDisabled: diffDisabled
|
|
203
213
|
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
204
|
-
style: styles.contentArea,
|
|
214
|
+
style: [styles.contentArea, showInternalFooter && styles.contentAreaFooterPad],
|
|
205
215
|
children: [activeView === "change" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_ZustandStateInfoView.ZustandStateInfoView, {
|
|
206
216
|
change: change
|
|
207
217
|
}), activeView === "state" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
@@ -209,19 +219,22 @@ function ZustandStateDetailContent({
|
|
|
209
219
|
children: renderStateView()
|
|
210
220
|
}), activeView === "diff" && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
211
221
|
style: styles.diffContainer,
|
|
222
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-diff`,
|
|
212
223
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.DiffModeTabs, {
|
|
213
224
|
tabs: DIFF_MODE_TABS,
|
|
214
225
|
activeTab: diffMode,
|
|
215
|
-
onTabChange: setDiffMode
|
|
226
|
+
onTabChange: setDiffMode,
|
|
227
|
+
testIDPrefix: `${_testIDs.ZUSTAND_TEST_ID}-diff-tab`
|
|
216
228
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.CompareBar, {
|
|
217
229
|
leftEvent: leftEvent,
|
|
218
230
|
rightEvent: rightEvent
|
|
219
231
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
220
232
|
style: styles.diffContent,
|
|
233
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-diff-content`,
|
|
221
234
|
children: renderDiffContent()
|
|
222
235
|
})]
|
|
223
236
|
})]
|
|
224
|
-
}),
|
|
237
|
+
}), showInternalFooter && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.EventStepperFooter, {
|
|
225
238
|
currentIndex: chronologicalNumber - 1,
|
|
226
239
|
totalItems: totalChanges,
|
|
227
240
|
onPrevious: handleFooterPrevious,
|
|
@@ -261,7 +274,11 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
261
274
|
backgroundColor: "transparent"
|
|
262
275
|
},
|
|
263
276
|
contentArea: {
|
|
264
|
-
flex: 1
|
|
277
|
+
flex: 1
|
|
278
|
+
},
|
|
279
|
+
// Clearance for the absolute EventStepperFooter — only when it renders,
|
|
280
|
+
// otherwise hosts like the Events tool get a dead band at the sheet bottom.
|
|
281
|
+
contentAreaFooterPad: {
|
|
265
282
|
paddingBottom: 96
|
|
266
283
|
},
|
|
267
284
|
stateContainer: {
|
|
@@ -11,6 +11,7 @@ var _license = require("@buoy-gg/license");
|
|
|
11
11
|
var _dataViewer = require("@buoy-gg/shared-ui/dataViewer");
|
|
12
12
|
var _ZustandActionButton = require("./ZustandActionButton");
|
|
13
13
|
var _zustandStateStore = require("../utils/zustandStateStore");
|
|
14
|
+
var _testIDs = require("../utils/testIDs");
|
|
14
15
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
15
16
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
16
17
|
/**
|
|
@@ -60,10 +61,12 @@ function formatDuration(duration) {
|
|
|
60
61
|
function SectionHeader({
|
|
61
62
|
icon: Icon,
|
|
62
63
|
title,
|
|
63
|
-
badge
|
|
64
|
+
badge,
|
|
65
|
+
testID
|
|
64
66
|
}) {
|
|
65
67
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
66
68
|
style: styles.sectionHeader,
|
|
69
|
+
testID: testID,
|
|
67
70
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
68
71
|
style: styles.sectionHeaderLeft,
|
|
69
72
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(Icon, {
|
|
@@ -80,7 +83,8 @@ function InfoRow({
|
|
|
80
83
|
label,
|
|
81
84
|
value,
|
|
82
85
|
valueColor,
|
|
83
|
-
mono = false
|
|
86
|
+
mono = false,
|
|
87
|
+
testID
|
|
84
88
|
}) {
|
|
85
89
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
86
90
|
style: styles.infoRow,
|
|
@@ -88,6 +92,7 @@ function InfoRow({
|
|
|
88
92
|
style: styles.infoLabel,
|
|
89
93
|
children: label
|
|
90
94
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
95
|
+
testID: testID,
|
|
91
96
|
style: [styles.infoValue, mono && styles.infoValueMono, valueColor ? {
|
|
92
97
|
color: valueColor
|
|
93
98
|
} : undefined],
|
|
@@ -143,8 +148,10 @@ const ZustandStateInfoView = exports.ZustandStateInfoView = /*#__PURE__*/(0, _re
|
|
|
143
148
|
style: styles.container,
|
|
144
149
|
contentContainerStyle: styles.contentContainer,
|
|
145
150
|
showsVerticalScrollIndicator: false,
|
|
151
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-detail-scroll`,
|
|
146
152
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
147
153
|
style: styles.card,
|
|
154
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-info-card`,
|
|
148
155
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(SectionHeader, {
|
|
149
156
|
icon: _sharedUi.Info,
|
|
150
157
|
title: "CHANGE INFO"
|
|
@@ -154,11 +161,13 @@ const ZustandStateInfoView = exports.ZustandStateInfoView = /*#__PURE__*/(0, _re
|
|
|
154
161
|
label: "Store",
|
|
155
162
|
value: change.storeName,
|
|
156
163
|
mono: true,
|
|
157
|
-
valueColor: storeColor
|
|
164
|
+
valueColor: storeColor,
|
|
165
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-info-store`
|
|
158
166
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(InfoRow, {
|
|
159
167
|
label: "Time",
|
|
160
168
|
value: formatTime(change.timestamp),
|
|
161
|
-
mono: true
|
|
169
|
+
mono: true,
|
|
170
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-info-time`
|
|
162
171
|
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
163
172
|
style: styles.badgeRow,
|
|
164
173
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
@@ -169,6 +178,7 @@ const ZustandStateInfoView = exports.ZustandStateInfoView = /*#__PURE__*/(0, _re
|
|
|
169
178
|
style: [styles.categoryText, {
|
|
170
179
|
color: categoryInfo.color
|
|
171
180
|
}],
|
|
181
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-info-category`,
|
|
172
182
|
children: categoryInfo.label
|
|
173
183
|
})
|
|
174
184
|
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
@@ -178,6 +188,7 @@ const ZustandStateInfoView = exports.ZustandStateInfoView = /*#__PURE__*/(0, _re
|
|
|
178
188
|
color: change.isSlowUpdate ? _sharedUi.buoyColors.error : _sharedUi.night.color.textSecondary
|
|
179
189
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
180
190
|
style: [styles.durationText, change.isSlowUpdate && styles.durationTextSlow],
|
|
191
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-info-duration`,
|
|
181
192
|
children: formatDuration(change.duration)
|
|
182
193
|
}), change.isSlowUpdate && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.AlertTriangle, {
|
|
183
194
|
size: 10,
|
|
@@ -190,12 +201,14 @@ const ZustandStateInfoView = exports.ZustandStateInfoView = /*#__PURE__*/(0, _re
|
|
|
190
201
|
color: _sharedUi.buoyColors.success
|
|
191
202
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
192
203
|
style: styles.changesText,
|
|
204
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-info-changes`,
|
|
193
205
|
children: change.diffSummary || "changed"
|
|
194
206
|
})]
|
|
195
207
|
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
196
208
|
style: styles.noChangesBadge,
|
|
197
209
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
198
210
|
style: styles.noChangesText,
|
|
211
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-info-no-changes`,
|
|
199
212
|
children: "no change"
|
|
200
213
|
})
|
|
201
214
|
}), change.isPersisted && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
@@ -205,6 +218,7 @@ const ZustandStateInfoView = exports.ZustandStateInfoView = /*#__PURE__*/(0, _re
|
|
|
205
218
|
color: _sharedUi.buoyColors.info
|
|
206
219
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
207
220
|
style: styles.persistText,
|
|
221
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-info-persisted`,
|
|
208
222
|
children: "PERSISTED"
|
|
209
223
|
})]
|
|
210
224
|
})]
|
|
@@ -212,6 +226,7 @@ const ZustandStateInfoView = exports.ZustandStateInfoView = /*#__PURE__*/(0, _re
|
|
|
212
226
|
})]
|
|
213
227
|
}), hasChangedKeys && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
214
228
|
style: styles.card,
|
|
229
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-keys-card`,
|
|
215
230
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(SectionHeader, {
|
|
216
231
|
icon: _sharedUi.Zap,
|
|
217
232
|
title: "CHANGED KEYS",
|
|
@@ -219,6 +234,7 @@ const ZustandStateInfoView = exports.ZustandStateInfoView = /*#__PURE__*/(0, _re
|
|
|
219
234
|
style: styles.countBadge,
|
|
220
235
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
221
236
|
style: styles.countText,
|
|
237
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-keys-count`,
|
|
222
238
|
children: change.changedKeys.length
|
|
223
239
|
})
|
|
224
240
|
})
|
|
@@ -230,6 +246,7 @@ const ZustandStateInfoView = exports.ZustandStateInfoView = /*#__PURE__*/(0, _re
|
|
|
230
246
|
style: styles.keyBadge,
|
|
231
247
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
232
248
|
style: styles.keyText,
|
|
249
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-key-${key}`,
|
|
233
250
|
children: key
|
|
234
251
|
})
|
|
235
252
|
}, key))
|
|
@@ -237,6 +254,7 @@ const ZustandStateInfoView = exports.ZustandStateInfoView = /*#__PURE__*/(0, _re
|
|
|
237
254
|
})]
|
|
238
255
|
}), hasPartial && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
239
256
|
style: styles.card,
|
|
257
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-partial-card`,
|
|
240
258
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(SectionHeader, {
|
|
241
259
|
icon: _sharedUi.Box,
|
|
242
260
|
title: "PARTIAL (setState argument)",
|
|
@@ -244,6 +262,7 @@ const ZustandStateInfoView = exports.ZustandStateInfoView = /*#__PURE__*/(0, _re
|
|
|
244
262
|
style: styles.typeBadge,
|
|
245
263
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
246
264
|
style: styles.typeText,
|
|
265
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-partial-type`,
|
|
247
266
|
children: Array.isArray(change.partial) ? "ARRAY" : typeof change.partial === "object" ? "OBJECT" : String(typeof change.partial).toUpperCase()
|
|
248
267
|
})
|
|
249
268
|
})
|
|
@@ -259,6 +278,7 @@ const ZustandStateInfoView = exports.ZustandStateInfoView = /*#__PURE__*/(0, _re
|
|
|
259
278
|
})]
|
|
260
279
|
}), change.partial === "(updater fn)" && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
261
280
|
style: styles.card,
|
|
281
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-updater-card`,
|
|
262
282
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(SectionHeader, {
|
|
263
283
|
icon: _sharedUi.Box,
|
|
264
284
|
title: "SET STATE CALL"
|
|
@@ -277,15 +297,18 @@ const ZustandStateInfoView = exports.ZustandStateInfoView = /*#__PURE__*/(0, _re
|
|
|
277
297
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_ZustandActionButton.ZustandActionButton, {
|
|
278
298
|
type: "jump",
|
|
279
299
|
text: "JUMP",
|
|
280
|
-
onPress: handleJumpToState
|
|
300
|
+
onPress: handleJumpToState,
|
|
301
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-jump`
|
|
281
302
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_ZustandActionButton.ZustandActionButton, {
|
|
282
303
|
type: "reset",
|
|
283
304
|
text: "RESET STORE",
|
|
284
|
-
onPress: handleResetStore
|
|
305
|
+
onPress: handleResetStore,
|
|
306
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-reset`
|
|
285
307
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_ZustandActionButton.ZustandActionButton, {
|
|
286
308
|
type: "copy",
|
|
287
309
|
text: "COPY STATE",
|
|
288
|
-
onPress: handleCopyState
|
|
310
|
+
onPress: handleCopyState,
|
|
311
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-copy-state`
|
|
289
312
|
})]
|
|
290
313
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ProUpgradeModal, {
|
|
291
314
|
visible: showProModal,
|
|
@@ -7,17 +7,16 @@ exports.ZustandStoreBrowser = ZustandStoreBrowser;
|
|
|
7
7
|
var _react = require("react");
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
9
|
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
10
|
-
var _dataViewer = require("@buoy-gg/shared-ui/dataViewer");
|
|
11
10
|
var _zustandStateStore = require("../utils/zustandStateStore");
|
|
11
|
+
var _testIDs = require("../utils/testIDs");
|
|
12
12
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
13
13
|
/**
|
|
14
14
|
* ZustandStoreBrowser
|
|
15
15
|
*
|
|
16
|
-
* Browse tab —
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* via the shared DataViewer component.
|
|
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.
|
|
21
20
|
*/
|
|
22
21
|
|
|
23
22
|
/**
|
|
@@ -44,80 +43,10 @@ function getKeysPreview(store) {
|
|
|
44
43
|
return "";
|
|
45
44
|
}
|
|
46
45
|
}
|
|
47
|
-
function StoreExpandedContent({
|
|
48
|
-
store,
|
|
49
|
-
onViewHistory
|
|
50
|
-
}) {
|
|
51
|
-
const state = store.api.getState();
|
|
52
|
-
const displayState = (0, _react.useMemo)(() => {
|
|
53
|
-
if (state && typeof state === "object") {
|
|
54
|
-
const filtered = {};
|
|
55
|
-
for (const [key, value] of Object.entries(state)) {
|
|
56
|
-
if (typeof value !== "function") {
|
|
57
|
-
filtered[key] = value;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return (0, _sharedUi.parseValue)(filtered);
|
|
61
|
-
}
|
|
62
|
-
return (0, _sharedUi.parseValue)(state);
|
|
63
|
-
}, [state]);
|
|
64
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
65
|
-
style: expandedStyles.container,
|
|
66
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ExpandedInfoRow, {
|
|
67
|
-
label: "Type",
|
|
68
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.PillBadge, {
|
|
69
|
-
color: store.color,
|
|
70
|
-
children: "ZUSTAND"
|
|
71
|
-
})
|
|
72
|
-
}), store.stateChangeCount > 0 && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_sharedUi.ExpandedInfoRow, {
|
|
73
|
-
label: "Changes",
|
|
74
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.PillBadge, {
|
|
75
|
-
color: _sharedUi.buoyColors.warning,
|
|
76
|
-
children: String(store.stateChangeCount)
|
|
77
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
78
|
-
onPress: () => onViewHistory(store.name),
|
|
79
|
-
style: expandedStyles.viewHistoryButton,
|
|
80
|
-
hitSlop: {
|
|
81
|
-
top: 6,
|
|
82
|
-
bottom: 6,
|
|
83
|
-
left: 6,
|
|
84
|
-
right: 6
|
|
85
|
-
},
|
|
86
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
87
|
-
style: [expandedStyles.viewHistoryText, {
|
|
88
|
-
color: store.color
|
|
89
|
-
}],
|
|
90
|
-
children: "view history \u2192"
|
|
91
|
-
})
|
|
92
|
-
})]
|
|
93
|
-
}), store.isPersisted && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ExpandedInfoRow, {
|
|
94
|
-
label: "Persist",
|
|
95
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.PillBadge, {
|
|
96
|
-
color: _sharedUi.buoyColors.info,
|
|
97
|
-
icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Database, {
|
|
98
|
-
size: 9,
|
|
99
|
-
color: _sharedUi.buoyColors.info
|
|
100
|
-
}),
|
|
101
|
-
children: store.persistName || "persisted"
|
|
102
|
-
})
|
|
103
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
104
|
-
style: expandedStyles.dataContainer,
|
|
105
|
-
children: displayState && typeof displayState === "object" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.DataViewer, {
|
|
106
|
-
title: "",
|
|
107
|
-
data: displayState,
|
|
108
|
-
showTypeFilter: true,
|
|
109
|
-
rawMode: true,
|
|
110
|
-
initialExpanded: true
|
|
111
|
-
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
112
|
-
style: expandedStyles.emptyText,
|
|
113
|
-
children: "Empty state"
|
|
114
|
-
})
|
|
115
|
-
})]
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
46
|
function LoadingBrowserState() {
|
|
119
47
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
120
48
|
style: styles.emptyState,
|
|
49
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-stores-loading`,
|
|
121
50
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
|
|
122
51
|
size: "small",
|
|
123
52
|
color: _sharedUi.night.color.textTertiary
|
|
@@ -133,11 +62,13 @@ function LoadingBrowserState() {
|
|
|
133
62
|
function EmptyBrowserState() {
|
|
134
63
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
135
64
|
style: styles.emptyState,
|
|
65
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-stores-empty`,
|
|
136
66
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Box, {
|
|
137
67
|
size: 32,
|
|
138
68
|
color: _sharedUi.night.color.textTertiary
|
|
139
69
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
140
70
|
style: styles.emptyTitle,
|
|
71
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-stores-empty-title`,
|
|
141
72
|
children: "No stores registered"
|
|
142
73
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
143
74
|
style: styles.emptyText,
|
|
@@ -148,33 +79,25 @@ function EmptyBrowserState() {
|
|
|
148
79
|
function ZustandStoreBrowser({
|
|
149
80
|
stores,
|
|
150
81
|
searchQuery,
|
|
151
|
-
onViewHistory,
|
|
152
82
|
isLoading = false,
|
|
153
|
-
|
|
83
|
+
onOpenStore
|
|
154
84
|
}) {
|
|
155
|
-
const [expandedStore, setExpandedStore] = (0, _react.useState)(null);
|
|
156
|
-
|
|
157
85
|
// Filter stores by search query
|
|
158
86
|
const filteredStores = (0, _react.useMemo)(() => {
|
|
159
87
|
if (!searchQuery) return stores;
|
|
160
88
|
const search = searchQuery.toLowerCase();
|
|
161
89
|
return stores.filter(s => s.name.toLowerCase().includes(search) || s.persistName && s.persistName.toLowerCase().includes(search));
|
|
162
90
|
}, [stores, searchQuery]);
|
|
163
|
-
const handleStorePress = (0, _react.useCallback)(store => {
|
|
164
|
-
setExpandedStore(prev => {
|
|
165
|
-
const next = prev === store.name ? null : store.name;
|
|
166
|
-
if (next) onStoreExpand?.(store.name);
|
|
167
|
-
return next;
|
|
168
|
-
});
|
|
169
|
-
}, [onStoreExpand]);
|
|
170
91
|
if (filteredStores.length === 0 && !searchQuery) {
|
|
171
92
|
return isLoading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(LoadingBrowserState, {}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(EmptyBrowserState, {});
|
|
172
93
|
}
|
|
173
94
|
if (filteredStores.length === 0 && searchQuery) {
|
|
174
95
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
175
96
|
style: styles.emptyState,
|
|
97
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-stores-no-match`,
|
|
176
98
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
177
99
|
style: styles.emptyTitle,
|
|
100
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-stores-no-match-title`,
|
|
178
101
|
children: "No matching stores"
|
|
179
102
|
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
180
103
|
style: styles.emptyText,
|
|
@@ -186,6 +109,7 @@ function ZustandStoreBrowser({
|
|
|
186
109
|
style: styles.container,
|
|
187
110
|
contentContainerStyle: styles.scrollContent,
|
|
188
111
|
showsVerticalScrollIndicator: true,
|
|
112
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-stores-scroll`,
|
|
189
113
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
190
114
|
style: styles.sectionHeader,
|
|
191
115
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
@@ -195,27 +119,27 @@ function ZustandStoreBrowser({
|
|
|
195
119
|
style: styles.sectionCountBadge,
|
|
196
120
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
197
121
|
style: styles.sectionCountText,
|
|
122
|
+
testID: `${_testIDs.ZUSTAND_TEST_ID}-stores-count`,
|
|
198
123
|
children: filteredStores.length
|
|
199
124
|
})
|
|
200
125
|
})]
|
|
201
126
|
}), filteredStores.map(store => {
|
|
202
|
-
const isExpanded = expandedStore === store.name;
|
|
203
127
|
const keysPreview = getKeysPreview(store);
|
|
204
128
|
const storeColor = _zustandStateStore.zustandStateStore.getStoreColor(store.name);
|
|
129
|
+
const rowID = (0, _testIDs.storeRowTestID)(store.name);
|
|
205
130
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
206
131
|
style: styles.storeRowWrapper,
|
|
207
132
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.CompactRow, {
|
|
208
133
|
statusDotColor: storeColor,
|
|
209
|
-
statusLabel: store.
|
|
210
|
-
|
|
211
|
-
|
|
134
|
+
statusLabel: store.isPersisted ? "persisted" : "in-memory",
|
|
135
|
+
primaryText: store.name,
|
|
136
|
+
secondaryText: keysPreview || undefined,
|
|
212
137
|
showChevron: true,
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}) : undefined
|
|
138
|
+
onPress: () => onOpenStore(store.name),
|
|
139
|
+
testID: rowID,
|
|
140
|
+
statusTestID: `${rowID}-backing`,
|
|
141
|
+
primaryTestID: `${rowID}-name`,
|
|
142
|
+
secondaryTestID: `${rowID}-keys`
|
|
219
143
|
}), store.stateChangeCount > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
220
144
|
style: [styles.absCountBadge, {
|
|
221
145
|
backgroundColor: storeColor + "22",
|
|
@@ -226,6 +150,7 @@ function ZustandStoreBrowser({
|
|
|
226
150
|
style: [styles.absCountText, {
|
|
227
151
|
color: storeColor
|
|
228
152
|
}],
|
|
153
|
+
testID: `${rowID}-count`,
|
|
229
154
|
children: String(store.stateChangeCount)
|
|
230
155
|
})
|
|
231
156
|
})]
|
|
@@ -301,32 +226,4 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
301
226
|
textAlign: "center",
|
|
302
227
|
lineHeight: 18
|
|
303
228
|
}
|
|
304
|
-
});
|
|
305
|
-
const expandedStyles = _reactNative.StyleSheet.create({
|
|
306
|
-
container: {
|
|
307
|
-
gap: 10
|
|
308
|
-
},
|
|
309
|
-
viewHistoryButton: {
|
|
310
|
-
marginLeft: 4
|
|
311
|
-
},
|
|
312
|
-
viewHistoryText: {
|
|
313
|
-
fontSize: 10,
|
|
314
|
-
fontWeight: "600",
|
|
315
|
-
fontFamily: "monospace"
|
|
316
|
-
},
|
|
317
|
-
dataContainer: {
|
|
318
|
-
// Inset display panel — darker than the card, the night track color.
|
|
319
|
-
backgroundColor: _sharedUi.night.color.bg,
|
|
320
|
-
borderRadius: 6,
|
|
321
|
-
borderWidth: 1,
|
|
322
|
-
borderColor: _sharedUi.night.color.border,
|
|
323
|
-
overflow: "hidden",
|
|
324
|
-
minHeight: 60
|
|
325
|
-
},
|
|
326
|
-
emptyText: {
|
|
327
|
-
color: _sharedUi.night.color.textTertiary,
|
|
328
|
-
fontSize: 12,
|
|
329
|
-
padding: 14,
|
|
330
|
-
fontStyle: "italic"
|
|
331
|
-
}
|
|
332
229
|
});
|