@buoy-gg/highlight-updates 2.1.12 → 2.1.14

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 (64) hide show
  1. package/lib/commonjs/highlight-updates/HighlightUpdatesOverlay.js +1 -285
  2. package/lib/commonjs/highlight-updates/components/HighlightFilterView.js +1 -1371
  3. package/lib/commonjs/highlight-updates/components/HighlightUpdatesModal.js +1 -591
  4. package/lib/commonjs/highlight-updates/components/IdentifierBadge.js +1 -267
  5. package/lib/commonjs/highlight-updates/components/IsolatedRenderList.js +1 -178
  6. package/lib/commonjs/highlight-updates/components/ModalHeaderContent.js +1 -303
  7. package/lib/commonjs/highlight-updates/components/RenderCauseBadge.js +1 -500
  8. package/lib/commonjs/highlight-updates/components/RenderDetailView.js +1 -830
  9. package/lib/commonjs/highlight-updates/components/RenderHistoryViewer.js +1 -894
  10. package/lib/commonjs/highlight-updates/components/RenderListItem.js +1 -220
  11. package/lib/commonjs/highlight-updates/components/StatsDisplay.js +1 -70
  12. package/lib/commonjs/highlight-updates/components/index.js +1 -97
  13. package/lib/commonjs/highlight-updates/utils/HighlightUpdatesController.js +1 -1435
  14. package/lib/commonjs/highlight-updates/utils/PerformanceLogger.js +1 -359
  15. package/lib/commonjs/highlight-updates/utils/ProfilerInterceptor.js +1 -371
  16. package/lib/commonjs/highlight-updates/utils/RenderCauseDetector.js +1 -1828
  17. package/lib/commonjs/highlight-updates/utils/RenderTracker.js +1 -903
  18. package/lib/commonjs/highlight-updates/utils/ViewTypeMapper.js +1 -264
  19. package/lib/commonjs/highlight-updates/utils/renderExportFormatter.js +1 -58
  20. package/lib/commonjs/index.js +1 -311
  21. package/lib/commonjs/preset.js +1 -278
  22. package/lib/module/highlight-updates/HighlightUpdatesOverlay.js +1 -278
  23. package/lib/module/highlight-updates/components/HighlightFilterView.js +1 -1365
  24. package/lib/module/highlight-updates/components/HighlightUpdatesModal.js +1 -585
  25. package/lib/module/highlight-updates/components/IdentifierBadge.js +1 -259
  26. package/lib/module/highlight-updates/components/IsolatedRenderList.js +1 -174
  27. package/lib/module/highlight-updates/components/ModalHeaderContent.js +1 -298
  28. package/lib/module/highlight-updates/components/RenderCauseBadge.js +1 -491
  29. package/lib/module/highlight-updates/components/RenderDetailView.js +1 -826
  30. package/lib/module/highlight-updates/components/RenderHistoryViewer.js +1 -888
  31. package/lib/module/highlight-updates/components/RenderListItem.js +1 -215
  32. package/lib/module/highlight-updates/components/StatsDisplay.js +1 -67
  33. package/lib/module/highlight-updates/components/index.js +1 -16
  34. package/lib/module/highlight-updates/utils/HighlightUpdatesController.js +1 -1431
  35. package/lib/module/highlight-updates/utils/PerformanceLogger.js +1 -353
  36. package/lib/module/highlight-updates/utils/ProfilerInterceptor.js +1 -358
  37. package/lib/module/highlight-updates/utils/RenderCauseDetector.js +1 -1818
  38. package/lib/module/highlight-updates/utils/RenderTracker.js +1 -900
  39. package/lib/module/highlight-updates/utils/ViewTypeMapper.js +1 -255
  40. package/lib/module/highlight-updates/utils/renderExportFormatter.js +1 -54
  41. package/lib/module/index.js +1 -71
  42. package/lib/module/preset.js +1 -272
  43. package/package.json +7 -7
  44. package/lib/typescript/highlight-updates/HighlightUpdatesOverlay.d.ts.map +0 -1
  45. package/lib/typescript/highlight-updates/components/HighlightFilterView.d.ts.map +0 -1
  46. package/lib/typescript/highlight-updates/components/HighlightUpdatesModal.d.ts.map +0 -1
  47. package/lib/typescript/highlight-updates/components/IdentifierBadge.d.ts.map +0 -1
  48. package/lib/typescript/highlight-updates/components/IsolatedRenderList.d.ts.map +0 -1
  49. package/lib/typescript/highlight-updates/components/ModalHeaderContent.d.ts.map +0 -1
  50. package/lib/typescript/highlight-updates/components/RenderCauseBadge.d.ts.map +0 -1
  51. package/lib/typescript/highlight-updates/components/RenderDetailView.d.ts.map +0 -1
  52. package/lib/typescript/highlight-updates/components/RenderHistoryViewer.d.ts.map +0 -1
  53. package/lib/typescript/highlight-updates/components/RenderListItem.d.ts.map +0 -1
  54. package/lib/typescript/highlight-updates/components/StatsDisplay.d.ts.map +0 -1
  55. package/lib/typescript/highlight-updates/components/index.d.ts.map +0 -1
  56. package/lib/typescript/highlight-updates/utils/HighlightUpdatesController.d.ts.map +0 -1
  57. package/lib/typescript/highlight-updates/utils/PerformanceLogger.d.ts.map +0 -1
  58. package/lib/typescript/highlight-updates/utils/ProfilerInterceptor.d.ts.map +0 -1
  59. package/lib/typescript/highlight-updates/utils/RenderCauseDetector.d.ts.map +0 -1
  60. package/lib/typescript/highlight-updates/utils/RenderTracker.d.ts.map +0 -1
  61. package/lib/typescript/highlight-updates/utils/ViewTypeMapper.d.ts.map +0 -1
  62. package/lib/typescript/highlight-updates/utils/renderExportFormatter.d.ts.map +0 -1
  63. package/lib/typescript/index.d.ts.map +0 -1
  64. package/lib/typescript/preset.d.ts.map +0 -1
