@buoy-gg/redux 2.1.12 → 2.1.13

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 +1 -179
  2. package/lib/commonjs/preset.js +1 -98
  3. package/lib/commonjs/redux/components/ReduxActionButton.js +1 -129
  4. package/lib/commonjs/redux/components/ReduxActionDetailContent.js +1 -380
  5. package/lib/commonjs/redux/components/ReduxActionDetailView.js +1 -401
  6. package/lib/commonjs/redux/components/ReduxActionInfoView.js +1 -838
  7. package/lib/commonjs/redux/components/ReduxActionItem.js +1 -366
  8. package/lib/commonjs/redux/components/ReduxDetailViewToggle.js +1 -134
  9. package/lib/commonjs/redux/components/ReduxIcon.js +1 -18
  10. package/lib/commonjs/redux/components/ReduxModal.js +1 -530
  11. package/lib/commonjs/redux/components/index.js +1 -52
  12. package/lib/commonjs/redux/hooks/index.js +1 -25
  13. package/lib/commonjs/redux/hooks/useAutoInstrumentRedux.js +1 -197
  14. package/lib/commonjs/redux/hooks/useReduxActions.js +1 -75
  15. package/lib/commonjs/redux/index.js +1 -49
  16. package/lib/commonjs/redux/utils/autoInstrument.js +1 -270
  17. package/lib/commonjs/redux/utils/buoyReduxMiddleware.js +1 -166
  18. package/lib/commonjs/redux/utils/createReduxHistoryAdapter.js +1 -146
  19. package/lib/commonjs/redux/utils/index.js +1 -111
  20. package/lib/commonjs/redux/utils/reduxActionStore.js +1 -358
  21. package/lib/module/index.js +1 -87
  22. package/lib/module/preset.js +1 -94
  23. package/lib/module/redux/components/ReduxActionButton.js +1 -126
  24. package/lib/module/redux/components/ReduxActionDetailContent.js +1 -376
  25. package/lib/module/redux/components/ReduxActionDetailView.js +1 -397
  26. package/lib/module/redux/components/ReduxActionInfoView.js +1 -833
  27. package/lib/module/redux/components/ReduxActionItem.js +1 -362
  28. package/lib/module/redux/components/ReduxDetailViewToggle.js +1 -129
  29. package/lib/module/redux/components/ReduxIcon.js +1 -8
  30. package/lib/module/redux/components/ReduxModal.js +1 -525
  31. package/lib/module/redux/components/index.js +1 -7
  32. package/lib/module/redux/hooks/index.js +1 -4
  33. package/lib/module/redux/hooks/useAutoInstrumentRedux.js +1 -193
  34. package/lib/module/redux/hooks/useReduxActions.js +1 -71
  35. package/lib/module/redux/index.js +1 -13
  36. package/lib/module/redux/utils/autoInstrument.js +1 -260
  37. package/lib/module/redux/utils/buoyReduxMiddleware.js +1 -157
  38. package/lib/module/redux/utils/createReduxHistoryAdapter.js +1 -142
  39. package/lib/module/redux/utils/index.js +1 -8
  40. package/lib/module/redux/utils/reduxActionStore.js +1 -354
  41. package/package.json +4 -4
  42. package/lib/typescript/index.d.ts.map +0 -1
  43. package/lib/typescript/preset.d.ts.map +0 -1
  44. package/lib/typescript/redux/components/ReduxActionButton.d.ts.map +0 -1
  45. package/lib/typescript/redux/components/ReduxActionDetailContent.d.ts.map +0 -1
  46. package/lib/typescript/redux/components/ReduxActionDetailView.d.ts.map +0 -1
  47. package/lib/typescript/redux/components/ReduxActionInfoView.d.ts.map +0 -1
  48. package/lib/typescript/redux/components/ReduxActionItem.d.ts.map +0 -1
  49. package/lib/typescript/redux/components/ReduxDetailViewToggle.d.ts.map +0 -1
  50. package/lib/typescript/redux/components/ReduxIcon.d.ts.map +0 -1
  51. package/lib/typescript/redux/components/ReduxModal.d.ts.map +0 -1
  52. package/lib/typescript/redux/components/index.d.ts.map +0 -1
  53. package/lib/typescript/redux/hooks/index.d.ts.map +0 -1
  54. package/lib/typescript/redux/hooks/useAutoInstrumentRedux.d.ts.map +0 -1
  55. package/lib/typescript/redux/hooks/useReduxActions.d.ts.map +0 -1
  56. package/lib/typescript/redux/index.d.ts.map +0 -1
  57. package/lib/typescript/redux/types/index.d.ts.map +0 -1
  58. package/lib/typescript/redux/utils/autoInstrument.d.ts.map +0 -1
  59. package/lib/typescript/redux/utils/buoyReduxMiddleware.d.ts.map +0 -1
  60. package/lib/typescript/redux/utils/createReduxHistoryAdapter.d.ts.map +0 -1
  61. package/lib/typescript/redux/utils/index.d.ts.map +0 -1
  62. package/lib/typescript/redux/utils/reduxActionStore.d.ts.map +0 -1
