@buoy-gg/zustand 7.0.41 → 7.0.42

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 (63) hide show
  1. package/README.md +11 -76
  2. package/lib/commonjs/index.js +1 -105
  3. package/lib/commonjs/preset.js +1 -102
  4. package/lib/commonjs/zustand/components/ZustandActionButton.js +1 -118
  5. package/lib/commonjs/zustand/components/ZustandDetailViewToggle.js +1 -48
  6. package/lib/commonjs/zustand/components/ZustandEventFilterView.js +1 -43
  7. package/lib/commonjs/zustand/components/ZustandIcon.js +1 -18
  8. package/lib/commonjs/zustand/components/ZustandModal.js +1 -772
  9. package/lib/commonjs/zustand/components/ZustandStateChangeItem.js +1 -117
  10. package/lib/commonjs/zustand/components/ZustandStateDetailContent.js +1 -372
  11. package/lib/commonjs/zustand/components/ZustandStateInfoView.js +1 -488
  12. package/lib/commonjs/zustand/components/ZustandStoreBrowser.js +1 -204
  13. package/lib/commonjs/zustand/components/ZustandStoreDetailContent.js +1 -471
  14. package/lib/commonjs/zustand/hooks/useZustandStateChanges.js +1 -74
  15. package/lib/commonjs/zustand/sync/zustandSyncAdapter.js +1 -418
  16. package/lib/commonjs/zustand/types/index.js +1 -1
  17. package/lib/commonjs/zustand/utils/buoyZustandMiddleware.js +1 -284
  18. package/lib/commonjs/zustand/utils/editableState.js +1 -146
  19. package/lib/commonjs/zustand/utils/snapshotProvider.js +1 -209
  20. package/lib/commonjs/zustand/utils/testIDs.js +1 -82
  21. package/lib/commonjs/zustand/utils/zustandStateStore.js +1 -379
  22. package/lib/module/index.js +1 -90
  23. package/lib/module/preset.js +1 -98
  24. package/lib/module/zustand/components/ZustandActionButton.js +1 -114
  25. package/lib/module/zustand/components/ZustandDetailViewToggle.js +1 -43
  26. package/lib/module/zustand/components/ZustandEventFilterView.js +1 -39
  27. package/lib/module/zustand/components/ZustandIcon.js +1 -11
  28. package/lib/module/zustand/components/ZustandModal.js +1 -767
  29. package/lib/module/zustand/components/ZustandStateChangeItem.js +1 -113
  30. package/lib/module/zustand/components/ZustandStateDetailContent.js +1 -368
  31. package/lib/module/zustand/components/ZustandStateInfoView.js +1 -483
  32. package/lib/module/zustand/components/ZustandStoreBrowser.js +1 -200
  33. package/lib/module/zustand/components/ZustandStoreDetailContent.js +1 -469
  34. package/lib/module/zustand/hooks/useZustandStateChanges.js +1 -70
  35. package/lib/module/zustand/sync/zustandSyncAdapter.js +1 -415
  36. package/lib/module/zustand/types/index.js +1 -1
  37. package/lib/module/zustand/utils/buoyZustandMiddleware.js +1 -278
  38. package/lib/module/zustand/utils/editableState.js +1 -138
  39. package/lib/module/zustand/utils/snapshotProvider.js +1 -209
  40. package/lib/module/zustand/utils/testIDs.js +1 -74
  41. package/lib/module/zustand/utils/zustandStateStore.js +1 -375
  42. package/lib/web/index.mjs +2 -3
  43. package/package.json +3 -3
  44. package/lib/typescript/index.d.ts.map +0 -1
  45. package/lib/typescript/preset.d.ts.map +0 -1
  46. package/lib/typescript/zustand/components/ZustandActionButton.d.ts.map +0 -1
  47. package/lib/typescript/zustand/components/ZustandDetailViewToggle.d.ts.map +0 -1
  48. package/lib/typescript/zustand/components/ZustandEventFilterView.d.ts.map +0 -1
  49. package/lib/typescript/zustand/components/ZustandIcon.d.ts.map +0 -1
  50. package/lib/typescript/zustand/components/ZustandModal.d.ts.map +0 -1
  51. package/lib/typescript/zustand/components/ZustandStateChangeItem.d.ts.map +0 -1
  52. package/lib/typescript/zustand/components/ZustandStateDetailContent.d.ts.map +0 -1
  53. package/lib/typescript/zustand/components/ZustandStateInfoView.d.ts.map +0 -1
  54. package/lib/typescript/zustand/components/ZustandStoreBrowser.d.ts.map +0 -1
  55. package/lib/typescript/zustand/components/ZustandStoreDetailContent.d.ts.map +0 -1
  56. package/lib/typescript/zustand/hooks/useZustandStateChanges.d.ts.map +0 -1
  57. package/lib/typescript/zustand/sync/zustandSyncAdapter.d.ts.map +0 -1
  58. package/lib/typescript/zustand/types/index.d.ts.map +0 -1
  59. package/lib/typescript/zustand/utils/buoyZustandMiddleware.d.ts.map +0 -1
  60. package/lib/typescript/zustand/utils/editableState.d.ts.map +0 -1
  61. package/lib/typescript/zustand/utils/snapshotProvider.d.ts.map +0 -1
  62. package/lib/typescript/zustand/utils/testIDs.d.ts.map +0 -1
  63. package/lib/typescript/zustand/utils/zustandStateStore.d.ts.map +0 -1