@@ -1,888 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * RenderHistoryViewer
5
- *
6
- * Displays render history for a component with event stepping.
7
- * Allows navigating through render events chronologically.
8
- * Shows current state view or diff view between renders.
9
- */
10
-
11
- import React, { useState, useCallback, useMemo } from "react";
12
- import { View, Text, TouchableOpacity, ScrollView, StyleSheet } from "react-native";
13
- import { Clock, GitBranch, Database, Lock, formatRelativeTime, SectionHeader, EventStepperFooter, buoyColors } from "@buoy-gg/shared-ui";
14
-
15
- // Free tier limit for render history events
16
- const FREE_TIER_EVENT_LIMIT = 3;
17
- import { TreeDiffViewer } from "@buoy-gg/shared-ui/dataViewer";
18
- import { EnhancedCauseDisplay, CAUSE_CONFIG } from "./RenderCauseBadge";
19
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
20
- /**
21
- * Format timestamp with milliseconds
22
- */
23
- function formatTimeWithMs(timestamp) {
24
- const date = new Date(timestamp);
25
- return date.toLocaleTimeString([], {
26
- hour: "2-digit",
27
- minute: "2-digit",
28
- second: "2-digit"
29
- }) + `.${date.getMilliseconds().toString().padStart(3, "0")}`;
30
- }
31
-
32
- /**
33
- * Main RenderHistoryViewer component
34
- */
35
- export function RenderHistoryViewer({
36
- render,
37
- disableInternalFooter = false,
38
- selectedEventIndex: externalIndex,
39
- onEventIndexChange: externalOnChange,
40
- isPro = false
41
- }) {
42
- // Internal state for event index when not controlled externally
43
- const [internalIndex, setInternalIndex] = useState(0);
44
-
45
- // Use external or internal state
46
- const selectedEventIndex = externalIndex ?? internalIndex;
47
- const onEventIndexChange = externalOnChange ?? setInternalIndex;
48
-
49
- // View mode: "current" shows selected event, "diff" shows comparison
50
- const [activeView, setActiveView] = useState("current");
51
-
52
- // Get all events sorted by timestamp (oldest first)
53
- const allEvents = useMemo(() => {
54
- if (!render.renderHistory || render.renderHistory.length === 0) {
55
- return [];
56
- }
57
- return [...render.renderHistory].sort((a, b) => a.timestamp - b.timestamp);
58
- }, [render.renderHistory]);
59
-
60
- // Limit visible events for free tier (show most recent N events)
61
- const events = useMemo(() => {
62
- if (isPro) return allEvents;
63
- // Take the most recent events (last N in the sorted list)
64
- return allEvents.slice(-FREE_TIER_EVENT_LIMIT);
65
- }, [allEvents, isPro]);
66
-
67
- // Calculate how many events are locked
68
- const lockedEventCount = useMemo(() => {
69
- if (isPro) return 0;
70
- return Math.max(0, allEvents.length - FREE_TIER_EVENT_LIMIT);
71
- }, [allEvents.length, isPro]);
72
- const totalEvents = events.length;
73
- const currentEvent = events[selectedEventIndex];
74
- const previousEvent = selectedEventIndex > 0 ? events[selectedEventIndex - 1] : null;
75
-
76
- // Navigation handlers
77
- const goToPrevious = useCallback(() => {
78
- if (selectedEventIndex > 0) {
79
- onEventIndexChange(selectedEventIndex - 1);
80
- }
81
- }, [selectedEventIndex, onEventIndexChange]);
82
- const goToNext = useCallback(() => {
83
- if (selectedEventIndex < totalEvents - 1) {
84
- onEventIndexChange(selectedEventIndex + 1);
85
- }
86
- }, [selectedEventIndex, totalEvents, onEventIndexChange]);
87
-
88
- // If no history, show empty state
89
- if (totalEvents === 0) {
90
- return /*#__PURE__*/_jsxs(View, {
91
- style: styles.emptyContainer,
92
- children: [/*#__PURE__*/_jsx(Clock, {
93
- size: 32,
94
- color: buoyColors.textMuted
95
- }), /*#__PURE__*/_jsx(Text, {
96
- style: styles.emptyTitle,
97
- children: "No Render History"
98
- }), /*#__PURE__*/_jsx(Text, {
99
- style: styles.emptyText,
100
- children: "Enable render history tracking in settings to see render events here."
101
- })]
102
- });
103
- }
104
- return /*#__PURE__*/_jsxs(_Fragment, {
105
- children: [/*#__PURE__*/_jsxs(View, {
106
- style: [styles.container, {
107
- paddingBottom: !disableInternalFooter && totalEvents > 1 ? 80 : 0
108
- }],
109
- children: [lockedEventCount > 0 && /*#__PURE__*/_jsxs(View, {
110
- style: styles.lockedBanner,
111
- children: [/*#__PURE__*/_jsx(Lock, {
112
- size: 14,
113
- color: buoyColors.warning
114
- }), /*#__PURE__*/_jsxs(Text, {
115
- style: styles.lockedBannerText,
116
- children: [lockedEventCount, " older ", lockedEventCount === 1 ? 'render' : 'renders', " locked"]
117
- }), /*#__PURE__*/_jsx(Text, {
118
- style: styles.lockedBannerSubtext,
119
- children: "Upgrade to Pro"
120
- })]
121
- }), /*#__PURE__*/_jsxs(View, {
122
- style: styles.viewToggleContainer,
123
- children: [/*#__PURE__*/_jsxs(TouchableOpacity, {
124
- style: [styles.viewToggleCard, activeView === "current" && styles.viewToggleCardActive],
125
- onPress: () => setActiveView("current"),
126
- activeOpacity: 0.8,
127
- children: [/*#__PURE__*/_jsxs(View, {
128
- style: styles.viewToggleContent,
129
- children: [/*#__PURE__*/_jsx(Database, {
130
- size: 16,
131
- color: activeView === "current" ? buoyColors.primary : buoyColors.textSecondary
132
- }), /*#__PURE__*/_jsx(Text, {
133
- style: [styles.viewToggleLabel, activeView === "current" && styles.viewToggleLabelActive],
134
- children: "CURRENT STATE"
135
- })]
136
- }), /*#__PURE__*/_jsxs(Text, {
137
- style: [styles.viewToggleDescription, activeView === "current" && {
138
- color: buoyColors.text
139
- }],
140
- children: ["View render #", currentEvent?.renderNumber ?? 0, " details"]
141
- })]
142
- }), /*#__PURE__*/_jsxs(View, {
143
- style: [styles.viewToggleCard, styles.viewToggleCardDisabled],
144
- children: [/*#__PURE__*/_jsxs(View, {
145
- style: styles.viewToggleContent,
146
- children: [/*#__PURE__*/_jsx(GitBranch, {
147
- size: 16,
148
- color: buoyColors.textMuted
149
- }), /*#__PURE__*/_jsx(Text, {
150
- style: [styles.viewToggleLabel, styles.viewToggleLabelDisabled],
151
- children: "DIFF VIEW"
152
- }), /*#__PURE__*/_jsx(View, {
153
- style: styles.todoBadge,
154
- children: /*#__PURE__*/_jsx(Text, {
155
- style: styles.todoBadgeText,
156
- children: "TODO"
157
- })
158
- })]
159
- }), /*#__PURE__*/_jsx(Text, {
160
- style: [styles.viewToggleDescription, {
161
- color: buoyColors.textMuted
162
- }],
163
- children: "Compare renders side by side (coming soon)"
164
- })]
165
- })]
166
- }), /*#__PURE__*/_jsx(ScrollView, {
167
- style: styles.contentScroll,
168
- contentContainerStyle: styles.contentContainer,
169
- showsVerticalScrollIndicator: false,
170
- children: activeView === "current" ? /*#__PURE__*/_jsx(CurrentStateView, {
171
- event: currentEvent,
172
- render: render
173
- }) : /*#__PURE__*/_jsx(DiffView, {
174
- previousEvent: previousEvent,
175
- currentEvent: currentEvent,
176
- render: render
177
- })
178
- })]
179
- }), !disableInternalFooter && /*#__PURE__*/_jsx(EventStepperFooter, {
180
- currentIndex: selectedEventIndex,
181
- totalItems: totalEvents,
182
- onPrevious: goToPrevious,
183
- onNext: goToNext,
184
- itemLabel: "Render",
185
- subtitle: formatRelativeTime(new Date(currentEvent?.timestamp ?? Date.now()))
186
- })]
187
- });
188
- }
189
-
190
- /**
191
- * Current State View - shows details of the selected render event
192
- */
193
- function CurrentStateView({
194
- event,
195
- render
196
- }) {
197
- if (!event) {
198
- return /*#__PURE__*/_jsx(View, {
199
- style: styles.noEventContainer,
200
- children: /*#__PURE__*/_jsx(Text, {
201
- style: styles.noEventText,
202
- children: "No event selected"
203
- })
204
- });
205
- }
206
- const causeConfig = CAUSE_CONFIG[event.cause.type];
207
- return /*#__PURE__*/_jsxs(View, {
208
- style: styles.currentStateContainer,
209
- children: [/*#__PURE__*/_jsxs(View, {
210
- style: styles.eventHeader,
211
- children: [/*#__PURE__*/_jsxs(View, {
212
- style: styles.eventHeaderLeft,
213
- children: [/*#__PURE__*/_jsxs(Text, {
214
- style: styles.eventTitle,
215
- children: ["Render #", event.renderNumber]
216
- }), /*#__PURE__*/_jsx(Text, {
217
- style: styles.eventTime,
218
- children: formatTimeWithMs(event.timestamp)
219
- })]
220
- }), /*#__PURE__*/_jsxs(View, {
221
- style: [styles.eventBadge, {
222
- backgroundColor: render.color + "30"
223
- }],
224
- children: [/*#__PURE__*/_jsx(View, {
225
- style: [styles.eventBadgeDot, {
226
- backgroundColor: render.color
227
- }]
228
- }), /*#__PURE__*/_jsx(Text, {
229
- style: [styles.eventBadgeText, {
230
- color: render.color
231
- }],
232
- children: event.cause.type.toUpperCase()
233
- })]
234
- })]
235
- }), /*#__PURE__*/_jsxs(View, {
236
- style: styles.section,
237
- children: [/*#__PURE__*/_jsxs(SectionHeader, {
238
- children: [/*#__PURE__*/_jsx(SectionHeader.Icon, {
239
- icon: Clock,
240
- color: causeConfig.color,
241
- size: 12
242
- }), /*#__PURE__*/_jsx(SectionHeader.Title, {
243
- children: "WHY DID THIS RENDER?"
244
- })]
245
- }), /*#__PURE__*/_jsx(View, {
246
- style: styles.sectionContent,
247
- children: /*#__PURE__*/_jsx(EnhancedCauseDisplay, {
248
- cause: event.cause,
249
- nativeType: render.viewType
250
- })
251
- })]
252
- }), event.capturedProps && Object.keys(event.capturedProps).length > 0 && /*#__PURE__*/_jsxs(View, {
253
- style: styles.section,
254
- children: [/*#__PURE__*/_jsxs(SectionHeader, {
255
- children: [/*#__PURE__*/_jsx(SectionHeader.Icon, {
256
- icon: Database,
257
- color: buoyColors.primary,
258
- size: 12
259
- }), /*#__PURE__*/_jsx(SectionHeader.Title, {
260
- children: "CAPTURED PROPS"
261
- })]
262
- }), /*#__PURE__*/_jsx(View, {
263
- style: styles.sectionContent,
264
- children: /*#__PURE__*/_jsx(ScrollView, {
265
- horizontal: true,
266
- showsHorizontalScrollIndicator: false,
267
- style: styles.propsScrollView,
268
- children: /*#__PURE__*/_jsx(Text, {
269
- style: styles.propsJson,
270
- children: JSON.stringify(event.capturedProps, null, 2)
271
- })
272
- })
273
- })]
274
- })]
275
- });
276
- }
277
-
278
- /**
279
- * Diff mode types
280
- */
281
-
282
- /**
283
- * Diff View - shows comparison between two render events
284
- */
285
- function DiffView({
286
- previousEvent,
287
- currentEvent,
288
- render
289
- }) {
290
- // Diff mode tab state
291
- const [diffMode, setDiffMode] = useState("props");
292
- if (!previousEvent || !currentEvent) {
293
- return /*#__PURE__*/_jsx(View, {
294
- style: styles.noEventContainer,
295
- children: /*#__PURE__*/_jsx(Text, {
296
- style: styles.noEventText,
297
- children: "Select an event with a previous event to compare"
298
- })
299
- });
300
- }
301
- const prevCauseConfig = CAUSE_CONFIG[previousEvent.cause.type];
302
- const currCauseConfig = CAUSE_CONFIG[currentEvent.cause.type];
303
-
304
- // Check what data is available for diff
305
- const hasPropsData = previousEvent.capturedProps && currentEvent.capturedProps;
306
- const hasStateData = previousEvent.capturedState && currentEvent.capturedState;
307
- return /*#__PURE__*/_jsxs(View, {
308
- style: styles.diffContainer,
309
- children: [/*#__PURE__*/_jsxs(View, {
310
- style: styles.compareBar,
311
- children: [/*#__PURE__*/_jsxs(View, {
312
- style: styles.compareSide,
313
- children: [/*#__PURE__*/_jsxs(View, {
314
- style: styles.compareLabelRow,
315
- children: [/*#__PURE__*/_jsx(Text, {
316
- style: [styles.compareLabel, {
317
- color: buoyColors.warning
318
- }],
319
- children: "PREV"
320
- }), /*#__PURE__*/_jsx(View, {
321
- style: [styles.compareActionBadge, {
322
- backgroundColor: `${prevCauseConfig.color}20`
323
- }],
324
- children: /*#__PURE__*/_jsx(Text, {
325
- style: [styles.compareActionText, {
326
- color: prevCauseConfig.color
327
- }],
328
- children: previousEvent.cause.type.toUpperCase()
329
- })
330
- })]
331
- }), /*#__PURE__*/_jsxs(View, {
332
- style: styles.compareMeta,
333
- children: [/*#__PURE__*/_jsxs(Text, {
334
- style: styles.compareIndex,
335
- children: ["#", previousEvent.renderNumber]
336
- }), /*#__PURE__*/_jsx(Text, {
337
- style: styles.compareTime,
338
- children: formatTimeWithMs(previousEvent.timestamp)
339
- })]
340
- })]
341
- }), /*#__PURE__*/_jsx(View, {
342
- style: styles.compareDivider,
343
- children: /*#__PURE__*/_jsx(Text, {
344
- style: styles.compareArrow,
345
- children: "\u2192"
346
- })
347
- }), /*#__PURE__*/_jsxs(View, {
348
- style: styles.compareSide,
349
- children: [/*#__PURE__*/_jsxs(View, {
350
- style: styles.compareLabelRow,
351
- children: [/*#__PURE__*/_jsx(Text, {
352
- style: [styles.compareLabel, {
353
- color: buoyColors.success
354
- }],
355
- children: "CUR"
356
- }), /*#__PURE__*/_jsx(View, {
357
- style: [styles.compareActionBadge, {
358
- backgroundColor: `${currCauseConfig.color}20`
359
- }],
360
- children: /*#__PURE__*/_jsx(Text, {
361
- style: [styles.compareActionText, {
362
- color: currCauseConfig.color
363
- }],
364
- children: currentEvent.cause.type.toUpperCase()
365
- })
366
- })]
367
- }), /*#__PURE__*/_jsxs(View, {
368
- style: styles.compareMeta,
369
- children: [/*#__PURE__*/_jsxs(Text, {
370
- style: styles.compareIndex,
371
- children: ["#", currentEvent.renderNumber]
372
- }), /*#__PURE__*/_jsx(Text, {
373
- style: styles.compareTime,
374
- children: formatTimeWithMs(currentEvent.timestamp)
375
- })]
376
- })]
377
- })]
378
- }), /*#__PURE__*/_jsxs(View, {
379
- style: styles.diffModeTabs,
380
- children: [/*#__PURE__*/_jsx(TouchableOpacity, {
381
- style: [styles.diffModeTab, diffMode === "cause" && styles.diffModeTabActive],
382
- onPress: () => setDiffMode("cause"),
383
- activeOpacity: 0.7,
384
- children: /*#__PURE__*/_jsx(Text, {
385
- style: [styles.diffModeTabText, diffMode === "cause" && styles.diffModeTabTextActive],
386
- children: "CAUSE"
387
- })
388
- }), /*#__PURE__*/_jsx(TouchableOpacity, {
389
- style: [styles.diffModeTab, diffMode === "props" && styles.diffModeTabActive, !hasPropsData && styles.diffModeTabDisabled],
390
- onPress: () => hasPropsData && setDiffMode("props"),
391
- activeOpacity: hasPropsData ? 0.7 : 1,
392
- children: /*#__PURE__*/_jsx(Text, {
393
- style: [styles.diffModeTabText, diffMode === "props" && styles.diffModeTabTextActive, !hasPropsData && styles.diffModeTabTextDisabled],
394
- children: "PROPS"
395
- })
396
- }), /*#__PURE__*/_jsx(TouchableOpacity, {
397
- style: [styles.diffModeTab, diffMode === "state" && styles.diffModeTabActive, !hasStateData && styles.diffModeTabDisabled],
398
- onPress: () => hasStateData && setDiffMode("state"),
399
- activeOpacity: hasStateData ? 0.7 : 1,
400
- children: /*#__PURE__*/_jsx(Text, {
401
- style: [styles.diffModeTabText, diffMode === "state" && styles.diffModeTabTextActive, !hasStateData && styles.diffModeTabTextDisabled],
402
- children: "STATE"
403
- })
404
- })]
405
- }), diffMode === "cause" && /*#__PURE__*/_jsx(View, {
406
- style: styles.diffSummary,
407
- children: /*#__PURE__*/_jsx(EnhancedCauseDisplay, {
408
- cause: currentEvent.cause,
409
- nativeType: render.viewType
410
- })
411
- }), diffMode === "props" && /*#__PURE__*/_jsx(View, {
412
- style: styles.treeDiffContainer,
413
- children: hasPropsData ? /*#__PURE__*/_jsx(TreeDiffViewer, {
414
- oldValue: previousEvent.capturedProps,
415
- newValue: currentEvent.capturedProps,
416
- theme: "dark",
417
- showUnchanged: true
418
- }) : /*#__PURE__*/_jsxs(View, {
419
- style: styles.noDiffData,
420
- children: [/*#__PURE__*/_jsx(Text, {
421
- style: styles.noDiffDataTitle,
422
- children: "Props Not Captured"
423
- }), /*#__PURE__*/_jsx(Text, {
424
- style: styles.noDiffDataText,
425
- children: "Enable \"Capture Props on Render\" in settings to see props diff."
426
- })]
427
- })
428
- }), diffMode === "state" && /*#__PURE__*/_jsx(View, {
429
- style: styles.treeDiffContainer,
430
- children: hasStateData ? /*#__PURE__*/_jsx(TreeDiffViewer, {
431
- oldValue: previousEvent.capturedState,
432
- newValue: currentEvent.capturedState,
433
- theme: "dark",
434
- showUnchanged: true
435
- }) : /*#__PURE__*/_jsxs(View, {
436
- style: styles.noDiffData,
437
- children: [/*#__PURE__*/_jsx(Text, {
438
- style: styles.noDiffDataTitle,
439
- children: "State Not Captured"
440
- }), /*#__PURE__*/_jsx(Text, {
441
- style: styles.noDiffDataText,
442
- children: "Enable \"Capture State on Render\" in settings to see state diff."
443
- })]
444
- })
445
- })]
446
- });
447
- }
448
-
449
- /**
450
- * External footer component for modal integration
451
- * Uses renderHistory for events (only available when history tracking is enabled)
452
- */
453
- export function RenderHistoryFooter({
454
- render,
455
- selectedEventIndex = 0,
456
- onEventIndexChange = () => {},
457
- isPro = false
458
- }) {
459
- // Get all events from render history (sorted by timestamp)
460
- const allEvents = useMemo(() => {
461
- if (!render.renderHistory || render.renderHistory.length === 0) {
462
- return [];
463
- }
464
- return [...render.renderHistory].sort((a, b) => a.timestamp - b.timestamp);
465
- }, [render.renderHistory]);
466
-
467
- // Limit visible events for free tier (show most recent N events)
468
- const events = useMemo(() => {
469
- if (isPro) return allEvents;
470
- return allEvents.slice(-FREE_TIER_EVENT_LIMIT);
471
- }, [allEvents, isPro]);
472
- const totalEvents = events.length;
473
- const currentEvent = events[selectedEventIndex];
474
- const goToPrevious = useCallback(() => {
475
- onEventIndexChange(Math.max(0, selectedEventIndex - 1));
476
- }, [selectedEventIndex, onEventIndexChange]);
477
- const goToNext = useCallback(() => {
478
- onEventIndexChange(Math.min(totalEvents - 1, selectedEventIndex + 1));
479
- }, [selectedEventIndex, totalEvents, onEventIndexChange]);
480
-
481
- // Don't render if no history events (history tracking might be disabled)
482
- if (totalEvents <= 1) {
483
- return null;
484
- }
485
- return /*#__PURE__*/_jsx(EventStepperFooter, {
486
- currentIndex: selectedEventIndex,
487
- totalItems: totalEvents,
488
- onPrevious: goToPrevious,
489
- onNext: goToNext,
490
- itemLabel: "Render",
491
- subtitle: currentEvent ? formatRelativeTime(new Date(currentEvent.timestamp)) : undefined
492
- });
493
- }
494
- const styles = StyleSheet.create({
495
- container: {
496
- flex: 1,
497
- backgroundColor: buoyColors.base
498
- },
499
- emptyContainer: {
500
- flex: 1,
501
- alignItems: "center",
502
- justifyContent: "center",
503
- padding: 32,
504
- gap: 12
505
- },
506
- emptyTitle: {
507
- fontSize: 16,
508
- fontWeight: "600",
509
- color: buoyColors.text
510
- },
511
- emptyText: {
512
- fontSize: 13,
513
- color: buoyColors.textSecondary,
514
- textAlign: "center",
515
- lineHeight: 18
516
- },
517
- viewToggleContainer: {
518
- flexDirection: "row",
519
- padding: 12,
520
- gap: 8
521
- },
522
- viewToggleCard: {
523
- flex: 1,
524
- backgroundColor: buoyColors.card,
525
- borderRadius: 8,
526
- borderWidth: 1,
527
- borderColor: buoyColors.border,
528
- padding: 10,
529
- gap: 4
530
- },
531
- viewToggleCardActive: {
532
- borderColor: buoyColors.primary,
533
- backgroundColor: buoyColors.primary + "10"
534
- },
535
- viewToggleCardDisabled: {
536
- opacity: 0.5
537
- },
538
- todoBadge: {
539
- backgroundColor: buoyColors.textMuted + "30",
540
- paddingHorizontal: 6,
541
- paddingVertical: 2,
542
- borderRadius: 4,
543
- marginLeft: 4
544
- },
545
- todoBadgeText: {
546
- fontSize: 9,
547
- fontWeight: "700",
548
- color: buoyColors.textMuted,
549
- letterSpacing: 0.3
550
- },
551
- viewToggleContent: {
552
- flexDirection: "row",
553
- alignItems: "center",
554
- gap: 6
555
- },
556
- viewToggleLabel: {
557
- fontSize: 10,
558
- fontWeight: "700",
559
- color: buoyColors.textSecondary,
560
- letterSpacing: 0.5
561
- },
562
- viewToggleLabelActive: {
563
- color: buoyColors.primary
564
- },
565
- viewToggleLabelDisabled: {
566
- color: buoyColors.textMuted
567
- },
568
- viewToggleDescription: {
569
- fontSize: 11,
570
- color: buoyColors.textMuted,
571
- marginTop: 2
572
- },
573
- contentScroll: {
574
- flex: 1
575
- },
576
- contentContainer: {
577
- padding: 12,
578
- paddingTop: 0
579
- },
580
- noEventContainer: {
581
- padding: 24,
582
- alignItems: "center"
583
- },
584
- noEventText: {
585
- fontSize: 13,
586
- color: buoyColors.textMuted
587
- },
588
- currentStateContainer: {
589
- gap: 12
590
- },
591
- eventHeader: {
592
- flexDirection: "row",
593
- alignItems: "center",
594
- justifyContent: "space-between",
595
- backgroundColor: buoyColors.card,
596
- borderRadius: 8,
597
- borderWidth: 1,
598
- borderColor: buoyColors.border,
599
- padding: 12
600
- },
601
- eventHeaderLeft: {
602
- gap: 2
603
- },
604
- eventTitle: {
605
- fontSize: 15,
606
- fontWeight: "700",
607
- color: buoyColors.text
608
- },
609
- eventTime: {
610
- fontSize: 11,
611
- color: buoyColors.textMuted,
612
- fontFamily: "monospace"
613
- },
614
- eventBadge: {
615
- flexDirection: "row",
616
- alignItems: "center",
617
- paddingHorizontal: 10,
618
- paddingVertical: 4,
619
- borderRadius: 12,
620
- gap: 6
621
- },
622
- eventBadgeDot: {
623
- width: 6,
624
- height: 6,
625
- borderRadius: 3
626
- },
627
- eventBadgeText: {
628
- fontSize: 10,
629
- fontWeight: "700",
630
- fontFamily: "monospace"
631
- },
632
- section: {
633
- backgroundColor: buoyColors.card,
634
- borderRadius: 8,
635
- borderWidth: 1,
636
- borderColor: buoyColors.border,
637
- overflow: "hidden"
638
- },
639
- sectionContent: {
640
- padding: 12,
641
- paddingTop: 8
642
- },
643
- causeContainer: {
644
- marginBottom: 12
645
- },
646
- changedList: {
647
- marginBottom: 12,
648
- paddingLeft: 4
649
- },
650
- changedListTitle: {
651
- fontSize: 11,
652
- fontWeight: "600",
653
- color: buoyColors.textSecondary,
654
- marginBottom: 6
655
- },
656
- changedItem: {
657
- fontSize: 12,
658
- color: buoyColors.text,
659
- fontFamily: "monospace",
660
- marginBottom: 3,
661
- paddingLeft: 8
662
- },
663
- propsScrollView: {
664
- maxHeight: 150
665
- },
666
- propsJson: {
667
- fontSize: 11,
668
- fontFamily: "monospace",
669
- color: buoyColors.text,
670
- backgroundColor: buoyColors.input,
671
- padding: 10,
672
- borderRadius: 6
673
- },
674
- diffContainer: {
675
- gap: 12
676
- },
677
- compareBar: {
678
- flexDirection: "row",
679
- backgroundColor: buoyColors.card,
680
- borderRadius: 8,
681
- borderWidth: 1,
682
- borderColor: buoyColors.border,
683
- padding: 10
684
- },
685
- compareSide: {
686
- flex: 1,
687
- gap: 4
688
- },
689
- compareLabelRow: {
690
- flexDirection: "row",
691
- alignItems: "center",
692
- gap: 8
693
- },
694
- compareLabel: {
695
- fontSize: 10,
696
- fontWeight: "700",
697
- letterSpacing: 0.5
698
- },
699
- compareActionBadge: {
700
- paddingHorizontal: 6,
701
- paddingVertical: 2,
702
- borderRadius: 4
703
- },
704
- compareActionText: {
705
- fontSize: 9,
706
- fontWeight: "600"
707
- },
708
- compareMeta: {
709
- flexDirection: "row",
710
- alignItems: "center",
711
- gap: 6
712
- },
713
- compareIndex: {
714
- fontSize: 12,
715
- fontWeight: "600",
716
- color: buoyColors.text
717
- },
718
- compareTime: {
719
- fontSize: 10,
720
- color: buoyColors.textMuted,
721
- fontFamily: "monospace"
722
- },
723
- compareDivider: {
724
- width: 30,
725
- alignItems: "center",
726
- justifyContent: "center"
727
- },
728
- compareArrow: {
729
- fontSize: 16,
730
- color: buoyColors.textMuted
731
- },
732
- diffSummary: {
733
- backgroundColor: buoyColors.card,
734
- borderRadius: 8,
735
- borderWidth: 1,
736
- borderColor: buoyColors.border,
737
- padding: 12
738
- },
739
- diffSummaryTitle: {
740
- fontSize: 11,
741
- fontWeight: "600",
742
- color: buoyColors.textSecondary,
743
- marginBottom: 8
744
- },
745
- diffChanges: {
746
- gap: 4
747
- },
748
- diffChangeItem: {
749
- flexDirection: "row",
750
- alignItems: "center",
751
- gap: 6
752
- },
753
- diffChangeIcon: {
754
- fontSize: 12,
755
- fontWeight: "700",
756
- color: buoyColors.warning,
757
- fontFamily: "monospace"
758
- },
759
- diffChangeKey: {
760
- fontSize: 12,
761
- color: buoyColors.text,
762
- fontFamily: "monospace"
763
- },
764
- diffNoChanges: {
765
- fontSize: 12,
766
- color: buoyColors.textMuted,
767
- fontStyle: "italic"
768
- },
769
- diffPlaceholder: {
770
- fontSize: 12,
771
- color: buoyColors.textMuted,
772
- fontStyle: "italic",
773
- textAlign: "center",
774
- padding: 16
775
- },
776
- // Diff mode tabs
777
- diffModeTabs: {
778
- flexDirection: "row",
779
- backgroundColor: buoyColors.card,
780
- borderRadius: 8,
781
- borderWidth: 1,
782
- borderColor: buoyColors.border,
783
- padding: 4,
784
- gap: 4
785
- },
786
- diffModeTab: {
787
- flex: 1,
788
- paddingVertical: 8,
789
- paddingHorizontal: 12,
790
- borderRadius: 6,
791
- alignItems: "center"
792
- },
793
- diffModeTabActive: {
794
- backgroundColor: buoyColors.primary + "20"
795
- },
796
- diffModeTabDisabled: {
797
- opacity: 0.4
798
- },
799
- diffModeTabText: {
800
- fontSize: 10,
801
- fontWeight: "600",
802
- color: buoyColors.textSecondary,
803
- letterSpacing: 0.5
804
- },
805
- diffModeTabTextActive: {
806
- color: buoyColors.primary
807
- },
808
- diffModeTabTextDisabled: {
809
- color: buoyColors.textMuted
810
- },
811
- // Cause diff styles
812
- causeDiffContainer: {
813
- gap: 8,
814
- marginBottom: 12
815
- },
816
- causeDiffRow: {
817
- flexDirection: "row",
818
- alignItems: "center",
819
- gap: 8
820
- },
821
- causeDiffLabel: {
822
- fontSize: 11,
823
- fontWeight: "600",
824
- color: buoyColors.textSecondary,
825
- minWidth: 80
826
- },
827
- causeDiffValue: {
828
- fontSize: 12,
829
- color: buoyColors.text,
830
- fontFamily: "monospace",
831
- fontWeight: "500"
832
- },
833
- diffChangesTitle: {
834
- fontSize: 11,
835
- fontWeight: "600",
836
- color: buoyColors.textSecondary,
837
- marginBottom: 6
838
- },
839
- // Tree diff container
840
- treeDiffContainer: {
841
- backgroundColor: buoyColors.card,
842
- borderRadius: 8,
843
- borderWidth: 1,
844
- borderColor: buoyColors.border,
845
- overflow: "hidden",
846
- minHeight: 150
847
- },
848
- noDiffData: {
849
- padding: 24,
850
- alignItems: "center",
851
- gap: 8
852
- },
853
- noDiffDataTitle: {
854
- fontSize: 13,
855
- fontWeight: "600",
856
- color: buoyColors.text
857
- },
858
- noDiffDataText: {
859
- fontSize: 12,
860
- color: buoyColors.textMuted,
861
- textAlign: "center",
862
- lineHeight: 18
863
- },
864
- lockedBanner: {
865
- flexDirection: "row",
866
- alignItems: "center",
867
- justifyContent: "center",
868
- paddingVertical: 10,
869
- paddingHorizontal: 16,
870
- marginHorizontal: 12,
871
- marginTop: 8,
872
- backgroundColor: buoyColors.warning + "15",
873
- borderRadius: 8,
874
- borderWidth: 1,
875
- borderColor: buoyColors.warning + "30",
876
- gap: 8
877
- },
878
- lockedBannerText: {
879
- color: buoyColors.warning,
880
- fontSize: 13,
881
- fontWeight: "500"
882
- },
883
- lockedBannerSubtext: {
884
- color: buoyColors.textMuted,
885
- fontSize: 12
886
- }
887
- });
888
- export default RenderHistoryViewer;
1
+ "use strict";import React,{useState,useCallback,useMemo}from"react";import{View,Text,TouchableOpacity,ScrollView,StyleSheet}from"react-native";import{Clock,GitBranch,Database,Lock,formatRelativeTime,SectionHeader,EventStepperFooter,buoyColors}from"@buoy-gg/shared-ui";const FREE_TIER_EVENT_LIMIT=3;import{TreeDiffViewer}from"@buoy-gg/shared-ui/dataViewer";import{EnhancedCauseDisplay,CAUSE_CONFIG}from"./RenderCauseBadge";import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";function formatTimeWithMs(e){const t=new Date(e);return t.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit",second:"2-digit"})+`.${t.getMilliseconds().toString().padStart(3,"0")}`}export function RenderHistoryViewer({render:e,disableInternalFooter:t=!1,selectedEventIndex:o,onEventIndexChange:r,isPro:s=!1}){const[i,n]=useState(0),l=o??i,a=r??n,[d,c]=useState("current"),y=useMemo(()=>e.renderHistory&&0!==e.renderHistory.length?[...e.renderHistory].sort((e,t)=>e.timestamp-t.timestamp):[],[e.renderHistory]),u=useMemo(()=>s?y:y.slice(-3),[y,s]),x=useMemo(()=>s?0:Math.max(0,y.length-3),[y.length,s]),f=u.length,g=u[l],p=l>0?u[l-1]:null,b=useCallback(()=>{l>0&&a(l-1)},[l,a]),m=useCallback(()=>{l<f-1&&a(l+1)},[l,f,a]);return 0===f?_jsxs(View,{style:styles.emptyContainer,children:[_jsx(Clock,{size:32,color:buoyColors.textMuted}),_jsx(Text,{style:styles.emptyTitle,children:"No Render History"}),_jsx(Text,{style:styles.emptyText,children:"Enable render history tracking in settings to see render events here."})]}):_jsxs(_Fragment,{children:[_jsxs(View,{style:[styles.container,{paddingBottom:!t&&f>1?80:0}],children:[x>0&&_jsxs(View,{style:styles.lockedBanner,children:[_jsx(Lock,{size:14,color:buoyColors.warning}),_jsxs(Text,{style:styles.lockedBannerText,children:[x," older ",1===x?"render":"renders"," locked"]}),_jsx(Text,{style:styles.lockedBannerSubtext,children:"Upgrade to Pro"})]}),_jsxs(View,{style:styles.viewToggleContainer,children:[_jsxs(TouchableOpacity,{style:[styles.viewToggleCard,"current"===d&&styles.viewToggleCardActive],onPress:()=>c("current"),activeOpacity:.8,children:[_jsxs(View,{style:styles.viewToggleContent,children:[_jsx(Database,{size:16,color:"current"===d?buoyColors.primary:buoyColors.textSecondary}),_jsx(Text,{style:[styles.viewToggleLabel,"current"===d&&styles.viewToggleLabelActive],children:"CURRENT STATE"})]}),_jsxs(Text,{style:[styles.viewToggleDescription,"current"===d&&{color:buoyColors.text}],children:["View render #",g?.renderNumber??0," details"]})]}),_jsxs(View,{style:[styles.viewToggleCard,styles.viewToggleCardDisabled],children:[_jsxs(View,{style:styles.viewToggleContent,children:[_jsx(GitBranch,{size:16,color:buoyColors.textMuted}),_jsx(Text,{style:[styles.viewToggleLabel,styles.viewToggleLabelDisabled],children:"DIFF VIEW"}),_jsx(View,{style:styles.todoBadge,children:_jsx(Text,{style:styles.todoBadgeText,children:"TODO"})})]}),_jsx(Text,{style:[styles.viewToggleDescription,{color:buoyColors.textMuted}],children:"Compare renders side by side (coming soon)"})]})]}),_jsx(ScrollView,{style:styles.contentScroll,contentContainerStyle:styles.contentContainer,showsVerticalScrollIndicator:!1,children:"current"===d?_jsx(CurrentStateView,{event:g,render:e}):_jsx(DiffView,{previousEvent:p,currentEvent:g,render:e})})]}),!t&&_jsx(EventStepperFooter,{currentIndex:l,totalItems:f,onPrevious:b,onNext:m,itemLabel:"Render",subtitle:formatRelativeTime(new Date(g?.timestamp??Date.now()))})]})}function CurrentStateView({event:e,render:t}){if(!e)return _jsx(View,{style:styles.noEventContainer,children:_jsx(Text,{style:styles.noEventText,children:"No event selected"})});const o=CAUSE_CONFIG[e.cause.type];return _jsxs(View,{style:styles.currentStateContainer,children:[_jsxs(View,{style:styles.eventHeader,children:[_jsxs(View,{style:styles.eventHeaderLeft,children:[_jsxs(Text,{style:styles.eventTitle,children:["Render #",e.renderNumber]}),_jsx(Text,{style:styles.eventTime,children:formatTimeWithMs(e.timestamp)})]}),_jsxs(View,{style:[styles.eventBadge,{backgroundColor:t.color+"30"}],children:[_jsx(View,{style:[styles.eventBadgeDot,{backgroundColor:t.color}]}),_jsx(Text,{style:[styles.eventBadgeText,{color:t.color}],children:e.cause.type.toUpperCase()})]})]}),_jsxs(View,{style:styles.section,children:[_jsxs(SectionHeader,{children:[_jsx(SectionHeader.Icon,{icon:Clock,color:o.color,size:12}),_jsx(SectionHeader.Title,{children:"WHY DID THIS RENDER?"})]}),_jsx(View,{style:styles.sectionContent,children:_jsx(EnhancedCauseDisplay,{cause:e.cause,nativeType:t.viewType})})]}),e.capturedProps&&Object.keys(e.capturedProps).length>0&&_jsxs(View,{style:styles.section,children:[_jsxs(SectionHeader,{children:[_jsx(SectionHeader.Icon,{icon:Database,color:buoyColors.primary,size:12}),_jsx(SectionHeader.Title,{children:"CAPTURED PROPS"})]}),_jsx(View,{style:styles.sectionContent,children:_jsx(ScrollView,{horizontal:!0,showsHorizontalScrollIndicator:!1,style:styles.propsScrollView,children:_jsx(Text,{style:styles.propsJson,children:JSON.stringify(e.capturedProps,null,2)})})})]})]})}function DiffView({previousEvent:e,currentEvent:t,render:o}){const[r,s]=useState("props");if(!e||!t)return _jsx(View,{style:styles.noEventContainer,children:_jsx(Text,{style:styles.noEventText,children:"Select an event with a previous event to compare"})});const i=CAUSE_CONFIG[e.cause.type],n=CAUSE_CONFIG[t.cause.type],l=e.capturedProps&&t.capturedProps,a=e.capturedState&&t.capturedState;return _jsxs(View,{style:styles.diffContainer,children:[_jsxs(View,{style:styles.compareBar,children:[_jsxs(View,{style:styles.compareSide,children:[_jsxs(View,{style:styles.compareLabelRow,children:[_jsx(Text,{style:[styles.compareLabel,{color:buoyColors.warning}],children:"PREV"}),_jsx(View,{style:[styles.compareActionBadge,{backgroundColor:`${i.color}20`}],children:_jsx(Text,{style:[styles.compareActionText,{color:i.color}],children:e.cause.type.toUpperCase()})})]}),_jsxs(View,{style:styles.compareMeta,children:[_jsxs(Text,{style:styles.compareIndex,children:["#",e.renderNumber]}),_jsx(Text,{style:styles.compareTime,children:formatTimeWithMs(e.timestamp)})]})]}),_jsx(View,{style:styles.compareDivider,children:_jsx(Text,{style:styles.compareArrow,children:"→"})}),_jsxs(View,{style:styles.compareSide,children:[_jsxs(View,{style:styles.compareLabelRow,children:[_jsx(Text,{style:[styles.compareLabel,{color:buoyColors.success}],children:"CUR"}),_jsx(View,{style:[styles.compareActionBadge,{backgroundColor:`${n.color}20`}],children:_jsx(Text,{style:[styles.compareActionText,{color:n.color}],children:t.cause.type.toUpperCase()})})]}),_jsxs(View,{style:styles.compareMeta,children:[_jsxs(Text,{style:styles.compareIndex,children:["#",t.renderNumber]}),_jsx(Text,{style:styles.compareTime,children:formatTimeWithMs(t.timestamp)})]})]})]}),_jsxs(View,{style:styles.diffModeTabs,children:[_jsx(TouchableOpacity,{style:[styles.diffModeTab,"cause"===r&&styles.diffModeTabActive],onPress:()=>s("cause"),activeOpacity:.7,children:_jsx(Text,{style:[styles.diffModeTabText,"cause"===r&&styles.diffModeTabTextActive],children:"CAUSE"})}),_jsx(TouchableOpacity,{style:[styles.diffModeTab,"props"===r&&styles.diffModeTabActive,!l&&styles.diffModeTabDisabled],onPress:()=>l&&s("props"),activeOpacity:l?.7:1,children:_jsx(Text,{style:[styles.diffModeTabText,"props"===r&&styles.diffModeTabTextActive,!l&&styles.diffModeTabTextDisabled],children:"PROPS"})}),_jsx(TouchableOpacity,{style:[styles.diffModeTab,"state"===r&&styles.diffModeTabActive,!a&&styles.diffModeTabDisabled],onPress:()=>a&&s("state"),activeOpacity:a?.7:1,children:_jsx(Text,{style:[styles.diffModeTabText,"state"===r&&styles.diffModeTabTextActive,!a&&styles.diffModeTabTextDisabled],children:"STATE"})})]}),"cause"===r&&_jsx(View,{style:styles.diffSummary,children:_jsx(EnhancedCauseDisplay,{cause:t.cause,nativeType:o.viewType})}),"props"===r&&_jsx(View,{style:styles.treeDiffContainer,children:l?_jsx(TreeDiffViewer,{oldValue:e.capturedProps,newValue:t.capturedProps,theme:"dark",showUnchanged:!0}):_jsxs(View,{style:styles.noDiffData,children:[_jsx(Text,{style:styles.noDiffDataTitle,children:"Props Not Captured"}),_jsx(Text,{style:styles.noDiffDataText,children:'Enable "Capture Props on Render" in settings to see props diff.'})]})}),"state"===r&&_jsx(View,{style:styles.treeDiffContainer,children:a?_jsx(TreeDiffViewer,{oldValue:e.capturedState,newValue:t.capturedState,theme:"dark",showUnchanged:!0}):_jsxs(View,{style:styles.noDiffData,children:[_jsx(Text,{style:styles.noDiffDataTitle,children:"State Not Captured"}),_jsx(Text,{style:styles.noDiffDataText,children:'Enable "Capture State on Render" in settings to see state diff.'})]})})]})}export function RenderHistoryFooter({render:e,selectedEventIndex:t=0,onEventIndexChange:o=()=>{},isPro:r=!1}){const s=useMemo(()=>e.renderHistory&&0!==e.renderHistory.length?[...e.renderHistory].sort((e,t)=>e.timestamp-t.timestamp):[],[e.renderHistory]),i=useMemo(()=>r?s:s.slice(-3),[s,r]),n=i.length,l=i[t],a=useCallback(()=>{o(Math.max(0,t-1))},[t,o]),d=useCallback(()=>{o(Math.min(n-1,t+1))},[t,n,o]);return n<=1?null:_jsx(EventStepperFooter,{currentIndex:t,totalItems:n,onPrevious:a,onNext:d,itemLabel:"Render",subtitle:l?formatRelativeTime(new Date(l.timestamp)):void 0})}const styles=StyleSheet.create({container:{flex:1,backgroundColor:buoyColors.base},emptyContainer:{flex:1,alignItems:"center",justifyContent:"center",padding:32,gap:12},emptyTitle:{fontSize:16,fontWeight:"600",color:buoyColors.text},emptyText:{fontSize:13,color:buoyColors.textSecondary,textAlign:"center",lineHeight:18},viewToggleContainer:{flexDirection:"row",padding:12,gap:8},viewToggleCard:{flex:1,backgroundColor:buoyColors.card,borderRadius:8,borderWidth:1,borderColor:buoyColors.border,padding:10,gap:4},viewToggleCardActive:{borderColor:buoyColors.primary,backgroundColor:buoyColors.primary+"10"},viewToggleCardDisabled:{opacity:.5},todoBadge:{backgroundColor:buoyColors.textMuted+"30",paddingHorizontal:6,paddingVertical:2,borderRadius:4,marginLeft:4},todoBadgeText:{fontSize:9,fontWeight:"700",color:buoyColors.textMuted,letterSpacing:.3},viewToggleContent:{flexDirection:"row",alignItems:"center",gap:6},viewToggleLabel:{fontSize:10,fontWeight:"700",color:buoyColors.textSecondary,letterSpacing:.5},viewToggleLabelActive:{color:buoyColors.primary},viewToggleLabelDisabled:{color:buoyColors.textMuted},viewToggleDescription:{fontSize:11,color:buoyColors.textMuted,marginTop:2},contentScroll:{flex:1},contentContainer:{padding:12,paddingTop:0},noEventContainer:{padding:24,alignItems:"center"},noEventText:{fontSize:13,color:buoyColors.textMuted},currentStateContainer:{gap:12},eventHeader:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",backgroundColor:buoyColors.card,borderRadius:8,borderWidth:1,borderColor:buoyColors.border,padding:12},eventHeaderLeft:{gap:2},eventTitle:{fontSize:15,fontWeight:"700",color:buoyColors.text},eventTime:{fontSize:11,color:buoyColors.textMuted,fontFamily:"monospace"},eventBadge:{flexDirection:"row",alignItems:"center",paddingHorizontal:10,paddingVertical:4,borderRadius:12,gap:6},eventBadgeDot:{width:6,height:6,borderRadius:3},eventBadgeText:{fontSize:10,fontWeight:"700",fontFamily:"monospace"},section:{backgroundColor:buoyColors.card,borderRadius:8,borderWidth:1,borderColor:buoyColors.border,overflow:"hidden"},sectionContent:{padding:12,paddingTop:8},causeContainer:{marginBottom:12},changedList:{marginBottom:12,paddingLeft:4},changedListTitle:{fontSize:11,fontWeight:"600",color:buoyColors.textSecondary,marginBottom:6},changedItem:{fontSize:12,color:buoyColors.text,fontFamily:"monospace",marginBottom:3,paddingLeft:8},propsScrollView:{maxHeight:150},propsJson:{fontSize:11,fontFamily:"monospace",color:buoyColors.text,backgroundColor:buoyColors.input,padding:10,borderRadius:6},diffContainer:{gap:12},compareBar:{flexDirection:"row",backgroundColor:buoyColors.card,borderRadius:8,borderWidth:1,borderColor:buoyColors.border,padding:10},compareSide:{flex:1,gap:4},compareLabelRow:{flexDirection:"row",alignItems:"center",gap:8},compareLabel:{fontSize:10,fontWeight:"700",letterSpacing:.5},compareActionBadge:{paddingHorizontal:6,paddingVertical:2,borderRadius:4},compareActionText:{fontSize:9,fontWeight:"600"},compareMeta:{flexDirection:"row",alignItems:"center",gap:6},compareIndex:{fontSize:12,fontWeight:"600",color:buoyColors.text},compareTime:{fontSize:10,color:buoyColors.textMuted,fontFamily:"monospace"},compareDivider:{width:30,alignItems:"center",justifyContent:"center"},compareArrow:{fontSize:16,color:buoyColors.textMuted},diffSummary:{backgroundColor:buoyColors.card,borderRadius:8,borderWidth:1,borderColor:buoyColors.border,padding:12},diffSummaryTitle:{fontSize:11,fontWeight:"600",color:buoyColors.textSecondary,marginBottom:8},diffChanges:{gap:4},diffChangeItem:{flexDirection:"row",alignItems:"center",gap:6},diffChangeIcon:{fontSize:12,fontWeight:"700",color:buoyColors.warning,fontFamily:"monospace"},diffChangeKey:{fontSize:12,color:buoyColors.text,fontFamily:"monospace"},diffNoChanges:{fontSize:12,color:buoyColors.textMuted,fontStyle:"italic"},diffPlaceholder:{fontSize:12,color:buoyColors.textMuted,fontStyle:"italic",textAlign:"center",padding:16},diffModeTabs:{flexDirection:"row",backgroundColor:buoyColors.card,borderRadius:8,borderWidth:1,borderColor:buoyColors.border,padding:4,gap:4},diffModeTab:{flex:1,paddingVertical:8,paddingHorizontal:12,borderRadius:6,alignItems:"center"},diffModeTabActive:{backgroundColor:buoyColors.primary+"20"},diffModeTabDisabled:{opacity:.4},diffModeTabText:{fontSize:10,fontWeight:"600",color:buoyColors.textSecondary,letterSpacing:.5},diffModeTabTextActive:{color:buoyColors.primary},diffModeTabTextDisabled:{color:buoyColors.textMuted},causeDiffContainer:{gap:8,marginBottom:12},causeDiffRow:{flexDirection:"row",alignItems:"center",gap:8},causeDiffLabel:{fontSize:11,fontWeight:"600",color:buoyColors.textSecondary,minWidth:80},causeDiffValue:{fontSize:12,color:buoyColors.text,fontFamily:"monospace",fontWeight:"500"},diffChangesTitle:{fontSize:11,fontWeight:"600",color:buoyColors.textSecondary,marginBottom:6},treeDiffContainer:{backgroundColor:buoyColors.card,borderRadius:8,borderWidth:1,borderColor:buoyColors.border,overflow:"hidden",minHeight:150},noDiffData:{padding:24,alignItems:"center",gap:8},noDiffDataTitle:{fontSize:13,fontWeight:"600",color:buoyColors.text},noDiffDataText:{fontSize:12,color:buoyColors.textMuted,textAlign:"center",lineHeight:18},lockedBanner:{flexDirection:"row",alignItems:"center",justifyContent:"center",paddingVertical:10,paddingHorizontal:16,marginHorizontal:12,marginTop:8,backgroundColor:buoyColors.warning+"15",borderRadius:8,borderWidth:1,borderColor:buoyColors.warning+"30",gap:8},lockedBannerText:{color:buoyColors.warning,fontSize:13,fontWeight:"500"},lockedBannerSubtext:{color:buoyColors.textMuted,fontSize:12}});export default RenderHistoryViewer;