@@ -1,833 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * ReduxActionInfoView
5
- *
6
- * Displays comprehensive action information including:
7
- * - Action metadata (type, slice, category, duration)
8
- * - Payload data
9
- * - Async thunk metadata (requestId, status, arg)
10
- * - Error details for rejected actions
11
- */
12
-
13
- import React, { memo, useMemo, useCallback, useState, useEffect } from "react";
14
- import { View, Text, StyleSheet, ScrollView, TouchableOpacity } from "react-native";
15
- import { buoyColors, Clock, AlertTriangle, Zap, Hash, Info, Box, AlertCircle, FileText, parseValue, ProUpgradeModal, copyToClipboard } from "@buoy-gg/shared-ui";
16
- import { useIsPro } from "@buoy-gg/license";
17
- import { DataViewer } from "@buoy-gg/shared-ui/dataViewer";
18
- import { reduxActionStore } from "../utils/reduxActionStore";
19
- import { jumpToState, replayAction } from "../utils/buoyReduxMiddleware";
20
- import { ReduxActionButton } from "./ReduxActionButton";
21
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
22
- /**
23
- * Get category display info
24
- */
25
- function getCategoryInfo(category) {
26
- switch (category) {
27
- case "pending":
28
- return {
29
- label: "PENDING",
30
- color: buoyColors.warning,
31
- bgColor: buoyColors.warning + "26"
32
- };
33
- case "fulfilled":
34
- return {
35
- label: "FULFILLED",
36
- color: buoyColors.success,
37
- bgColor: buoyColors.success + "26"
38
- };
39
- case "rejected":
40
- return {
41
- label: "REJECTED",
42
- color: buoyColors.error,
43
- bgColor: buoyColors.error + "26"
44
- };
45
- case "internal":
46
- return {
47
- label: "INTERNAL",
48
- color: buoyColors.textMuted,
49
- bgColor: buoyColors.textMuted + "26"
50
- };
51
- case "query":
52
- return {
53
- label: "QUERY",
54
- color: buoyColors.info,
55
- bgColor: buoyColors.info + "26"
56
- };
57
- case "mutation":
58
- return {
59
- label: "MUTATION",
60
- color: buoyColors.info,
61
- bgColor: buoyColors.info + "26"
62
- };
63
- default:
64
- return {
65
- label: "ACTION",
66
- color: buoyColors.info,
67
- bgColor: buoyColors.info + "26"
68
- };
69
- }
70
- }
71
-
72
- /**
73
- * Format duration for display
74
- */
75
- function formatDuration(duration) {
76
- if (duration === undefined) return "N/A";
77
- if (duration < 1) return "<1ms";
78
- return `${duration.toFixed(1)}ms`;
79
- }
80
-
81
- /**
82
- * Section header component - matches React Query DevTools styling
83
- */
84
- function SectionHeader({
85
- icon: Icon,
86
- title,
87
- badge
88
- }) {
89
- return /*#__PURE__*/_jsxs(View, {
90
- style: styles.sectionHeader,
91
- children: [/*#__PURE__*/_jsxs(View, {
92
- style: styles.sectionHeaderLeft,
93
- children: [/*#__PURE__*/_jsx(Icon, {
94
- size: 14,
95
- color: buoyColors.primary
96
- }), /*#__PURE__*/_jsx(Text, {
97
- style: styles.sectionTitle,
98
- children: title
99
- })]
100
- }), badge]
101
- });
102
- }
103
-
104
- /**
105
- * Info row component for key-value display
106
- */
107
- function InfoRow({
108
- label,
109
- value,
110
- valueColor,
111
- mono = false
112
- }) {
113
- return /*#__PURE__*/_jsxs(View, {
114
- style: styles.infoRow,
115
- children: [/*#__PURE__*/_jsx(Text, {
116
- style: styles.infoLabel,
117
- children: label
118
- }), /*#__PURE__*/_jsx(Text, {
119
- style: [styles.infoValue, mono && styles.infoValueMono, valueColor && {
120
- color: valueColor
121
- }],
122
- numberOfLines: 1,
123
- ellipsizeMode: "middle",
124
- children: value
125
- })]
126
- });
127
- }
128
-
129
- /**
130
- * Format timestamp for display
131
- */
132
- function formatTime(timestamp) {
133
- const date = new Date(timestamp);
134
- const hours = date.getHours().toString().padStart(2, "0");
135
- const minutes = date.getMinutes().toString().padStart(2, "0");
136
- const seconds = date.getSeconds().toString().padStart(2, "0");
137
- const ms = date.getMilliseconds().toString().padStart(3, "0");
138
- return `${hours}:${minutes}:${seconds}.${ms}`;
139
- }
140
- export const ReduxActionInfoView = /*#__PURE__*/memo(function ReduxActionInfoView({
141
- action,
142
- onNavigateToAction
143
- }) {
144
- const isPro = useIsPro();
145
- const [showProModal, setShowProModal] = useState(false);
146
-
147
- // Auto-close modal when user becomes Pro
148
- useEffect(() => {
149
- if (showProModal && isPro) {
150
- setShowProModal(false);
151
- }
152
- }, [showProModal, isPro]);
153
- const categoryInfo = getCategoryInfo(action.category);
154
- const hasPayload = action.payload !== undefined;
155
- const hasMeta = action.meta && Object.keys(action.meta).length > 0;
156
- const hasError = action.error !== undefined;
157
-
158
- // Get related async actions
159
- const relatedActions = useMemo(() => {
160
- return reduxActionStore.getLinkedActions(action);
161
- }, [action]);
162
- const hasRelatedActions = relatedActions.length > 1;
163
- const baseActionType = hasRelatedActions ? reduxActionStore.getBaseActionType(action.type) : null;
164
- const totalDuration = action.meta?.requestId ? reduxActionStore.getAsyncOperationDuration(action.meta.requestId) : null;
165
-
166
- // Action handlers - copy requires Pro
167
- const handleCopyAction = useCallback(async () => {
168
- if (!isPro) {
169
- setShowProModal(true);
170
- return;
171
- }
172
- await copyToClipboard(action.action);
173
- }, [action, isPro]);
174
- const handleCopyPayload = useCallback(async () => {
175
- if (!isPro) {
176
- setShowProModal(true);
177
- return;
178
- }
179
- await copyToClipboard(action.payload);
180
- }, [action.payload, isPro]);
181
- const handleReplay = useCallback(() => {
182
- // Replay the original action
183
- if (action.action && typeof action.action === "object" && "type" in action.action) {
184
- replayAction(action.action);
185
- }
186
- }, [action]);
187
- const handleJump = useCallback(() => {
188
- // Jump to the state after this action was applied
189
- if (action.nextState !== undefined) {
190
- jumpToState(action.nextState);
191
- }
192
- }, [action]);
193
- return /*#__PURE__*/_jsxs(ScrollView, {
194
- style: styles.container,
195
- contentContainerStyle: styles.contentContainer,
196
- showsVerticalScrollIndicator: false,
197
- children: [/*#__PURE__*/_jsxs(View, {
198
- style: styles.card,
199
- children: [/*#__PURE__*/_jsx(SectionHeader, {
200
- icon: Info,
201
- title: "ACTION INFO"
202
- }), /*#__PURE__*/_jsxs(View, {
203
- style: styles.cardContent,
204
- children: [/*#__PURE__*/_jsx(InfoRow, {
205
- label: "Type",
206
- value: action.type,
207
- mono: true
208
- }), action.sliceName && /*#__PURE__*/_jsx(InfoRow, {
209
- label: "Slice",
210
- value: action.sliceName,
211
- mono: true
212
- }), /*#__PURE__*/_jsx(InfoRow, {
213
- label: "Action",
214
- value: action.actionName,
215
- mono: true
216
- }), /*#__PURE__*/_jsxs(View, {
217
- style: styles.badgeRow,
218
- children: [/*#__PURE__*/_jsx(View, {
219
- style: [styles.categoryBadge, {
220
- backgroundColor: categoryInfo.bgColor
221
- }],
222
- children: /*#__PURE__*/_jsx(Text, {
223
- style: [styles.categoryText, {
224
- color: categoryInfo.color
225
- }],
226
- children: categoryInfo.label
227
- })
228
- }), /*#__PURE__*/_jsxs(View, {
229
- style: [styles.durationBadge, action.isSlowAction && styles.durationBadgeSlow],
230
- children: [/*#__PURE__*/_jsx(Clock, {
231
- size: 10,
232
- color: action.isSlowAction ? buoyColors.error : buoyColors.textSecondary
233
- }), /*#__PURE__*/_jsx(Text, {
234
- style: [styles.durationText, action.isSlowAction && styles.durationTextSlow],
235
- children: formatDuration(action.duration)
236
- }), action.isSlowAction && /*#__PURE__*/_jsx(AlertTriangle, {
237
- size: 10,
238
- color: buoyColors.error
239
- })]
240
- }), action.hasStateChange ? /*#__PURE__*/_jsxs(View, {
241
- style: styles.changesBadge,
242
- children: [/*#__PURE__*/_jsx(Zap, {
243
- size: 10,
244
- color: buoyColors.success
245
- }), /*#__PURE__*/_jsx(Text, {
246
- style: styles.changesText,
247
- children: action.diffSummary || "changed"
248
- })]
249
- }) : /*#__PURE__*/_jsx(View, {
250
- style: styles.noChangesBadge,
251
- children: /*#__PURE__*/_jsx(Text, {
252
- style: styles.noChangesText,
253
- children: "no change"
254
- })
255
- })]
256
- })]
257
- })]
258
- }), hasRelatedActions && /*#__PURE__*/_jsxs(View, {
259
- style: styles.card,
260
- children: [/*#__PURE__*/_jsx(SectionHeader, {
261
- icon: Hash,
262
- title: "ASYNC FLOW",
263
- badge: /*#__PURE__*/_jsx(View, {
264
- style: styles.asyncBadge,
265
- children: /*#__PURE__*/_jsxs(Text, {
266
- style: styles.asyncBadgeText,
267
- children: [relatedActions.length, " ACTIONS"]
268
- })
269
- })
270
- }), /*#__PURE__*/_jsxs(View, {
271
- style: styles.cardContent,
272
- children: [/*#__PURE__*/_jsx(Text, {
273
- style: styles.baseActionType,
274
- children: baseActionType
275
- }), totalDuration !== null && /*#__PURE__*/_jsxs(View, {
276
- style: styles.totalDurationRow,
277
- children: [/*#__PURE__*/_jsx(Text, {
278
- style: styles.totalDurationLabel,
279
- children: "Total Duration"
280
- }), /*#__PURE__*/_jsxs(Text, {
281
- style: styles.totalDurationValue,
282
- children: [totalDuration, "ms"]
283
- })]
284
- }), /*#__PURE__*/_jsx(View, {
285
- style: styles.timeline,
286
- children: relatedActions.map((relatedAction, index) => {
287
- const relatedCategoryInfo = getCategoryInfo(relatedAction.category);
288
- const isCurrent = relatedAction.id === action.id;
289
- return /*#__PURE__*/_jsxs(TouchableOpacity, {
290
- style: [styles.timelineItem, isCurrent && styles.timelineItemCurrent],
291
- onPress: () => onNavigateToAction?.(relatedAction),
292
- disabled: isCurrent || !onNavigateToAction,
293
- activeOpacity: 0.7,
294
- children: [index < relatedActions.length - 1 && /*#__PURE__*/_jsx(View, {
295
- style: styles.timelineConnector
296
- }), /*#__PURE__*/_jsx(View, {
297
- style: [styles.timelineDot, {
298
- backgroundColor: relatedCategoryInfo.color
299
- }]
300
- }), /*#__PURE__*/_jsxs(View, {
301
- style: styles.timelineContent,
302
- children: [/*#__PURE__*/_jsxs(View, {
303
- style: styles.timelineHeader,
304
- children: [/*#__PURE__*/_jsx(View, {
305
- style: [styles.timelineStatusBadge, {
306
- backgroundColor: relatedCategoryInfo.bgColor
307
- }],
308
- children: /*#__PURE__*/_jsx(Text, {
309
- style: [styles.timelineStatusText, {
310
- color: relatedCategoryInfo.color
311
- }],
312
- children: relatedCategoryInfo.label
313
- })
314
- }), isCurrent && /*#__PURE__*/_jsx(View, {
315
- style: styles.currentBadge,
316
- children: /*#__PURE__*/_jsx(Text, {
317
- style: styles.currentBadgeText,
318
- children: "CURRENT"
319
- })
320
- })]
321
- }), /*#__PURE__*/_jsx(Text, {
322
- style: styles.timelineTime,
323
- children: formatTime(relatedAction.timestamp)
324
- })]
325
- })]
326
- }, relatedAction.id);
327
- })
328
- })]
329
- })]
330
- }), hasPayload && /*#__PURE__*/_jsxs(View, {
331
- style: styles.card,
332
- children: [/*#__PURE__*/_jsx(SectionHeader, {
333
- icon: Box,
334
- title: "PAYLOAD",
335
- badge: /*#__PURE__*/_jsx(View, {
336
- style: styles.typeBadge,
337
- children: /*#__PURE__*/_jsx(Text, {
338
- style: styles.typeText,
339
- children: Array.isArray(action.payload) ? "ARRAY" : typeof action.payload === "object" ? "OBJECT" : typeof action.payload?.toString().toUpperCase()
340
- })
341
- })
342
- }), /*#__PURE__*/_jsx(View, {
343
- style: styles.dataViewerContainer,
344
- children: /*#__PURE__*/_jsx(DataViewer, {
345
- title: "",
346
- data: parseValue(action.payload),
347
- showTypeFilter: true,
348
- rawMode: true,
349
- initialExpanded: true
350
- })
351
- })]
352
- }), hasMeta && /*#__PURE__*/_jsxs(View, {
353
- style: styles.card,
354
- children: [/*#__PURE__*/_jsx(SectionHeader, {
355
- icon: Hash,
356
- title: "ASYNC METADATA",
357
- badge: /*#__PURE__*/_jsx(View, {
358
- style: [styles.categoryBadge, {
359
- backgroundColor: categoryInfo.bgColor
360
- }],
361
- children: /*#__PURE__*/_jsx(Text, {
362
- style: [styles.categoryText, {
363
- color: categoryInfo.color
364
- }],
365
- children: "RTK THUNK"
366
- })
367
- })
368
- }), /*#__PURE__*/_jsxs(View, {
369
- style: styles.cardContent,
370
- children: [action.meta?.requestId && /*#__PURE__*/_jsx(InfoRow, {
371
- label: "Request ID",
372
- value: action.meta.requestId,
373
- mono: true
374
- }), action.meta?.requestStatus && /*#__PURE__*/_jsx(InfoRow, {
375
- label: "Status",
376
- value: action.meta.requestStatus.toUpperCase(),
377
- valueColor: categoryInfo.color
378
- }), action.meta?.arg !== undefined && /*#__PURE__*/_jsxs(View, {
379
- style: styles.argSection,
380
- children: [/*#__PURE__*/_jsx(Text, {
381
- style: styles.argLabel,
382
- children: "Original Argument"
383
- }), /*#__PURE__*/_jsx(View, {
384
- style: styles.argValueContainer,
385
- children: typeof action.meta.arg === "object" ? /*#__PURE__*/_jsx(DataViewer, {
386
- title: "",
387
- data: parseValue(action.meta.arg),
388
- showTypeFilter: true,
389
- rawMode: true,
390
- initialExpanded: true
391
- }) : /*#__PURE__*/_jsx(Text, {
392
- style: styles.argValue,
393
- children: JSON.stringify(action.meta.arg)
394
- })
395
- })]
396
- }), action.meta?.rejectedWithValue && /*#__PURE__*/_jsx(InfoRow, {
397
- label: "Rejected With Value",
398
- value: "true",
399
- valueColor: buoyColors.error
400
- }), action.meta?.aborted && /*#__PURE__*/_jsx(InfoRow, {
401
- label: "Aborted",
402
- value: "true",
403
- valueColor: buoyColors.warning
404
- }), action.meta?.condition && /*#__PURE__*/_jsx(InfoRow, {
405
- label: "Condition",
406
- value: "true",
407
- valueColor: buoyColors.textMuted
408
- })]
409
- })]
410
- }), hasError && /*#__PURE__*/_jsxs(View, {
411
- style: [styles.card, styles.errorCard],
412
- children: [/*#__PURE__*/_jsx(SectionHeader, {
413
- icon: AlertCircle,
414
- title: "ERROR",
415
- badge: /*#__PURE__*/_jsx(View, {
416
- style: styles.errorBadge,
417
- children: /*#__PURE__*/_jsx(Text, {
418
- style: styles.errorBadgeText,
419
- children: "REJECTED"
420
- })
421
- })
422
- }), /*#__PURE__*/_jsx(View, {
423
- style: styles.dataViewerContainer,
424
- children: typeof action.error === "object" ? /*#__PURE__*/_jsx(DataViewer, {
425
- title: "",
426
- data: parseValue(action.error),
427
- showTypeFilter: true,
428
- rawMode: true,
429
- initialExpanded: true
430
- }) : /*#__PURE__*/_jsx(Text, {
431
- style: styles.errorText,
432
- children: String(action.error)
433
- })
434
- })]
435
- }), /*#__PURE__*/_jsxs(View, {
436
- style: styles.card,
437
- children: [/*#__PURE__*/_jsx(SectionHeader, {
438
- icon: FileText,
439
- title: "FULL ACTION OBJECT"
440
- }), /*#__PURE__*/_jsx(View, {
441
- style: styles.dataViewerContainer,
442
- children: /*#__PURE__*/_jsx(DataViewer, {
443
- title: "",
444
- data: parseValue(action.action),
445
- showTypeFilter: true,
446
- rawMode: true,
447
- initialExpanded: true
448
- })
449
- })]
450
- }), /*#__PURE__*/_jsx(View, {
451
- style: styles.actionFooter,
452
- children: /*#__PURE__*/_jsxs(View, {
453
- style: styles.actionsGrid,
454
- children: [/*#__PURE__*/_jsxs(View, {
455
- style: styles.actionButtonWrapper,
456
- children: [/*#__PURE__*/_jsx(ReduxActionButton, {
457
- type: "replay",
458
- text: "REPLAY",
459
- onPress: handleReplay
460
- }), /*#__PURE__*/_jsx(Text, {
461
- style: styles.actionDescription,
462
- children: "Dispatch again"
463
- })]
464
- }), /*#__PURE__*/_jsxs(View, {
465
- style: styles.actionButtonWrapper,
466
- children: [/*#__PURE__*/_jsx(ReduxActionButton, {
467
- type: "jump",
468
- text: "JUMP",
469
- onPress: handleJump
470
- }), /*#__PURE__*/_jsx(Text, {
471
- style: styles.actionDescription,
472
- children: "Restore this state"
473
- })]
474
- }), /*#__PURE__*/_jsxs(View, {
475
- style: styles.actionButtonWrapper,
476
- children: [/*#__PURE__*/_jsx(ReduxActionButton, {
477
- type: "copy",
478
- text: "COPY ACTION",
479
- onPress: handleCopyAction
480
- }), /*#__PURE__*/_jsx(Text, {
481
- style: styles.actionDescription,
482
- children: isPro ? "Copy to clipboard" : "Pro feature"
483
- })]
484
- }), hasPayload && /*#__PURE__*/_jsxs(View, {
485
- style: styles.actionButtonWrapper,
486
- children: [/*#__PURE__*/_jsx(ReduxActionButton, {
487
- type: "copy",
488
- text: "COPY PAYLOAD",
489
- onPress: handleCopyPayload
490
- }), /*#__PURE__*/_jsx(Text, {
491
- style: styles.actionDescription,
492
- children: isPro ? "Copy payload only" : "Pro feature"
493
- })]
494
- })]
495
- })
496
- }), /*#__PURE__*/_jsx(ProUpgradeModal, {
497
- visible: showProModal,
498
- onClose: () => setShowProModal(false),
499
- featureName: "Copy"
500
- })]
501
- });
502
- });
503
- const styles = StyleSheet.create({
504
- container: {
505
- flex: 1
506
- },
507
- contentContainer: {
508
- padding: 8,
509
- paddingBottom: 100,
510
- gap: 16
511
- },
512
- // Card styling - matches React Query DevTools
513
- card: {
514
- backgroundColor: buoyColors.card,
515
- borderRadius: 6,
516
- borderWidth: 1,
517
- borderColor: buoyColors.primary + "4D",
518
- overflow: "hidden",
519
- shadowColor: buoyColors.primary,
520
- shadowOffset: {
521
- width: 0,
522
- height: 0
523
- },
524
- shadowOpacity: 0.1,
525
- shadowRadius: 6
526
- },
527
- errorCard: {
528
- borderColor: buoyColors.error + "4D",
529
- shadowColor: buoyColors.error
530
- },
531
- // Section header - green tinted like React Query
532
- sectionHeader: {
533
- flexDirection: "row",
534
- alignItems: "center",
535
- justifyContent: "space-between",
536
- paddingHorizontal: 12,
537
- paddingVertical: 10,
538
- borderBottomWidth: 1,
539
- borderBottomColor: buoyColors.primary + "33",
540
- backgroundColor: buoyColors.primary + "15"
541
- },
542
- sectionHeaderLeft: {
543
- flexDirection: "row",
544
- alignItems: "center",
545
- gap: 6
546
- },
547
- sectionTitle: {
548
- fontSize: 12,
549
- fontWeight: "600",
550
- letterSpacing: 0.5,
551
- color: buoyColors.primary,
552
- fontFamily: "monospace"
553
- },
554
- cardContent: {
555
- padding: 14,
556
- gap: 10
557
- },
558
- infoRow: {
559
- flexDirection: "row",
560
- alignItems: "center",
561
- justifyContent: "space-between"
562
- },
563
- infoLabel: {
564
- fontSize: 11,
565
- color: buoyColors.textMuted,
566
- fontWeight: "500"
567
- },
568
- infoValue: {
569
- fontSize: 11,
570
- color: buoyColors.text,
571
- fontWeight: "500",
572
- flex: 1,
573
- textAlign: "right",
574
- marginLeft: 12
575
- },
576
- infoValueMono: {
577
- fontFamily: "monospace"
578
- },
579
- badgeRow: {
580
- flexDirection: "row",
581
- flexWrap: "wrap",
582
- gap: 8,
583
- marginTop: 6
584
- },
585
- categoryBadge: {
586
- paddingHorizontal: 8,
587
- paddingVertical: 3,
588
- borderRadius: 4
589
- },
590
- categoryText: {
591
- fontSize: 9,
592
- fontWeight: "700",
593
- letterSpacing: 0.3
594
- },
595
- durationBadge: {
596
- flexDirection: "row",
597
- alignItems: "center",
598
- gap: 4,
599
- paddingHorizontal: 8,
600
- paddingVertical: 3,
601
- borderRadius: 4,
602
- backgroundColor: buoyColors.input
603
- },
604
- durationBadgeSlow: {
605
- backgroundColor: buoyColors.error + "26"
606
- },
607
- durationText: {
608
- fontSize: 9,
609
- fontWeight: "600",
610
- color: buoyColors.textSecondary,
611
- fontFamily: "monospace"
612
- },
613
- durationTextSlow: {
614
- color: buoyColors.error
615
- },
616
- changesBadge: {
617
- flexDirection: "row",
618
- alignItems: "center",
619
- gap: 4,
620
- paddingHorizontal: 8,
621
- paddingVertical: 3,
622
- borderRadius: 4,
623
- backgroundColor: buoyColors.success + "26"
624
- },
625
- changesText: {
626
- fontSize: 9,
627
- fontWeight: "600",
628
- color: buoyColors.success
629
- },
630
- noChangesBadge: {
631
- paddingHorizontal: 8,
632
- paddingVertical: 3,
633
- borderRadius: 4,
634
- backgroundColor: buoyColors.input
635
- },
636
- noChangesText: {
637
- fontSize: 9,
638
- fontWeight: "600",
639
- color: buoyColors.textMuted
640
- },
641
- typeBadge: {
642
- paddingHorizontal: 6,
643
- paddingVertical: 2,
644
- borderRadius: 3,
645
- backgroundColor: buoyColors.input
646
- },
647
- typeText: {
648
- fontSize: 8,
649
- fontWeight: "600",
650
- color: buoyColors.textMuted,
651
- fontFamily: "monospace"
652
- },
653
- dataViewerContainer: {
654
- backgroundColor: buoyColors.base,
655
- minHeight: 60
656
- },
657
- argSection: {
658
- marginTop: 4
659
- },
660
- argLabel: {
661
- fontSize: 11,
662
- color: buoyColors.textMuted,
663
- fontWeight: "500",
664
- marginBottom: 6
665
- },
666
- argValueContainer: {
667
- backgroundColor: buoyColors.base,
668
- borderRadius: 6,
669
- borderWidth: 1,
670
- borderColor: buoyColors.border,
671
- overflow: "hidden"
672
- },
673
- argValue: {
674
- fontSize: 11,
675
- color: buoyColors.text,
676
- fontFamily: "monospace",
677
- padding: 10
678
- },
679
- errorBadge: {
680
- paddingHorizontal: 8,
681
- paddingVertical: 3,
682
- borderRadius: 4,
683
- backgroundColor: buoyColors.error + "26"
684
- },
685
- errorBadgeText: {
686
- fontSize: 9,
687
- fontWeight: "700",
688
- color: buoyColors.error,
689
- letterSpacing: 0.3
690
- },
691
- errorText: {
692
- fontSize: 12,
693
- color: buoyColors.error,
694
- fontFamily: "monospace",
695
- padding: 14
696
- },
697
- // Async Operation / Related Actions styles
698
- asyncBadge: {
699
- paddingHorizontal: 8,
700
- paddingVertical: 3,
701
- borderRadius: 4,
702
- backgroundColor: buoyColors.primary + "26"
703
- },
704
- asyncBadgeText: {
705
- fontSize: 9,
706
- fontWeight: "700",
707
- color: buoyColors.primary,
708
- letterSpacing: 0.3
709
- },
710
- baseActionType: {
711
- fontSize: 12,
712
- fontWeight: "600",
713
- color: buoyColors.text,
714
- fontFamily: "monospace",
715
- marginBottom: 8
716
- },
717
- totalDurationRow: {
718
- flexDirection: "row",
719
- justifyContent: "space-between",
720
- alignItems: "center",
721
- marginBottom: 12,
722
- paddingBottom: 12,
723
- borderBottomWidth: 1,
724
- borderBottomColor: buoyColors.border
725
- },
726
- totalDurationLabel: {
727
- fontSize: 11,
728
- color: buoyColors.textMuted,
729
- fontWeight: "500"
730
- },
731
- totalDurationValue: {
732
- fontSize: 14,
733
- fontWeight: "700",
734
- color: buoyColors.success,
735
- fontFamily: "monospace"
736
- },
737
- timeline: {
738
- gap: 0
739
- },
740
- timelineItem: {
741
- flexDirection: "row",
742
- alignItems: "flex-start",
743
- paddingVertical: 8,
744
- paddingHorizontal: 8,
745
- borderRadius: 8,
746
- position: "relative"
747
- },
748
- timelineItemCurrent: {
749
- backgroundColor: buoyColors.primary + "15"
750
- },
751
- timelineConnector: {
752
- position: "absolute",
753
- left: 13,
754
- top: 24,
755
- bottom: -8,
756
- width: 2,
757
- backgroundColor: buoyColors.border
758
- },
759
- timelineDot: {
760
- width: 12,
761
- height: 12,
762
- borderRadius: 6,
763
- marginRight: 10,
764
- marginTop: 2
765
- },
766
- timelineContent: {
767
- flex: 1
768
- },
769
- timelineHeader: {
770
- flexDirection: "row",
771
- alignItems: "center",
772
- gap: 8,
773
- marginBottom: 2
774
- },
775
- timelineStatusBadge: {
776
- paddingHorizontal: 6,
777
- paddingVertical: 2,
778
- borderRadius: 4
779
- },
780
- timelineStatusText: {
781
- fontSize: 9,
782
- fontWeight: "700",
783
- letterSpacing: 0.3
784
- },
785
- currentBadge: {
786
- paddingHorizontal: 6,
787
- paddingVertical: 2,
788
- borderRadius: 4,
789
- backgroundColor: buoyColors.primary
790
- },
791
- currentBadgeText: {
792
- fontSize: 8,
793
- fontWeight: "700",
794
- color: "#fff",
795
- letterSpacing: 0.3
796
- },
797
- timelineTime: {
798
- fontSize: 10,
799
- color: buoyColors.textMuted,
800
- fontFamily: "monospace"
801
- },
802
- // Action footer - matches React Query DevTools
803
- actionFooter: {
804
- backgroundColor: buoyColors.card,
805
- borderRadius: 6,
806
- borderWidth: 1,
807
- borderColor: buoyColors.primary + "4D",
808
- paddingVertical: 12,
809
- paddingHorizontal: 12,
810
- shadowColor: buoyColors.primary,
811
- shadowOffset: {
812
- width: 0,
813
- height: 0
814
- },
815
- shadowOpacity: 0.1,
816
- shadowRadius: 6
817
- },
818
- actionsGrid: {
819
- flexDirection: "row",
820
- flexWrap: "wrap",
821
- gap: 12,
822
- justifyContent: "flex-start"
823
- },
824
- actionButtonWrapper: {
825
- alignItems: "center",
826
- gap: 4
827
- },
828
- actionDescription: {
829
- fontSize: 9,
830
- color: buoyColors.textMuted,
831
- textAlign: "center"
832
- }
833
- });
1
+ "use strict";import React,{memo,useMemo,useCallback,useState,useEffect}from"react";import{View,Text,StyleSheet,ScrollView,TouchableOpacity}from"react-native";import{buoyColors,Clock,AlertTriangle,Zap,Hash,Info,Box,AlertCircle,FileText,parseValue,ProUpgradeModal,copyToClipboard}from"@buoy-gg/shared-ui";import{useIsPro}from"@buoy-gg/license";import{DataViewer}from"@buoy-gg/shared-ui/dataViewer";import{reduxActionStore}from"../utils/reduxActionStore";import{jumpToState,replayAction}from"../utils/buoyReduxMiddleware";import{ReduxActionButton}from"./ReduxActionButton";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";function getCategoryInfo(e){switch(e){case"pending":return{label:"PENDING",color:buoyColors.warning,bgColor:buoyColors.warning+"26"};case"fulfilled":return{label:"FULFILLED",color:buoyColors.success,bgColor:buoyColors.success+"26"};case"rejected":return{label:"REJECTED",color:buoyColors.error,bgColor:buoyColors.error+"26"};case"internal":return{label:"INTERNAL",color:buoyColors.textMuted,bgColor:buoyColors.textMuted+"26"};case"query":return{label:"QUERY",color:buoyColors.info,bgColor:buoyColors.info+"26"};case"mutation":return{label:"MUTATION",color:buoyColors.info,bgColor:buoyColors.info+"26"};default:return{label:"ACTION",color:buoyColors.info,bgColor:buoyColors.info+"26"}}}function formatDuration(e){return void 0===e?"N/A":e<1?"<1ms":`${e.toFixed(1)}ms`}function SectionHeader({icon:e,title:o,badge:t}){return _jsxs(View,{style:styles.sectionHeader,children:[_jsxs(View,{style:styles.sectionHeaderLeft,children:[_jsx(e,{size:14,color:buoyColors.primary}),_jsx(Text,{style:styles.sectionTitle,children:o})]}),t]})}function InfoRow({label:e,value:o,valueColor:t,mono:r=!1}){return _jsxs(View,{style:styles.infoRow,children:[_jsx(Text,{style:styles.infoLabel,children:e}),_jsx(Text,{style:[styles.infoValue,r&&styles.infoValueMono,t&&{color:t}],numberOfLines:1,ellipsizeMode:"middle",children:o})]})}function formatTime(e){const o=new Date(e);return`${o.getHours().toString().padStart(2,"0")}:${o.getMinutes().toString().padStart(2,"0")}:${o.getSeconds().toString().padStart(2,"0")}.${o.getMilliseconds().toString().padStart(3,"0")}`}export const ReduxActionInfoView=memo(function({action:e,onNavigateToAction:o}){const t=useIsPro(),[r,l]=useState(!1);useEffect(()=>{r&&t&&l(!1)},[r,t]);const i=getCategoryInfo(e.category),s=void 0!==e.payload,a=e.meta&&Object.keys(e.meta).length>0,n=void 0!==e.error,d=useMemo(()=>reduxActionStore.getLinkedActions(e),[e]),c=d.length>1,y=c?reduxActionStore.getBaseActionType(e.type):null,u=e.meta?.requestId?reduxActionStore.getAsyncOperationDuration(e.meta.requestId):null,g=useCallback(async()=>{t?await copyToClipboard(e.action):l(!0)},[e,t]),x=useCallback(async()=>{t?await copyToClipboard(e.payload):l(!0)},[e.payload,t]),p=useCallback(()=>{e.action&&"object"==typeof e.action&&"type"in e.action&&replayAction(e.action)},[e]),b=useCallback(()=>{void 0!==e.nextState&&jumpToState(e.nextState)},[e]);return _jsxs(ScrollView,{style:styles.container,contentContainerStyle:styles.contentContainer,showsVerticalScrollIndicator:!1,children:[_jsxs(View,{style:styles.card,children:[_jsx(SectionHeader,{icon:Info,title:"ACTION INFO"}),_jsxs(View,{style:styles.cardContent,children:[_jsx(InfoRow,{label:"Type",value:e.type,mono:!0}),e.sliceName&&_jsx(InfoRow,{label:"Slice",value:e.sliceName,mono:!0}),_jsx(InfoRow,{label:"Action",value:e.actionName,mono:!0}),_jsxs(View,{style:styles.badgeRow,children:[_jsx(View,{style:[styles.categoryBadge,{backgroundColor:i.bgColor}],children:_jsx(Text,{style:[styles.categoryText,{color:i.color}],children:i.label})}),_jsxs(View,{style:[styles.durationBadge,e.isSlowAction&&styles.durationBadgeSlow],children:[_jsx(Clock,{size:10,color:e.isSlowAction?buoyColors.error:buoyColors.textSecondary}),_jsx(Text,{style:[styles.durationText,e.isSlowAction&&styles.durationTextSlow],children:formatDuration(e.duration)}),e.isSlowAction&&_jsx(AlertTriangle,{size:10,color:buoyColors.error})]}),e.hasStateChange?_jsxs(View,{style:styles.changesBadge,children:[_jsx(Zap,{size:10,color:buoyColors.success}),_jsx(Text,{style:styles.changesText,children:e.diffSummary||"changed"})]}):_jsx(View,{style:styles.noChangesBadge,children:_jsx(Text,{style:styles.noChangesText,children:"no change"})})]})]})]}),c&&_jsxs(View,{style:styles.card,children:[_jsx(SectionHeader,{icon:Hash,title:"ASYNC FLOW",badge:_jsx(View,{style:styles.asyncBadge,children:_jsxs(Text,{style:styles.asyncBadgeText,children:[d.length," ACTIONS"]})})}),_jsxs(View,{style:styles.cardContent,children:[_jsx(Text,{style:styles.baseActionType,children:y}),null!==u&&_jsxs(View,{style:styles.totalDurationRow,children:[_jsx(Text,{style:styles.totalDurationLabel,children:"Total Duration"}),_jsxs(Text,{style:styles.totalDurationValue,children:[u,"ms"]})]}),_jsx(View,{style:styles.timeline,children:d.map((t,r)=>{const l=getCategoryInfo(t.category),i=t.id===e.id;return _jsxs(TouchableOpacity,{style:[styles.timelineItem,i&&styles.timelineItemCurrent],onPress:()=>o?.(t),disabled:i||!o,activeOpacity:.7,children:[r<d.length-1&&_jsx(View,{style:styles.timelineConnector}),_jsx(View,{style:[styles.timelineDot,{backgroundColor:l.color}]}),_jsxs(View,{style:styles.timelineContent,children:[_jsxs(View,{style:styles.timelineHeader,children:[_jsx(View,{style:[styles.timelineStatusBadge,{backgroundColor:l.bgColor}],children:_jsx(Text,{style:[styles.timelineStatusText,{color:l.color}],children:l.label})}),i&&_jsx(View,{style:styles.currentBadge,children:_jsx(Text,{style:styles.currentBadgeText,children:"CURRENT"})})]}),_jsx(Text,{style:styles.timelineTime,children:formatTime(t.timestamp)})]})]},t.id)})})]})]}),s&&_jsxs(View,{style:styles.card,children:[_jsx(SectionHeader,{icon:Box,title:"PAYLOAD",badge:_jsx(View,{style:styles.typeBadge,children:_jsx(Text,{style:styles.typeText,children:Array.isArray(e.payload)?"ARRAY":"object"==typeof e.payload?"OBJECT":typeof e.payload?.toString().toUpperCase()})})}),_jsx(View,{style:styles.dataViewerContainer,children:_jsx(DataViewer,{title:"",data:parseValue(e.payload),showTypeFilter:!0,rawMode:!0,initialExpanded:!0})})]}),a&&_jsxs(View,{style:styles.card,children:[_jsx(SectionHeader,{icon:Hash,title:"ASYNC METADATA",badge:_jsx(View,{style:[styles.categoryBadge,{backgroundColor:i.bgColor}],children:_jsx(Text,{style:[styles.categoryText,{color:i.color}],children:"RTK THUNK"})})}),_jsxs(View,{style:styles.cardContent,children:[e.meta?.requestId&&_jsx(InfoRow,{label:"Request ID",value:e.meta.requestId,mono:!0}),e.meta?.requestStatus&&_jsx(InfoRow,{label:"Status",value:e.meta.requestStatus.toUpperCase(),valueColor:i.color}),void 0!==e.meta?.arg&&_jsxs(View,{style:styles.argSection,children:[_jsx(Text,{style:styles.argLabel,children:"Original Argument"}),_jsx(View,{style:styles.argValueContainer,children:"object"==typeof e.meta.arg?_jsx(DataViewer,{title:"",data:parseValue(e.meta.arg),showTypeFilter:!0,rawMode:!0,initialExpanded:!0}):_jsx(Text,{style:styles.argValue,children:JSON.stringify(e.meta.arg)})})]}),e.meta?.rejectedWithValue&&_jsx(InfoRow,{label:"Rejected With Value",value:"true",valueColor:buoyColors.error}),e.meta?.aborted&&_jsx(InfoRow,{label:"Aborted",value:"true",valueColor:buoyColors.warning}),e.meta?.condition&&_jsx(InfoRow,{label:"Condition",value:"true",valueColor:buoyColors.textMuted})]})]}),n&&_jsxs(View,{style:[styles.card,styles.errorCard],children:[_jsx(SectionHeader,{icon:AlertCircle,title:"ERROR",badge:_jsx(View,{style:styles.errorBadge,children:_jsx(Text,{style:styles.errorBadgeText,children:"REJECTED"})})}),_jsx(View,{style:styles.dataViewerContainer,children:"object"==typeof e.error?_jsx(DataViewer,{title:"",data:parseValue(e.error),showTypeFilter:!0,rawMode:!0,initialExpanded:!0}):_jsx(Text,{style:styles.errorText,children:String(e.error)})})]}),_jsxs(View,{style:styles.card,children:[_jsx(SectionHeader,{icon:FileText,title:"FULL ACTION OBJECT"}),_jsx(View,{style:styles.dataViewerContainer,children:_jsx(DataViewer,{title:"",data:parseValue(e.action),showTypeFilter:!0,rawMode:!0,initialExpanded:!0})})]}),_jsx(View,{style:styles.actionFooter,children:_jsxs(View,{style:styles.actionsGrid,children:[_jsxs(View,{style:styles.actionButtonWrapper,children:[_jsx(ReduxActionButton,{type:"replay",text:"REPLAY",onPress:p}),_jsx(Text,{style:styles.actionDescription,children:"Dispatch again"})]}),_jsxs(View,{style:styles.actionButtonWrapper,children:[_jsx(ReduxActionButton,{type:"jump",text:"JUMP",onPress:b}),_jsx(Text,{style:styles.actionDescription,children:"Restore this state"})]}),_jsxs(View,{style:styles.actionButtonWrapper,children:[_jsx(ReduxActionButton,{type:"copy",text:"COPY ACTION",onPress:g}),_jsx(Text,{style:styles.actionDescription,children:t?"Copy to clipboard":"Pro feature"})]}),s&&_jsxs(View,{style:styles.actionButtonWrapper,children:[_jsx(ReduxActionButton,{type:"copy",text:"COPY PAYLOAD",onPress:x}),_jsx(Text,{style:styles.actionDescription,children:t?"Copy payload only":"Pro feature"})]})]})}),_jsx(ProUpgradeModal,{visible:r,onClose:()=>l(!1),featureName:"Copy"})]})});const styles=StyleSheet.create({container:{flex:1},contentContainer:{padding:8,paddingBottom:100,gap:16},card:{backgroundColor:buoyColors.card,borderRadius:6,borderWidth:1,borderColor:buoyColors.primary+"4D",overflow:"hidden",shadowColor:buoyColors.primary,shadowOffset:{width:0,height:0},shadowOpacity:.1,shadowRadius:6},errorCard:{borderColor:buoyColors.error+"4D",shadowColor:buoyColors.error},sectionHeader:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",paddingHorizontal:12,paddingVertical:10,borderBottomWidth:1,borderBottomColor:buoyColors.primary+"33",backgroundColor:buoyColors.primary+"15"},sectionHeaderLeft:{flexDirection:"row",alignItems:"center",gap:6},sectionTitle:{fontSize:12,fontWeight:"600",letterSpacing:.5,color:buoyColors.primary,fontFamily:"monospace"},cardContent:{padding:14,gap:10},infoRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-between"},infoLabel:{fontSize:11,color:buoyColors.textMuted,fontWeight:"500"},infoValue:{fontSize:11,color:buoyColors.text,fontWeight:"500",flex:1,textAlign:"right",marginLeft:12},infoValueMono:{fontFamily:"monospace"},badgeRow:{flexDirection:"row",flexWrap:"wrap",gap:8,marginTop:6},categoryBadge:{paddingHorizontal:8,paddingVertical:3,borderRadius:4},categoryText:{fontSize:9,fontWeight:"700",letterSpacing:.3},durationBadge:{flexDirection:"row",alignItems:"center",gap:4,paddingHorizontal:8,paddingVertical:3,borderRadius:4,backgroundColor:buoyColors.input},durationBadgeSlow:{backgroundColor:buoyColors.error+"26"},durationText:{fontSize:9,fontWeight:"600",color:buoyColors.textSecondary,fontFamily:"monospace"},durationTextSlow:{color:buoyColors.error},changesBadge:{flexDirection:"row",alignItems:"center",gap:4,paddingHorizontal:8,paddingVertical:3,borderRadius:4,backgroundColor:buoyColors.success+"26"},changesText:{fontSize:9,fontWeight:"600",color:buoyColors.success},noChangesBadge:{paddingHorizontal:8,paddingVertical:3,borderRadius:4,backgroundColor:buoyColors.input},noChangesText:{fontSize:9,fontWeight:"600",color:buoyColors.textMuted},typeBadge:{paddingHorizontal:6,paddingVertical:2,borderRadius:3,backgroundColor:buoyColors.input},typeText:{fontSize:8,fontWeight:"600",color:buoyColors.textMuted,fontFamily:"monospace"},dataViewerContainer:{backgroundColor:buoyColors.base,minHeight:60},argSection:{marginTop:4},argLabel:{fontSize:11,color:buoyColors.textMuted,fontWeight:"500",marginBottom:6},argValueContainer:{backgroundColor:buoyColors.base,borderRadius:6,borderWidth:1,borderColor:buoyColors.border,overflow:"hidden"},argValue:{fontSize:11,color:buoyColors.text,fontFamily:"monospace",padding:10},errorBadge:{paddingHorizontal:8,paddingVertical:3,borderRadius:4,backgroundColor:buoyColors.error+"26"},errorBadgeText:{fontSize:9,fontWeight:"700",color:buoyColors.error,letterSpacing:.3},errorText:{fontSize:12,color:buoyColors.error,fontFamily:"monospace",padding:14},asyncBadge:{paddingHorizontal:8,paddingVertical:3,borderRadius:4,backgroundColor:buoyColors.primary+"26"},asyncBadgeText:{fontSize:9,fontWeight:"700",color:buoyColors.primary,letterSpacing:.3},baseActionType:{fontSize:12,fontWeight:"600",color:buoyColors.text,fontFamily:"monospace",marginBottom:8},totalDurationRow:{flexDirection:"row",justifyContent:"space-between",alignItems:"center",marginBottom:12,paddingBottom:12,borderBottomWidth:1,borderBottomColor:buoyColors.border},totalDurationLabel:{fontSize:11,color:buoyColors.textMuted,fontWeight:"500"},totalDurationValue:{fontSize:14,fontWeight:"700",color:buoyColors.success,fontFamily:"monospace"},timeline:{gap:0},timelineItem:{flexDirection:"row",alignItems:"flex-start",paddingVertical:8,paddingHorizontal:8,borderRadius:8,position:"relative"},timelineItemCurrent:{backgroundColor:buoyColors.primary+"15"},timelineConnector:{position:"absolute",left:13,top:24,bottom:-8,width:2,backgroundColor:buoyColors.border},timelineDot:{width:12,height:12,borderRadius:6,marginRight:10,marginTop:2},timelineContent:{flex:1},timelineHeader:{flexDirection:"row",alignItems:"center",gap:8,marginBottom:2},timelineStatusBadge:{paddingHorizontal:6,paddingVertical:2,borderRadius:4},timelineStatusText:{fontSize:9,fontWeight:"700",letterSpacing:.3},currentBadge:{paddingHorizontal:6,paddingVertical:2,borderRadius:4,backgroundColor:buoyColors.primary},currentBadgeText:{fontSize:8,fontWeight:"700",color:"#fff",letterSpacing:.3},timelineTime:{fontSize:10,color:buoyColors.textMuted,fontFamily:"monospace"},actionFooter:{backgroundColor:buoyColors.card,borderRadius:6,borderWidth:1,borderColor:buoyColors.primary+"4D",paddingVertical:12,paddingHorizontal:12,shadowColor:buoyColors.primary,shadowOffset:{width:0,height:0},shadowOpacity:.1,shadowRadius:6},actionsGrid:{flexDirection:"row",flexWrap:"wrap",gap:12,justifyContent:"flex-start"},actionButtonWrapper:{alignItems:"center",gap:4},actionDescription:{fontSize:9,color:buoyColors.textMuted,textAlign:"center"}});