@buoy-gg/redux 7.0.40 → 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 (79) hide show
  1. package/README.md +11 -102
  2. package/lib/commonjs/index.js +1 -256
  3. package/lib/commonjs/preset.js +1 -90
  4. package/lib/commonjs/redux/components/ReduxActionButton.js +1 -131
  5. package/lib/commonjs/redux/components/ReduxActionDetailContent.js +1 -437
  6. package/lib/commonjs/redux/components/ReduxActionDetailView.js +1 -401
  7. package/lib/commonjs/redux/components/ReduxActionInfoView.js +1 -836
  8. package/lib/commonjs/redux/components/ReduxActionItem.js +1 -334
  9. package/lib/commonjs/redux/components/ReduxAutoInstrument.js +1 -20
  10. package/lib/commonjs/redux/components/ReduxDetailViewToggle.js +1 -50
  11. package/lib/commonjs/redux/components/ReduxIcon.js +1 -18
  12. package/lib/commonjs/redux/components/ReduxModal.js +1 -703
  13. package/lib/commonjs/redux/hooks/reduxPeer.js +1 -0
  14. package/lib/commonjs/redux/hooks/reduxPeer.web.js +1 -0
  15. package/lib/commonjs/redux/hooks/useAutoInstrumentRedux.js +1 -187
  16. package/lib/commonjs/redux/hooks/useReduxActions.js +1 -58
  17. package/lib/commonjs/redux/sync/reduxSyncAdapter.js +1 -191
  18. package/lib/commonjs/redux/types/index.js +1 -1
  19. package/lib/commonjs/redux/utils/activeStoreRegistry.js +1 -104
  20. package/lib/commonjs/redux/utils/autoInstrument.js +1 -231
  21. package/lib/commonjs/redux/utils/buoyReduxMiddleware.js +1 -202
  22. package/lib/commonjs/redux/utils/createReduxHistoryAdapter.js +1 -146
  23. package/lib/commonjs/redux/utils/devtoolsHook.js +1 -152
  24. package/lib/commonjs/redux/utils/reduxActionStore.js +1 -473
  25. package/lib/commonjs/redux/utils/snapshotProvider.js +1 -158
  26. package/lib/commonjs/redux/utils/testIDs.js +1 -75
  27. package/lib/module/index.js +1 -125
  28. package/lib/module/preset.js +1 -87
  29. package/lib/module/redux/components/ReduxActionButton.js +1 -128
  30. package/lib/module/redux/components/ReduxActionDetailContent.js +1 -433
  31. package/lib/module/redux/components/ReduxActionDetailView.js +1 -397
  32. package/lib/module/redux/components/ReduxActionInfoView.js +1 -831
  33. package/lib/module/redux/components/ReduxActionItem.js +1 -330
  34. package/lib/module/redux/components/ReduxAutoInstrument.js +1 -17
  35. package/lib/module/redux/components/ReduxDetailViewToggle.js +1 -45
  36. package/lib/module/redux/components/ReduxIcon.js +1 -8
  37. package/lib/module/redux/components/ReduxModal.js +1 -698
  38. package/lib/module/redux/hooks/reduxPeer.js +1 -0
  39. package/lib/module/redux/hooks/reduxPeer.web.js +1 -0
  40. package/lib/module/redux/hooks/useAutoInstrumentRedux.js +1 -183
  41. package/lib/module/redux/hooks/useReduxActions.js +1 -54
  42. package/lib/module/redux/sync/reduxSyncAdapter.js +1 -188
  43. package/lib/module/redux/types/index.js +1 -1
  44. package/lib/module/redux/utils/activeStoreRegistry.js +1 -92
  45. package/lib/module/redux/utils/autoInstrument.js +1 -201
  46. package/lib/module/redux/utils/buoyReduxMiddleware.js +1 -188
  47. package/lib/module/redux/utils/createReduxHistoryAdapter.js +1 -142
  48. package/lib/module/redux/utils/devtoolsHook.js +1 -145
  49. package/lib/module/redux/utils/reduxActionStore.js +1 -465
  50. package/lib/module/redux/utils/snapshotProvider.js +1 -157
  51. package/lib/module/redux/utils/testIDs.js +1 -68
  52. package/lib/typescript/redux/hooks/reduxPeer.d.ts +3 -0
  53. package/lib/typescript/redux/hooks/reduxPeer.web.d.ts +2 -0
  54. package/lib/typescript/redux/hooks/useAutoInstrumentRedux.d.ts +3 -15
  55. package/lib/web/index.mjs +1 -0
  56. package/package.json +36 -13
  57. package/lib/typescript/index.d.ts.map +0 -1
  58. package/lib/typescript/preset.d.ts.map +0 -1
  59. package/lib/typescript/redux/components/ReduxActionButton.d.ts.map +0 -1
  60. package/lib/typescript/redux/components/ReduxActionDetailContent.d.ts.map +0 -1
  61. package/lib/typescript/redux/components/ReduxActionDetailView.d.ts.map +0 -1
  62. package/lib/typescript/redux/components/ReduxActionInfoView.d.ts.map +0 -1
  63. package/lib/typescript/redux/components/ReduxActionItem.d.ts.map +0 -1
  64. package/lib/typescript/redux/components/ReduxAutoInstrument.d.ts.map +0 -1
  65. package/lib/typescript/redux/components/ReduxDetailViewToggle.d.ts.map +0 -1
  66. package/lib/typescript/redux/components/ReduxIcon.d.ts.map +0 -1
  67. package/lib/typescript/redux/components/ReduxModal.d.ts.map +0 -1
  68. package/lib/typescript/redux/hooks/useAutoInstrumentRedux.d.ts.map +0 -1
  69. package/lib/typescript/redux/hooks/useReduxActions.d.ts.map +0 -1
  70. package/lib/typescript/redux/sync/reduxSyncAdapter.d.ts.map +0 -1
  71. package/lib/typescript/redux/types/index.d.ts.map +0 -1
  72. package/lib/typescript/redux/utils/activeStoreRegistry.d.ts.map +0 -1
  73. package/lib/typescript/redux/utils/autoInstrument.d.ts.map +0 -1
  74. package/lib/typescript/redux/utils/buoyReduxMiddleware.d.ts.map +0 -1
  75. package/lib/typescript/redux/utils/createReduxHistoryAdapter.d.ts.map +0 -1
  76. package/lib/typescript/redux/utils/devtoolsHook.d.ts.map +0 -1
  77. package/lib/typescript/redux/utils/reduxActionStore.d.ts.map +0 -1
  78. package/lib/typescript/redux/utils/snapshotProvider.d.ts.map +0 -1
  79. package/lib/typescript/redux/utils/testIDs.d.ts.map +0 -1