@@ -1,117 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.ZustandStateChangeItem = void 0;
7
- var _react = require("react");
8
- var _sharedUi = require("@buoy-gg/shared-ui");
9
- var _zustandStateStore = require("../utils/zustandStateStore");
10
- var _jsxRuntime = require("react/jsx-runtime");
11
- /**
12
- * Compact list item for displaying a Zustand state change
13
- *
14
- * Mirrors ReduxActionItem.tsx - uses shared CompactRow for consistent styling
15
- */
16
-
17
- /**
18
- * Get status label based on category
19
- */
20
- function getStatusLabel(category, storeName) {
21
- switch (category) {
22
- case "replace":
23
- return "Replace";
24
- case "persist":
25
- return "Hydrate";
26
- case "initial":
27
- return "Initial";
28
- default:
29
- return storeName.charAt(0).toUpperCase() + storeName.slice(1);
30
- }
31
- }
32
-
33
- /**
34
- * Get color for category
35
- */
36
- function getCategoryColor(category, storeName) {
37
- switch (category) {
38
- case "replace":
39
- return _sharedUi.buoyColors.warning;
40
- case "persist":
41
- return _sharedUi.buoyColors.info;
42
- case "initial":
43
- return _sharedUi.night.color.textTertiary;
44
- default:
45
- return _zustandStateStore.zustandStateStore.getStoreColor(storeName);
46
- }
47
- }
48
-
49
- /**
50
- * Get sublabel with duration and diff info
51
- */
52
- function getSublabel(change) {
53
- const parts = [];
54
- if (change.duration !== undefined && change.duration >= 0.1) {
55
- parts.push(`${change.duration.toFixed(1)}ms`);
56
- }
57
- if (change.hasStateChange) {
58
- if (change.changedKeysCount > 0) {
59
- parts.push(`${change.changedKeysCount} key${change.changedKeysCount > 1 ? "s" : ""} changed`);
60
- } else {
61
- parts.push(change.diffSummary || "state changed");
62
- }
63
- } else {
64
- parts.push("no state change");
65
- }
66
- return parts.join(" \u00B7 ");
67
- }
68
-
69
- /**
70
- * Get badge text for the change
71
- */
72
- function getBadgeText(change) {
73
- if (change.category === "replace") return "REPLACE";
74
- if (change.category === "persist") return "HYDRATE";
75
- if (change.category === "initial") return "INIT";
76
- return "SET";
77
- }
78
-
79
- /**
80
- * Get primary display text
81
- */
82
- function getPrimaryText(change) {
83
- if (change.changedKeys.length > 0 && change.changedKeys.length <= 3) {
84
- return change.changedKeys.join(", ");
85
- }
86
- if (change.changedKeys.length > 3) {
87
- return `${change.changedKeys.slice(0, 2).join(", ")} +${change.changedKeys.length - 2}`;
88
- }
89
- return change.partialPreview || "setState()";
90
- }
91
-
92
- // Memo justified by profiling (tool-bench 2026-07-06): unmemoized, every
93
- // visible row re-rendered on each store emission. Leaf w/ stable props
94
- // ({change, onPress} — onPress is a stable useCallback in the modal).
95
- const ZustandStateChangeItem = exports.ZustandStateChangeItem = /*#__PURE__*/(0, _react.memo)(function ZustandStateChangeItem({
96
- change,
97
- onPress,
98
- testID
99
- }) {
100
- const statusColor = getCategoryColor(change.category, change.storeName);
101
- const statusLabel = getStatusLabel(change.category, change.storeName);
102
- const sublabel = getSublabel(change);
103
- const primaryText = getPrimaryText(change);
104
- const badgeText = getBadgeText(change);
105
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.ChangeRow, {
106
- statusColor: statusColor,
107
- statusLabel: statusLabel,
108
- sublabel: sublabel,
109
- primaryText: primaryText,
110
- timestamp: change.timestamp,
111
- badgeText: badgeText,
112
- changed: change.hasStateChange,
113
- slow: change.isSlowUpdate,
114
- onPress: () => onPress(change),
115
- testID: testID
116
- });
117
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.ZustandStateChangeItem=void 0;var _react=require("react");var _sharedUi=require("@buoy-gg/shared-ui");var _zustandStateStore=require("../utils/zustandStateStore");var _jsxRuntime=require("react/jsx-runtime");function getStatusLabel(t,e){switch(t){case"replace":return"Replace";case"persist":return"Hydrate";case"initial":return"Initial";default:return e.charAt(0).toUpperCase()+e.slice(1)}}function getCategoryColor(t,e){switch(t){case"replace":return _sharedUi.buoyColors.warning;case"persist":return _sharedUi.buoyColors.info;case"initial":return _sharedUi.night.color.textTertiary;default:return _zustandStateStore.zustandStateStore.getStoreColor(e)}}function getSublabel(t){const e=[];if(t.duration!==void 0&&t.duration>=.1){e.push(`${t.duration.toFixed(1)}ms`)}if(t.hasStateChange){if(t.changedKeysCount>0){e.push(`${t.changedKeysCount} key${t.changedKeysCount>1?"s":""} changed`)}else{e.push(t.diffSummary||"state changed")}}else{e.push("no state change")}return e.join(" \xB7 ")}function getBadgeText(t){if(t.category==="replace")return"REPLACE";if(t.category==="persist")return"HYDRATE";if(t.category==="initial")return"INIT";return"SET"}function getPrimaryText(t){if(t.changedKeys.length>0&&t.changedKeys.length<=3){return t.changedKeys.join(", ")}if(t.changedKeys.length>3){return`${t.changedKeys.slice(0,2).join(", ")} +${t.changedKeys.length-2}`}return t.partialPreview||"setState()"}const ZustandStateChangeItem=exports.ZustandStateChangeItem=(0,_react.memo)(function t({change:e,onPress:r,testID:s}){const a=getCategoryColor(e.category,e.storeName);const u=getStatusLabel(e.category,e.storeName);const n=getSublabel(e);const i=getPrimaryText(e);const o=getBadgeText(e);return(0,_jsxRuntime.jsx)(_sharedUi.ChangeRow,{statusColor:a,statusLabel:u,sublabel:n,primaryText:i,timestamp:e.timestamp,badgeText:o,changed:e.hasStateChange,slow:e.isSlowUpdate,onPress:()=>r(e),testID:s})});
@@ -1,372 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.ZustandStateDetailContent = ZustandStateDetailContent;
7
- exports.ZustandStateDetailFooter = ZustandStateDetailFooter;
8
- var _reactNative = require("react-native");
9
- var _react = require("react");
10
- var _sharedUi = require("@buoy-gg/shared-ui");
11
- var _dataViewer = require("@buoy-gg/shared-ui/dataViewer");
12
- var _ZustandDetailViewToggle = require("./ZustandDetailViewToggle");
13
- var _ZustandStateInfoView = require("./ZustandStateInfoView");
14
- var _zustandStateStore = require("../utils/zustandStateStore");
15
- var _testIDs = require("../utils/testIDs");
16
- var _jsxRuntime = require("react/jsx-runtime");
17
- /**
18
- * ZustandStateDetailContent
19
- *
20
- * Detail view for a Zustand state change with 3 view modes:
21
- * - CHANGE: View change details, partial, metadata
22
- * - STATE: View current state after change
23
- * - DIFF: Compare prev vs next state
24
- *
25
- * Mirrors ReduxActionDetailContent.tsx
26
- */
27
-
28
- function getChangeColor(change) {
29
- return _zustandStateStore.zustandStateStore.getStoreColor(change.storeName);
30
- }
31
- function getChangeLabel(change) {
32
- switch (change.category) {
33
- case "replace":
34
- return "REPLACE";
35
- case "persist":
36
- return "HYDRATE";
37
- case "initial":
38
- return "INIT";
39
- default:
40
- return "SET";
41
- }
42
- }
43
- function getValueType(value) {
44
- if (value === null) return "null";
45
- if (value === undefined) return "undefined";
46
- if (Array.isArray(value)) return "array";
47
- return typeof value;
48
- }
49
- function formatTimestamp(timestamp) {
50
- const date = new Date(timestamp);
51
- return date.toLocaleTimeString("en-US", {
52
- hour12: false,
53
- hour: "2-digit",
54
- minute: "2-digit",
55
- second: "2-digit"
56
- });
57
- }
58
- const DIFF_MODE_TABS = [{
59
- key: "tree",
60
- label: "TREE VIEW"
61
- }, {
62
- key: "split",
63
- label: "SPLIT VIEW"
64
- }];
65
- function ZustandStateDetailContent({
66
- change,
67
- changes,
68
- selectedIndex,
69
- onIndexChange,
70
- disableInternalFooter = false,
71
- initialView = "change"
72
- }) {
73
- const [activeView, setActiveView] = (0, _react.useState)(initialView);
74
- const [diffMode, setDiffMode] = (0, _react.useState)("tree");
75
- const totalChanges = changes.length;
76
- const changeColor = getChangeColor(change);
77
- const changeLabel = getChangeLabel(change);
78
- const stateType = getValueType((0, _sharedUi.parseValue)(change.nextState));
79
-
80
- // Changes are in reverse chronological order (newest first)
81
- const chronologicalNumber = totalChanges - selectedIndex;
82
- const prevChronologicalNumber = chronologicalNumber - 1;
83
- const prevChangeIndex = selectedIndex < totalChanges - 1 ? selectedIndex + 1 : null;
84
- const prevChange = prevChangeIndex !== null ? changes[prevChangeIndex] : null;
85
-
86
- // Compare bar info
87
- const leftEvent = (0, _react.useMemo)(() => ({
88
- index: prevChangeIndex ?? 0,
89
- label: prevChronologicalNumber > 0 ? `#${prevChronologicalNumber}` : "Initial",
90
- timestamp: prevChange ? formatTimestamp(prevChange.timestamp) : "",
91
- relativeTime: prevChange ? (0, _sharedUi.formatRelativeTime)(new Date(prevChange.timestamp)) : "state",
92
- badge: prevChange ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
93
- style: [styles.changeBadgeSmall, {
94
- backgroundColor: `${getChangeColor(prevChange)}20`
95
- }],
96
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
97
- style: [styles.changeTextSmall, {
98
- color: getChangeColor(prevChange)
99
- }],
100
- children: getChangeLabel(prevChange)
101
- })
102
- }) : undefined
103
- }), [prevChangeIndex, prevChange, prevChronologicalNumber]);
104
- const rightEvent = (0, _react.useMemo)(() => ({
105
- index: selectedIndex,
106
- label: `#${chronologicalNumber}`,
107
- timestamp: formatTimestamp(change.timestamp),
108
- relativeTime: (0, _sharedUi.formatRelativeTime)(new Date(change.timestamp)),
109
- badge: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
110
- style: [styles.changeBadgeSmall, {
111
- backgroundColor: `${changeColor}20`
112
- }],
113
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
114
- style: [styles.changeTextSmall, {
115
- color: changeColor
116
- }],
117
- children: changeLabel
118
- })
119
- })
120
- }), [selectedIndex, change.timestamp, changeColor, changeLabel, chronologicalNumber]);
121
- const renderStateView = (0, _react.useCallback)(() => {
122
- const parsed = (0, _sharedUi.parseValue)(change.nextState);
123
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
124
- style: styles.contentCard,
125
- testID: `${_testIDs.ZUSTAND_TEST_ID}-state-card`,
126
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
127
- style: styles.valueHeader,
128
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
129
- style: styles.valueLabel,
130
- children: "STATE AFTER CHANGE"
131
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
132
- style: styles.valueHeaderBadges,
133
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
134
- style: [styles.changeBadge, {
135
- backgroundColor: `${changeColor}20`
136
- }],
137
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
138
- style: [styles.changeText, {
139
- color: changeColor
140
- }],
141
- children: changeLabel
142
- })
143
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
144
- style: styles.typeBadge,
145
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
146
- style: styles.typeText,
147
- testID: `${_testIDs.ZUSTAND_TEST_ID}-state-type`,
148
- children: stateType.toUpperCase()
149
- })
150
- })]
151
- })]
152
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
153
- style: styles.dataViewerContainer,
154
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.DataViewer, {
155
- title: "",
156
- data: parsed,
157
- showTypeFilter: true,
158
- rawMode: true,
159
- initialExpanded: true
160
- })
161
- })]
162
- });
163
- }, [change.nextState, changeColor, changeLabel, stateType]);
164
- const renderDiffContent = (0, _react.useCallback)(() => {
165
- const prevState = (0, _sharedUi.parseValue)(change.prevState);
166
- const nextState = (0, _sharedUi.parseValue)(change.nextState);
167
- if (diffMode === "split") {
168
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
169
- style: {
170
- flex: 1
171
- },
172
- showsVerticalScrollIndicator: true,
173
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.SplitDiffViewer, {
174
- oldValue: prevState,
175
- newValue: nextState,
176
- theme: _dataViewer.diffThemes.devToolsDefault,
177
- options: {
178
- hideLineNumbers: false,
179
- disableWordDiff: false,
180
- showDiffOnly: false,
181
- compareMethod: "words",
182
- contextLines: 3
183
- },
184
- showThemeName: false
185
- })
186
- });
187
- }
188
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.TreeDiffViewer, {
189
- oldValue: prevState,
190
- newValue: nextState
191
- });
192
- }, [change.prevState, change.nextState, diffMode]);
193
- const handleFooterPrevious = (0, _react.useCallback)(() => {
194
- onIndexChange(Math.min(totalChanges - 1, selectedIndex + 1));
195
- }, [selectedIndex, totalChanges, onIndexChange]);
196
- const handleFooterNext = (0, _react.useCallback)(() => {
197
- onIndexChange(Math.max(0, selectedIndex - 1));
198
- }, [selectedIndex, onIndexChange]);
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;
207
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
208
- style: styles.container,
209
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_ZustandDetailViewToggle.ZustandDetailViewToggle, {
210
- activeView: activeView,
211
- onViewChange: setActiveView,
212
- diffDisabled: diffDisabled
213
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
214
- style: [styles.contentArea, showInternalFooter && styles.contentAreaFooterPad],
215
- children: [activeView === "change" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_ZustandStateInfoView.ZustandStateInfoView, {
216
- change: change
217
- }), activeView === "state" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
218
- style: styles.stateContainer,
219
- children: renderStateView()
220
- }), activeView === "diff" && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
221
- style: styles.diffContainer,
222
- testID: `${_testIDs.ZUSTAND_TEST_ID}-diff`,
223
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.DiffModeTabs, {
224
- tabs: DIFF_MODE_TABS,
225
- activeTab: diffMode,
226
- onTabChange: setDiffMode,
227
- testIDPrefix: `${_testIDs.ZUSTAND_TEST_ID}-diff-tab`
228
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.CompareBar, {
229
- leftEvent: leftEvent,
230
- rightEvent: rightEvent
231
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
232
- style: styles.diffContent,
233
- testID: `${_testIDs.ZUSTAND_TEST_ID}-diff-content`,
234
- children: renderDiffContent()
235
- })]
236
- })]
237
- }), showInternalFooter && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.EventStepperFooter, {
238
- currentIndex: chronologicalNumber - 1,
239
- totalItems: totalChanges,
240
- onPrevious: handleFooterPrevious,
241
- onNext: handleFooterNext,
242
- itemLabel: "Change",
243
- subtitle: (0, _sharedUi.formatRelativeTime)(new Date(change.timestamp)),
244
- absolute: true
245
- })]
246
- });
247
- }
248
-
249
- /**
250
- * External footer component for modal use
251
- */
252
- function ZustandStateDetailFooter({
253
- change,
254
- changes,
255
- selectedIndex,
256
- onIndexChange
257
- }) {
258
- const totalChanges = changes.length;
259
- if (totalChanges <= 1) return null;
260
- const chronologicalNumber = totalChanges - selectedIndex;
261
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.EventStepperFooter, {
262
- currentIndex: chronologicalNumber - 1,
263
- totalItems: totalChanges,
264
- onPrevious: () => onIndexChange(Math.min(totalChanges - 1, selectedIndex + 1)),
265
- onNext: () => onIndexChange(Math.max(0, selectedIndex - 1)),
266
- itemLabel: "Change",
267
- subtitle: (0, _sharedUi.formatRelativeTime)(new Date(change.timestamp))
268
- });
269
- }
270
- const styles = _reactNative.StyleSheet.create({
271
- container: {
272
- flex: 1,
273
- // Transparent so the night sheet's star field shows through.
274
- backgroundColor: "transparent"
275
- },
276
- contentArea: {
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: {
282
- paddingBottom: 96
283
- },
284
- stateContainer: {
285
- flex: 1,
286
- padding: 14
287
- },
288
- contentCard: {
289
- backgroundColor: _sharedUi.night.color.surface,
290
- borderRadius: 14,
291
- padding: 14,
292
- borderWidth: 1,
293
- borderColor: _sharedUi.night.color.border
294
- },
295
- valueHeader: {
296
- flexDirection: "row",
297
- alignItems: "center",
298
- justifyContent: "space-between",
299
- marginBottom: 8
300
- },
301
- valueLabel: {
302
- fontSize: 10,
303
- color: _sharedUi.night.color.textSecondary,
304
- fontFamily: _sharedUi.monoFont,
305
- letterSpacing: 0.5,
306
- fontWeight: "600"
307
- },
308
- valueHeaderBadges: {
309
- flexDirection: "row",
310
- alignItems: "center",
311
- gap: 6
312
- },
313
- changeBadge: {
314
- paddingHorizontal: 8,
315
- paddingVertical: 2,
316
- borderRadius: 4
317
- },
318
- changeText: {
319
- fontSize: 9,
320
- fontWeight: "700",
321
- fontFamily: _sharedUi.monoFont,
322
- letterSpacing: 0.3
323
- },
324
- typeBadge: {
325
- paddingHorizontal: 8,
326
- paddingVertical: 2,
327
- borderRadius: 4,
328
- backgroundColor: _sharedUi.night.color.surfaceElevated
329
- },
330
- typeText: {
331
- fontSize: 9,
332
- fontWeight: "600",
333
- color: _sharedUi.night.color.textTertiary,
334
- fontFamily: _sharedUi.monoFont
335
- },
336
- valueBox: {
337
- // Inset code box — darker than the card, the night track color.
338
- backgroundColor: _sharedUi.night.color.bg,
339
- borderRadius: 6,
340
- borderWidth: 1,
341
- borderColor: _sharedUi.night.color.border,
342
- padding: 8
343
- },
344
- valueText: {
345
- fontSize: 12,
346
- color: _sharedUi.night.color.text,
347
- fontFamily: _sharedUi.monoFont,
348
- lineHeight: 18
349
- },
350
- diffContainer: {
351
- flex: 1
352
- },
353
- diffContent: {
354
- flex: 1,
355
- paddingHorizontal: 14
356
- },
357
- changeBadgeSmall: {
358
- paddingHorizontal: 6,
359
- paddingVertical: 1,
360
- borderRadius: 3
361
- },
362
- changeTextSmall: {
363
- fontSize: 8,
364
- fontWeight: "700",
365
- fontFamily: _sharedUi.monoFont
366
- },
367
- dataViewerContainer: {
368
- marginTop: -12,
369
- marginHorizontal: -12,
370
- marginBottom: -12
371
- }
372
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.ZustandStateDetailContent=ZustandStateDetailContent;exports.ZustandStateDetailFooter=ZustandStateDetailFooter;var _reactNative=require("react-native");var _react=require("react");var _sharedUi=require("@buoy-gg/shared-ui");var _dataViewer=require("@buoy-gg/shared-ui/dataViewer");var _ZustandDetailViewToggle=require("./ZustandDetailViewToggle");var _ZustandStateInfoView=require("./ZustandStateInfoView");var _zustandStateStore=require("../utils/zustandStateStore");var _testIDs=require("../utils/testIDs");var _jsxRuntime=require("react/jsx-runtime");function getChangeColor(e){return _zustandStateStore.zustandStateStore.getStoreColor(e.storeName)}function getChangeLabel(e){switch(e.category){case"replace":return"REPLACE";case"persist":return"HYDRATE";case"initial":return"INIT";default:return"SET"}}function getValueType(e){if(e===null)return"null";if(e===void 0)return"undefined";if(Array.isArray(e))return"array";return typeof e}function formatTimestamp(e){const o=new Date(e);return o.toLocaleTimeString("en-US",{hour12:false,hour:"2-digit",minute:"2-digit",second:"2-digit"})}const DIFF_MODE_TABS=[{key:"tree",label:"TREE VIEW"},{key:"split",label:"SPLIT VIEW"}];function ZustandStateDetailContent({change:e,changes:o,selectedIndex:t,onIndexChange:r,disableInternalFooter:n=false,initialView:g="change"}){const[s,T]=(0,_react.useState)(g);const[m,b]=(0,_react.useState)("tree");const i=o.length;const l=getChangeColor(e);const d=getChangeLabel(e);const p=getValueType((0,_sharedUi.parseValue)(e.nextState));const u=i-t;const h=u-1;const c=t<i-1?t+1:null;const a=c!==null?o[c]:null;const w=(0,_react.useMemo)(()=>({index:c??0,label:h>0?`#${h}`:"Initial",timestamp:a?formatTimestamp(a.timestamp):"",relativeTime:a?(0,_sharedUi.formatRelativeTime)(new Date(a.timestamp)):"state",badge:a?(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.changeBadgeSmall,{backgroundColor:`${getChangeColor(a)}20`}],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.changeTextSmall,{color:getChangeColor(a)}],children:getChangeLabel(a)})}):void 0}),[c,a,h]);const y=(0,_react.useMemo)(()=>({index:t,label:`#${u}`,timestamp:formatTimestamp(e.timestamp),relativeTime:(0,_sharedUi.formatRelativeTime)(new Date(e.timestamp)),badge:(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.changeBadgeSmall,{backgroundColor:`${l}20`}],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.changeTextSmall,{color:l}],children:d})})}),[t,e.timestamp,l,d,u]);const V=(0,_react.useCallback)(()=>{const f=(0,_sharedUi.parseValue)(e.nextState);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.contentCard,testID:`${_testIDs.ZUSTAND_TEST_ID}-state-card`,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.valueHeader,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.valueLabel,children:"STATE AFTER CHANGE"}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.valueHeaderBadges,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.changeBadge,{backgroundColor:`${l}20`}],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.changeText,{color:l}],children:d})}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.typeBadge,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.typeText,testID:`${_testIDs.ZUSTAND_TEST_ID}-state-type`,children:p.toUpperCase()})})]})]}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.dataViewerContainer,children:(0,_jsxRuntime.jsx)(_dataViewer.DataViewer,{title:"",data:f,showTypeFilter:true,rawMode:true,initialExpanded:true})})]})},[e.nextState,l,d,p]);const v=(0,_react.useCallback)(()=>{const f=(0,_sharedUi.parseValue)(e.prevState);const x=(0,_sharedUi.parseValue)(e.nextState);if(m==="split"){return(0,_jsxRuntime.jsx)(_reactNative.ScrollView,{style:{flex:1},showsVerticalScrollIndicator:true,children:(0,_jsxRuntime.jsx)(_dataViewer.SplitDiffViewer,{oldValue:f,newValue:x,theme:_dataViewer.diffThemes.devToolsDefault,options:{hideLineNumbers:false,disableWordDiff:false,showDiffOnly:false,compareMethod:"words",contextLines:3},showThemeName:false})})}return(0,_jsxRuntime.jsx)(_dataViewer.TreeDiffViewer,{oldValue:f,newValue:x})},[e.prevState,e.nextState,m]);const D=(0,_react.useCallback)(()=>{r(Math.min(i-1,t+1))},[t,i,r]);const C=(0,_react.useCallback)(()=>{r(Math.max(0,t-1))},[t,r]);const j=e.prevState===void 0;const S=!n&&i>1;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.container,children:[(0,_jsxRuntime.jsx)(_ZustandDetailViewToggle.ZustandDetailViewToggle,{activeView:s,onViewChange:T,diffDisabled:j}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:[styles.contentArea,S&&styles.contentAreaFooterPad],children:[s==="change"&&(0,_jsxRuntime.jsx)(_ZustandStateInfoView.ZustandStateInfoView,{change:e}),s==="state"&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.stateContainer,children:V()}),s==="diff"&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.diffContainer,testID:`${_testIDs.ZUSTAND_TEST_ID}-diff`,children:[(0,_jsxRuntime.jsx)(_sharedUi.DiffModeTabs,{tabs:DIFF_MODE_TABS,activeTab:m,onTabChange:b,testIDPrefix:`${_testIDs.ZUSTAND_TEST_ID}-diff-tab`}),(0,_jsxRuntime.jsx)(_sharedUi.CompareBar,{leftEvent:w,rightEvent:y}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.diffContent,testID:`${_testIDs.ZUSTAND_TEST_ID}-diff-content`,children:v()})]})]}),S&&(0,_jsxRuntime.jsx)(_sharedUi.EventStepperFooter,{currentIndex:u-1,totalItems:i,onPrevious:D,onNext:C,itemLabel:"Change",subtitle:(0,_sharedUi.formatRelativeTime)(new Date(e.timestamp)),absolute:true})]})}function ZustandStateDetailFooter({change:e,changes:o,selectedIndex:t,onIndexChange:r}){const n=o.length;if(n<=1)return null;const g=n-t;return(0,_jsxRuntime.jsx)(_sharedUi.EventStepperFooter,{currentIndex:g-1,totalItems:n,onPrevious:()=>r(Math.min(n-1,t+1)),onNext:()=>r(Math.max(0,t-1)),itemLabel:"Change",subtitle:(0,_sharedUi.formatRelativeTime)(new Date(e.timestamp))})}const styles=_reactNative.StyleSheet.create({container:{flex:1,backgroundColor:"transparent"},contentArea:{flex:1},contentAreaFooterPad:{paddingBottom:96},stateContainer:{flex:1,padding:14},contentCard:{backgroundColor:_sharedUi.night.color.surface,borderRadius:14,padding:14,borderWidth:1,borderColor:_sharedUi.night.color.border},valueHeader:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",marginBottom:8},valueLabel:{fontSize:10,color:_sharedUi.night.color.textSecondary,fontFamily:_sharedUi.monoFont,letterSpacing:.5,fontWeight:"600"},valueHeaderBadges:{flexDirection:"row",alignItems:"center",gap:6},changeBadge:{paddingHorizontal:8,paddingVertical:2,borderRadius:4},changeText:{fontSize:9,fontWeight:"700",fontFamily:_sharedUi.monoFont,letterSpacing:.3},typeBadge:{paddingHorizontal:8,paddingVertical:2,borderRadius:4,backgroundColor:_sharedUi.night.color.surfaceElevated},typeText:{fontSize:9,fontWeight:"600",color:_sharedUi.night.color.textTertiary,fontFamily:_sharedUi.monoFont},valueBox:{backgroundColor:_sharedUi.night.color.bg,borderRadius:6,borderWidth:1,borderColor:_sharedUi.night.color.border,padding:8},valueText:{fontSize:12,color:_sharedUi.night.color.text,fontFamily:_sharedUi.monoFont,lineHeight:18},diffContainer:{flex:1},diffContent:{flex:1,paddingHorizontal:14},changeBadgeSmall:{paddingHorizontal:6,paddingVertical:1,borderRadius:3},changeTextSmall:{fontSize:8,fontWeight:"700",fontFamily:_sharedUi.monoFont},dataViewerContainer:{marginTop:-12,marginHorizontal:-12,marginBottom:-12}});