@@ -1,437 +1 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.ReduxActionDetailContent = ReduxActionDetailContent;
7
- exports.ReduxActionDetailFooter = ReduxActionDetailFooter;
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 _ReduxDetailViewToggle = require("./ReduxDetailViewToggle");
13
- var _ReduxActionInfoView = require("./ReduxActionInfoView");
14
- var _testIDs = require("../utils/testIDs");
15
- var _reduxActionStore = require("../utils/reduxActionStore");
16
- var _jsxRuntime = require("react/jsx-runtime");
17
- /**
18
- * ReduxActionDetailContent
19
- *
20
- * Enhanced detail view for a Redux action with 3 view modes:
21
- * - ACTION: View action details, payload, meta, error
22
- * - STATE: View current state after action
23
- * - DIFF: Compare prev vs next state
24
- */
25
-
26
- /**
27
- * Get color for action type
28
- */
29
- function getActionColor(type) {
30
- if (type.includes("/pending")) return _sharedUi.macOSColors.semantic.warning;
31
- if (type.includes("/fulfilled")) return _sharedUi.macOSColors.semantic.success;
32
- if (type.includes("/rejected")) return _sharedUi.macOSColors.semantic.error;
33
- if (type.startsWith("@@")) return _sharedUi.macOSColors.text.muted;
34
- return _sharedUi.macOSColors.semantic.info;
35
- }
36
-
37
- /**
38
- * Get short action label
39
- */
40
- function getActionLabel(type) {
41
- if (type.includes("/pending")) return "PENDING";
42
- if (type.includes("/fulfilled")) return "FULFILLED";
43
- if (type.includes("/rejected")) return "REJECTED";
44
- if (type.startsWith("@@")) return "INTERNAL";
45
- const parts = type.split("/");
46
- return parts[parts.length - 1]?.toUpperCase() || "ACTION";
47
- }
48
-
49
- /**
50
- * Get the type (object, array, string, etc.)
51
- */
52
- function getValueType(value) {
53
- if (value === null) return "null";
54
- if (value === undefined) return "undefined";
55
- if (Array.isArray(value)) return "array";
56
- return typeof value;
57
- }
58
-
59
- /**
60
- * Format timestamp for display
61
- */
62
- function formatTimestamp(timestamp) {
63
- const date = new Date(timestamp);
64
- return date.toLocaleTimeString("en-US", {
65
- hour12: false,
66
- hour: "2-digit",
67
- minute: "2-digit",
68
- second: "2-digit"
69
- });
70
- }
71
-
72
- /**
73
- * Diff mode tabs configuration
74
- */
75
- const DIFF_MODE_TABS = [{
76
- key: "tree",
77
- label: "TREE VIEW"
78
- }, {
79
- key: "split",
80
- label: "SPLIT VIEW"
81
- }];
82
- function ReduxActionDetailContent({
83
- action,
84
- actions,
85
- selectedIndex,
86
- onIndexChange,
87
- disableInternalFooter = false,
88
- initialView = "action"
89
- }) {
90
- // View state (initialView seeds it once; taps own it afterwards)
91
- const [activeView, setActiveView] = (0, _react.useState)(initialView);
92
- const [diffMode, setDiffMode] = (0, _react.useState)("tree");
93
- const totalActions = actions.length;
94
- /**
95
- * The state trees this action was recorded with are gone.
96
- *
97
- * Not a failure: the store keeps raw prev/next state for the most recent
98
- * actions only, because with structural sharing broken (a store switch, a
99
- * rehydration) each retained action pins a distinct multi-MB subtree and a
100
- * few dozen of them are enough to OOM-kill a large app. But it has to be
101
- * SAID. The sentinel left behind is an ordinary object, so a state view that
102
- * just rendered it showed `{ __buoyStateEvicted: true, … }` under the
103
- * heading "STATE AFTER ACTION" — which reads as the app's actual state — and
104
- * a diff of two identical sentinels reported "no changes", which is a lie
105
- * about the app rather than about the recording.
106
- */
107
- const stateEvicted = (0, _reduxActionStore.isEvictedState)(action.nextState);
108
- const actionColor = getActionColor(action.type);
109
- const actionLabel = getActionLabel(action.type);
110
- const stateType = getValueType((0, _sharedUi.parseValue)(action.nextState));
111
-
112
- // Actions are in reverse chronological order (newest first, oldest last)
113
- const chronologicalNumber = totalActions - selectedIndex;
114
- const prevChronologicalNumber = chronologicalNumber - 1;
115
-
116
- // Get the previous action in chronological order (which is the NEXT index in the array)
117
- const prevActionIndex = selectedIndex < totalActions - 1 ? selectedIndex + 1 : null;
118
- const prevAction = prevActionIndex !== null ? actions[prevActionIndex] : null;
119
-
120
- // Compare bar info for diff view
121
- const leftEvent = (0, _react.useMemo)(() => ({
122
- index: prevActionIndex ?? 0,
123
- label: prevChronologicalNumber > 0 ? `#${prevChronologicalNumber}` : "Initial",
124
- timestamp: prevAction ? formatTimestamp(prevAction.timestamp) : "",
125
- relativeTime: prevAction ? (0, _sharedUi.formatRelativeTime)(new Date(prevAction.timestamp)) : "state",
126
- badge: prevAction ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
127
- style: [styles.actionBadgeSmall, {
128
- backgroundColor: `${getActionColor(prevAction.type)}20`
129
- }],
130
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
131
- style: [styles.actionTextSmall, {
132
- color: getActionColor(prevAction.type)
133
- }],
134
- children: getActionLabel(prevAction.type)
135
- })
136
- }) : undefined
137
- }), [prevActionIndex, prevAction, prevChronologicalNumber]);
138
- const rightEvent = (0, _react.useMemo)(() => ({
139
- index: selectedIndex,
140
- label: `#${chronologicalNumber}`,
141
- timestamp: formatTimestamp(action.timestamp),
142
- relativeTime: (0, _sharedUi.formatRelativeTime)(new Date(action.timestamp)),
143
- badge: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
144
- style: [styles.actionBadgeSmall, {
145
- backgroundColor: `${actionColor}20`
146
- }],
147
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
148
- style: [styles.actionTextSmall, {
149
- color: actionColor
150
- }],
151
- children: actionLabel
152
- })
153
- })
154
- }), [selectedIndex, action.timestamp, actionColor, actionLabel, chronologicalNumber]);
155
-
156
- // Render state view
157
- const renderStateView = (0, _react.useCallback)(() => {
158
- if (stateEvicted) {
159
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
160
- style: styles.contentCard,
161
- testID: `${_testIDs.REDUX_TEST_ID}-state-evicted`,
162
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
163
- style: styles.valueHeader,
164
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
165
- style: styles.valueLabel,
166
- children: "STATE AFTER ACTION"
167
- })
168
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
169
- style: styles.evictedText,
170
- children: `Not retained. Raw state is kept for the ${_reduxActionStore.STATE_RETENTION_LIMIT} most recent actions, so this action's before/after trees have been released.`
171
- })]
172
- });
173
- }
174
- const parsed = (0, _sharedUi.parseValue)(action.nextState);
175
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
176
- style: styles.contentCard,
177
- testID: `${_testIDs.REDUX_TEST_ID}-state-card`,
178
- children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
179
- style: styles.valueHeader,
180
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
181
- style: styles.valueLabel,
182
- children: "STATE AFTER ACTION"
183
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
184
- style: styles.valueHeaderBadges,
185
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
186
- style: [styles.actionBadge, {
187
- backgroundColor: `${actionColor}20`
188
- }],
189
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
190
- style: [styles.actionText, {
191
- color: actionColor
192
- }],
193
- children: actionLabel
194
- })
195
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
196
- style: styles.typeBadge,
197
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
198
- style: styles.typeText,
199
- testID: `${_testIDs.REDUX_TEST_ID}-state-type`,
200
- children: stateType.toUpperCase()
201
- })
202
- })]
203
- })]
204
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
205
- style: styles.dataViewerContainer,
206
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.DataViewer, {
207
- title: "",
208
- data: parsed,
209
- showTypeFilter: true,
210
- rawMode: true,
211
- initialExpanded: true
212
- })
213
- })]
214
- });
215
- }, [action.nextState, actionColor, actionLabel, stateType, stateEvicted]);
216
-
217
- // Render diff content
218
- const renderDiffContent = (0, _react.useCallback)(() => {
219
- const prevState = (0, _sharedUi.parseValue)(action.prevState);
220
- const nextState = (0, _sharedUi.parseValue)(action.nextState);
221
- if (diffMode === "split") {
222
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ScrollView, {
223
- style: {
224
- flex: 1
225
- },
226
- showsVerticalScrollIndicator: true,
227
- children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.SplitDiffViewer, {
228
- oldValue: prevState,
229
- newValue: nextState,
230
- theme: _dataViewer.diffThemes.devToolsDefault,
231
- options: {
232
- hideLineNumbers: false,
233
- disableWordDiff: false,
234
- showDiffOnly: false,
235
- compareMethod: "words",
236
- contextLines: 3
237
- },
238
- showThemeName: false
239
- })
240
- });
241
- }
242
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_dataViewer.TreeDiffViewer, {
243
- oldValue: prevState,
244
- newValue: nextState
245
- });
246
- }, [action.prevState, action.nextState, diffMode]);
247
-
248
- // Navigation handlers
249
- const handleFooterPrevious = (0, _react.useCallback)(() => {
250
- onIndexChange(Math.min(totalActions - 1, selectedIndex + 1));
251
- }, [selectedIndex, totalActions, onIndexChange]);
252
- const handleFooterNext = (0, _react.useCallback)(() => {
253
- onIndexChange(Math.max(0, selectedIndex - 1));
254
- }, [selectedIndex, onIndexChange]);
255
-
256
- // A diff needs two real trees, and both live on THIS action
257
- // (prevState/nextState) — no siblings needed, so the action count says
258
- // nothing (gating on it greyed DIFF out for every redux event opened from
259
- // the Events timeline, which passes a one-element array). Eviction of
260
- // EITHER side does disable it: two identical sentinels diff cleanly to
261
- // "no changes", which reads as a lie.
262
- const diffDisabled = stateEvicted || (0, _reduxActionStore.isEvictedState)(action.prevState) || action.prevState === undefined;
263
- const showInternalFooter = !disableInternalFooter && totalActions > 1;
264
- return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
265
- style: styles.container,
266
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_ReduxDetailViewToggle.ReduxDetailViewToggle, {
267
- activeView: activeView,
268
- onViewChange: setActiveView,
269
- diffDisabled: diffDisabled
270
- }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
271
- style: [styles.contentArea, showInternalFooter && styles.contentAreaFooterPad],
272
- children: [activeView === "action" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_ReduxActionInfoView.ReduxActionInfoView, {
273
- action: action
274
- }), activeView === "state" && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
275
- style: styles.stateContainer,
276
- children: renderStateView()
277
- }), activeView === "diff" && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
278
- style: styles.diffContainer,
279
- testID: `${_testIDs.REDUX_TEST_ID}-diff`,
280
- children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.DiffModeTabs, {
281
- tabs: DIFF_MODE_TABS,
282
- activeTab: diffMode,
283
- onTabChange: setDiffMode,
284
- testIDPrefix: `${_testIDs.REDUX_TEST_ID}-diff-tab`
285
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.CompareBar, {
286
- leftEvent: leftEvent,
287
- rightEvent: rightEvent
288
- }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
289
- style: styles.diffContent,
290
- testID: `${_testIDs.REDUX_TEST_ID}-diff-content`,
291
- children: renderDiffContent()
292
- })]
293
- })]
294
- }), showInternalFooter && /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.EventStepperFooter, {
295
- currentIndex: chronologicalNumber - 1,
296
- totalItems: totalActions,
297
- onPrevious: handleFooterPrevious,
298
- onNext: handleFooterNext,
299
- itemLabel: "Action",
300
- subtitle: (0, _sharedUi.formatRelativeTime)(new Date(action.timestamp)),
301
- absolute: true
302
- })]
303
- });
304
- }
305
-
306
- /**
307
- * External footer component for modal use
308
- */
309
- function ReduxActionDetailFooter({
310
- action,
311
- actions,
312
- selectedIndex,
313
- onIndexChange
314
- }) {
315
- const totalActions = actions.length;
316
- if (totalActions <= 1) return null;
317
- const chronologicalNumber = totalActions - selectedIndex;
318
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.EventStepperFooter, {
319
- currentIndex: chronologicalNumber - 1,
320
- totalItems: totalActions,
321
- onPrevious: () => onIndexChange(Math.min(totalActions - 1, selectedIndex + 1)),
322
- onNext: () => onIndexChange(Math.max(0, selectedIndex - 1)),
323
- itemLabel: "Action",
324
- subtitle: (0, _sharedUi.formatRelativeTime)(new Date(action.timestamp))
325
- });
326
- }
327
- const styles = _reactNative.StyleSheet.create({
328
- container: {
329
- flex: 1,
330
- // Transparent so the night sheet's star field shows through.
331
- backgroundColor: "transparent"
332
- },
333
- contentArea: {
334
- flex: 1
335
- },
336
- // Clearance for the absolute EventStepperFooter — only when it renders,
337
- // otherwise hosts like the Events tool get a dead band at the sheet bottom.
338
- contentAreaFooterPad: {
339
- paddingBottom: 96
340
- },
341
- // State view styles
342
- stateContainer: {
343
- flex: 1,
344
- padding: 14
345
- },
346
- contentCard: {
347
- backgroundColor: _sharedUi.night.color.surface,
348
- borderRadius: 14,
349
- padding: 14,
350
- borderWidth: 1,
351
- borderColor: _sharedUi.night.color.border
352
- },
353
- valueHeader: {
354
- flexDirection: "row",
355
- alignItems: "center",
356
- justifyContent: "space-between",
357
- marginBottom: 8
358
- },
359
- valueLabel: {
360
- fontSize: 10,
361
- color: _sharedUi.night.color.textSecondary,
362
- fontFamily: _sharedUi.monoFont,
363
- letterSpacing: 0.5,
364
- fontWeight: "600"
365
- },
366
- valueHeaderBadges: {
367
- flexDirection: "row",
368
- alignItems: "center",
369
- gap: 6
370
- },
371
- actionBadge: {
372
- paddingHorizontal: 8,
373
- paddingVertical: 2,
374
- borderRadius: 4
375
- },
376
- actionText: {
377
- fontSize: 9,
378
- fontWeight: "700",
379
- fontFamily: _sharedUi.monoFont,
380
- letterSpacing: 0.3
381
- },
382
- typeBadge: {
383
- paddingHorizontal: 8,
384
- paddingVertical: 2,
385
- borderRadius: 4,
386
- backgroundColor: _sharedUi.night.color.surfaceElevated
387
- },
388
- typeText: {
389
- fontSize: 9,
390
- fontWeight: "600",
391
- color: _sharedUi.night.color.textTertiary,
392
- fontFamily: _sharedUi.monoFont
393
- },
394
- valueBox: {
395
- // Inset code box — darker than the card, the night track color.
396
- backgroundColor: _sharedUi.night.color.bg,
397
- borderRadius: 6,
398
- borderWidth: 1,
399
- borderColor: _sharedUi.night.color.border,
400
- padding: 8
401
- },
402
- evictedText: {
403
- fontSize: 12,
404
- color: _sharedUi.night.color.textSecondary,
405
- lineHeight: 18
406
- },
407
- valueText: {
408
- fontSize: 12,
409
- color: _sharedUi.night.color.text,
410
- fontFamily: _sharedUi.monoFont,
411
- lineHeight: 18
412
- },
413
- // Diff view styles
414
- diffContainer: {
415
- flex: 1
416
- },
417
- diffContent: {
418
- flex: 1,
419
- paddingHorizontal: 14
420
- },
421
- // Action badges for compare bar
422
- actionBadgeSmall: {
423
- paddingHorizontal: 6,
424
- paddingVertical: 1,
425
- borderRadius: 3
426
- },
427
- actionTextSmall: {
428
- fontSize: 8,
429
- fontWeight: "700",
430
- fontFamily: _sharedUi.monoFont
431
- },
432
- dataViewerContainer: {
433
- marginTop: -12,
434
- marginHorizontal: -12,
435
- marginBottom: -12
436
- }
437
- });
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.ReduxActionDetailContent=ReduxActionDetailContent;exports.ReduxActionDetailFooter=ReduxActionDetailFooter;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 _ReduxDetailViewToggle=require("./ReduxDetailViewToggle");var _ReduxActionInfoView=require("./ReduxActionInfoView");var _testIDs=require("../utils/testIDs");var _reduxActionStore=require("../utils/reduxActionStore");var _jsxRuntime=require("react/jsx-runtime");function getActionColor(e){if(e.includes("/pending"))return _sharedUi.macOSColors.semantic.warning;if(e.includes("/fulfilled"))return _sharedUi.macOSColors.semantic.success;if(e.includes("/rejected"))return _sharedUi.macOSColors.semantic.error;if(e.startsWith("@@"))return _sharedUi.macOSColors.text.muted;return _sharedUi.macOSColors.semantic.info}function getActionLabel(e){if(e.includes("/pending"))return"PENDING";if(e.includes("/fulfilled"))return"FULFILLED";if(e.includes("/rejected"))return"REJECTED";if(e.startsWith("@@"))return"INTERNAL";const r=e.split("/");return r[r.length-1]?.toUpperCase()||"ACTION"}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 r=new Date(e);return r.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 ReduxActionDetailContent({action:e,actions:r,selectedIndex:t,onIndexChange:o,disableInternalFooter:n=false,initialView:m="action"}){const[s,b]=(0,_react.useState)(m);const[x,v]=(0,_react.useState)("tree");const a=r.length;const g=(0,_reduxActionStore.isEvictedState)(e.nextState);const l=getActionColor(e.type);const c=getActionLabel(e.type);const p=getValueType((0,_sharedUi.parseValue)(e.nextState));const d=a-t;const h=d-1;const u=t<a-1?t+1:null;const i=u!==null?r[u]:null;const w=(0,_react.useMemo)(()=>({index:u??0,label:h>0?`#${h}`:"Initial",timestamp:i?formatTimestamp(i.timestamp):"",relativeTime:i?(0,_sharedUi.formatRelativeTime)(new Date(i.timestamp)):"state",badge:i?(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.actionBadgeSmall,{backgroundColor:`${getActionColor(i.type)}20`}],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.actionTextSmall,{color:getActionColor(i.type)}],children:getActionLabel(i.type)})}):void 0}),[u,i,h]);const y=(0,_react.useMemo)(()=>({index:t,label:`#${d}`,timestamp:formatTimestamp(e.timestamp),relativeTime:(0,_sharedUi.formatRelativeTime)(new Date(e.timestamp)),badge:(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.actionBadgeSmall,{backgroundColor:`${l}20`}],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.actionTextSmall,{color:l}],children:c})})}),[t,e.timestamp,l,c,d]);const D=(0,_react.useCallback)(()=>{if(g){return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.contentCard,testID:`${_testIDs.REDUX_TEST_ID}-state-evicted`,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.valueHeader,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.valueLabel,children:"STATE AFTER ACTION"})}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.evictedText,children:`Not retained. Raw state is kept for the ${_reduxActionStore.STATE_RETENTION_LIMIT} most recent actions, so this action's before/after trees have been released.`})]})}const f=(0,_sharedUi.parseValue)(e.nextState);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.contentCard,testID:`${_testIDs.REDUX_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 ACTION"}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.valueHeaderBadges,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.actionBadge,{backgroundColor:`${l}20`}],children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.actionText,{color:l}],children:c})}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.typeBadge,children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.typeText,testID:`${_testIDs.REDUX_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,c,p,g]);const V=(0,_react.useCallback)(()=>{const f=(0,_sharedUi.parseValue)(e.prevState);const S=(0,_sharedUi.parseValue)(e.nextState);if(x==="split"){return(0,_jsxRuntime.jsx)(_reactNative.ScrollView,{style:{flex:1},showsVerticalScrollIndicator:true,children:(0,_jsxRuntime.jsx)(_dataViewer.SplitDiffViewer,{oldValue:f,newValue:S,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:S})},[e.prevState,e.nextState,x]);const C=(0,_react.useCallback)(()=>{o(Math.min(a-1,t+1))},[t,a,o]);const E=(0,_react.useCallback)(()=>{o(Math.max(0,t-1))},[t,o]);const j=g||(0,_reduxActionStore.isEvictedState)(e.prevState)||e.prevState===void 0;const T=!n&&a>1;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.container,children:[(0,_jsxRuntime.jsx)(_ReduxDetailViewToggle.ReduxDetailViewToggle,{activeView:s,onViewChange:b,diffDisabled:j}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:[styles.contentArea,T&&styles.contentAreaFooterPad],children:[s==="action"&&(0,_jsxRuntime.jsx)(_ReduxActionInfoView.ReduxActionInfoView,{action:e}),s==="state"&&(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.stateContainer,children:D()}),s==="diff"&&(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.diffContainer,testID:`${_testIDs.REDUX_TEST_ID}-diff`,children:[(0,_jsxRuntime.jsx)(_sharedUi.DiffModeTabs,{tabs:DIFF_MODE_TABS,activeTab:x,onTabChange:v,testIDPrefix:`${_testIDs.REDUX_TEST_ID}-diff-tab`}),(0,_jsxRuntime.jsx)(_sharedUi.CompareBar,{leftEvent:w,rightEvent:y}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.diffContent,testID:`${_testIDs.REDUX_TEST_ID}-diff-content`,children:V()})]})]}),T&&(0,_jsxRuntime.jsx)(_sharedUi.EventStepperFooter,{currentIndex:d-1,totalItems:a,onPrevious:C,onNext:E,itemLabel:"Action",subtitle:(0,_sharedUi.formatRelativeTime)(new Date(e.timestamp)),absolute:true})]})}function ReduxActionDetailFooter({action:e,actions:r,selectedIndex:t,onIndexChange:o}){const n=r.length;if(n<=1)return null;const m=n-t;return(0,_jsxRuntime.jsx)(_sharedUi.EventStepperFooter,{currentIndex:m-1,totalItems:n,onPrevious:()=>o(Math.min(n-1,t+1)),onNext:()=>o(Math.max(0,t-1)),itemLabel:"Action",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},actionBadge:{paddingHorizontal:8,paddingVertical:2,borderRadius:4},actionText:{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},evictedText:{fontSize:12,color:_sharedUi.night.color.textSecondary,lineHeight:18},valueText:{fontSize:12,color:_sharedUi.night.color.text,fontFamily:_sharedUi.monoFont,lineHeight:18},diffContainer:{flex:1},diffContent:{flex:1,paddingHorizontal:14},actionBadgeSmall:{paddingHorizontal:6,paddingVertical:1,borderRadius:3},actionTextSmall:{fontSize:8,fontWeight:"700",fontFamily:_sharedUi.monoFont},dataViewerContainer:{marginTop:-12,marginHorizontal:-12,marginBottom:-12}});