@buoy-gg/highlight-updates 2.1.11 → 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 (65) hide show
  1. package/LICENSE +58 -0
  2. package/lib/commonjs/highlight-updates/HighlightUpdatesOverlay.js +1 -285
  3. package/lib/commonjs/highlight-updates/components/HighlightFilterView.js +1 -1371
  4. package/lib/commonjs/highlight-updates/components/HighlightUpdatesModal.js +1 -591
  5. package/lib/commonjs/highlight-updates/components/IdentifierBadge.js +1 -267
  6. package/lib/commonjs/highlight-updates/components/IsolatedRenderList.js +1 -178
  7. package/lib/commonjs/highlight-updates/components/ModalHeaderContent.js +1 -303
  8. package/lib/commonjs/highlight-updates/components/RenderCauseBadge.js +1 -500
  9. package/lib/commonjs/highlight-updates/components/RenderDetailView.js +1 -830
  10. package/lib/commonjs/highlight-updates/components/RenderHistoryViewer.js +1 -894
  11. package/lib/commonjs/highlight-updates/components/RenderListItem.js +1 -220
  12. package/lib/commonjs/highlight-updates/components/StatsDisplay.js +1 -70
  13. package/lib/commonjs/highlight-updates/components/index.js +1 -97
  14. package/lib/commonjs/highlight-updates/utils/HighlightUpdatesController.js +1 -1435
  15. package/lib/commonjs/highlight-updates/utils/PerformanceLogger.js +1 -359
  16. package/lib/commonjs/highlight-updates/utils/ProfilerInterceptor.js +1 -371
  17. package/lib/commonjs/highlight-updates/utils/RenderCauseDetector.js +1 -1828
  18. package/lib/commonjs/highlight-updates/utils/RenderTracker.js +1 -903
  19. package/lib/commonjs/highlight-updates/utils/ViewTypeMapper.js +1 -264
  20. package/lib/commonjs/highlight-updates/utils/renderExportFormatter.js +1 -58
  21. package/lib/commonjs/index.js +1 -311
  22. package/lib/commonjs/preset.js +1 -278
  23. package/lib/module/highlight-updates/HighlightUpdatesOverlay.js +1 -278
  24. package/lib/module/highlight-updates/components/HighlightFilterView.js +1 -1365
  25. package/lib/module/highlight-updates/components/HighlightUpdatesModal.js +1 -585
  26. package/lib/module/highlight-updates/components/IdentifierBadge.js +1 -259
  27. package/lib/module/highlight-updates/components/IsolatedRenderList.js +1 -174
  28. package/lib/module/highlight-updates/components/ModalHeaderContent.js +1 -298
  29. package/lib/module/highlight-updates/components/RenderCauseBadge.js +1 -491
  30. package/lib/module/highlight-updates/components/RenderDetailView.js +1 -826
  31. package/lib/module/highlight-updates/components/RenderHistoryViewer.js +1 -888
  32. package/lib/module/highlight-updates/components/RenderListItem.js +1 -215
  33. package/lib/module/highlight-updates/components/StatsDisplay.js +1 -67
  34. package/lib/module/highlight-updates/components/index.js +1 -16
  35. package/lib/module/highlight-updates/utils/HighlightUpdatesController.js +1 -1431
  36. package/lib/module/highlight-updates/utils/PerformanceLogger.js +1 -353
  37. package/lib/module/highlight-updates/utils/ProfilerInterceptor.js +1 -358
  38. package/lib/module/highlight-updates/utils/RenderCauseDetector.js +1 -1818
  39. package/lib/module/highlight-updates/utils/RenderTracker.js +1 -900
  40. package/lib/module/highlight-updates/utils/ViewTypeMapper.js +1 -255
  41. package/lib/module/highlight-updates/utils/renderExportFormatter.js +1 -54
  42. package/lib/module/index.js +1 -71
  43. package/lib/module/preset.js +1 -272
  44. package/package.json +16 -16
  45. package/lib/typescript/highlight-updates/HighlightUpdatesOverlay.d.ts.map +0 -1
  46. package/lib/typescript/highlight-updates/components/HighlightFilterView.d.ts.map +0 -1
  47. package/lib/typescript/highlight-updates/components/HighlightUpdatesModal.d.ts.map +0 -1
  48. package/lib/typescript/highlight-updates/components/IdentifierBadge.d.ts.map +0 -1
  49. package/lib/typescript/highlight-updates/components/IsolatedRenderList.d.ts.map +0 -1
  50. package/lib/typescript/highlight-updates/components/ModalHeaderContent.d.ts.map +0 -1
  51. package/lib/typescript/highlight-updates/components/RenderCauseBadge.d.ts.map +0 -1
  52. package/lib/typescript/highlight-updates/components/RenderDetailView.d.ts.map +0 -1
  53. package/lib/typescript/highlight-updates/components/RenderHistoryViewer.d.ts.map +0 -1
  54. package/lib/typescript/highlight-updates/components/RenderListItem.d.ts.map +0 -1
  55. package/lib/typescript/highlight-updates/components/StatsDisplay.d.ts.map +0 -1
  56. package/lib/typescript/highlight-updates/components/index.d.ts.map +0 -1
  57. package/lib/typescript/highlight-updates/utils/HighlightUpdatesController.d.ts.map +0 -1
  58. package/lib/typescript/highlight-updates/utils/PerformanceLogger.d.ts.map +0 -1
  59. package/lib/typescript/highlight-updates/utils/ProfilerInterceptor.d.ts.map +0 -1
  60. package/lib/typescript/highlight-updates/utils/RenderCauseDetector.d.ts.map +0 -1
  61. package/lib/typescript/highlight-updates/utils/RenderTracker.d.ts.map +0 -1
  62. package/lib/typescript/highlight-updates/utils/ViewTypeMapper.d.ts.map +0 -1
  63. package/lib/typescript/highlight-updates/utils/renderExportFormatter.d.ts.map +0 -1
  64. package/lib/typescript/index.d.ts.map +0 -1
  65. package/lib/typescript/preset.d.ts.map +0 -1
@@ -1,826 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * RenderDetailView
5
- *
6
- * Minimal, glanceable view for render details.
7
- * Design principle: Dev should understand WHY in 3 seconds.
8
- *
9
- * Layout:
10
- * - Header: Component name + native type
11
- * - Answer Card: Cause badges + hook change (THE answer)
12
- * - History Row: Compact inline navigation
13
- */
14
-
15
- import React, { useMemo, useState, useCallback } from "react";
16
- import { View, Text, TouchableOpacity, ScrollView, StyleSheet } from "react-native";
17
- import { CopyButton, formatRelativeTime, PlusIcon, MinusIcon, EventStepperFooter, Lock, buoyColors } from "@buoy-gg/shared-ui";
18
- import { TreeDiffViewer } from "@buoy-gg/shared-ui/dataViewer";
19
- import { CAUSE_CONFIG, COMPONENT_CAUSE_CONFIG } from "./RenderCauseBadge";
20
-
21
- /**
22
- * Format component render data for clipboard
23
- */
24
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
25
- function formatRenderDetailForClipboard(render) {
26
- const lines = [];
27
- lines.push(`${render.componentName || render.displayName} (${render.viewType})`);
28
- lines.push(`Renders: ${render.renderCount}`);
29
- if (render.lastRenderCause) {
30
- const cause = render.lastRenderCause;
31
- if (cause.componentCause) {
32
- lines.push(`Cause: ${cause.componentCause.toUpperCase()} → ${cause.type.toUpperCase()}`);
33
- } else {
34
- lines.push(`Cause: ${cause.type.toUpperCase()}`);
35
- }
36
- if (cause.hookChanges?.length) {
37
- for (const hook of cause.hookChanges) {
38
- lines.push(` ${hook.type}[${hook.index}]: ${hook.previousValue} → ${hook.currentValue}`);
39
- }
40
- }
41
- }
42
- if (render.renderHistory?.length) {
43
- lines.push(`\nHistory (${render.renderHistory.length} events):`);
44
- for (const event of render.renderHistory) {
45
- const causeStr = event.cause.componentCause ? `${event.cause.componentCause.toUpperCase()} → ${event.cause.type.toUpperCase()}` : event.cause.type.toUpperCase();
46
- lines.push(` #${event.renderNumber}: ${causeStr}`);
47
- }
48
- }
49
- return lines.join("\n");
50
- }
51
- // Free tier limit for render history events
52
- const FREE_TIER_EVENT_LIMIT = 5;
53
- export function RenderDetailView({
54
- render,
55
- disableInternalFooter = false,
56
- selectedEventIndex: externalIndex,
57
- onEventIndexChange: externalOnChange,
58
- onAddFilter,
59
- isPro = false
60
- }) {
61
- // Internal state for event index when not controlled externally
62
- const [internalIndex, setInternalIndex] = useState(0);
63
-
64
- // Use external or internal state
65
- const selectedEventIndex = externalIndex ?? internalIndex;
66
- const onEventIndexChange = externalOnChange ?? setInternalIndex;
67
-
68
- // Get events sorted by timestamp (oldest first)
69
- const events = useMemo(() => {
70
- if (!render.renderHistory || render.renderHistory.length === 0) {
71
- return [];
72
- }
73
- return [...render.renderHistory].sort((a, b) => a.timestamp - b.timestamp);
74
- }, [render.renderHistory]);
75
- const totalEvents = events.length;
76
- const currentEvent = events[selectedEventIndex];
77
-
78
- // Calculate hidden events for free tier
79
- const hiddenEventCount = useMemo(() => {
80
- if (isPro) return 0;
81
- return Math.max(0, totalEvents - FREE_TIER_EVENT_LIMIT);
82
- }, [isPro, totalEvents]);
83
-
84
- // Use current event's cause if available, otherwise fall back to lastRenderCause
85
- const displayCause = currentEvent?.cause || render.lastRenderCause;
86
-
87
- // Navigation handlers
88
- const goToPrevious = useCallback(() => {
89
- if (selectedEventIndex > 0) {
90
- onEventIndexChange(selectedEventIndex - 1);
91
- }
92
- }, [selectedEventIndex, onEventIndexChange]);
93
- const goToNext = useCallback(() => {
94
- // Limit navigation for free tier users
95
- const maxIndex = isPro ? totalEvents - 1 : Math.min(FREE_TIER_EVENT_LIMIT - 1, totalEvents - 1);
96
- if (selectedEventIndex < maxIndex) {
97
- onEventIndexChange(selectedEventIndex + 1);
98
- }
99
- }, [selectedEventIndex, totalEvents, onEventIndexChange, isPro]);
100
-
101
- // Memoize copy data
102
- const copyData = useMemo(() => formatRenderDetailForClipboard(render), [render]);
103
-
104
- // Get component name (prefer componentName, fall back to displayName)
105
- const componentName = render.componentName || render.displayName;
106
- const nativeType = render.viewType;
107
-
108
- // Calculate render stats
109
- const renderDuration = render.lastRenderTime - render.firstRenderTime;
110
- const rendersPerSec = renderDuration > 0 ? (render.renderCount / (renderDuration / 1000)).toFixed(1) : render.renderCount.toString();
111
-
112
- // Determine if we should show footer (either history or filters)
113
- const showHistoryFooter = !disableInternalFooter && totalEvents > 1;
114
- return /*#__PURE__*/_jsxs(View, {
115
- style: styles.container,
116
- children: [/*#__PURE__*/_jsxs(View, {
117
- style: styles.header,
118
- children: [/*#__PURE__*/_jsxs(View, {
119
- style: styles.headerLeft,
120
- children: [/*#__PURE__*/_jsx(Text, {
121
- style: styles.componentName,
122
- numberOfLines: 1,
123
- children: componentName
124
- }), /*#__PURE__*/_jsx(View, {
125
- style: styles.nativeTypeBadge,
126
- children: /*#__PURE__*/_jsx(Text, {
127
- style: styles.nativeTypeText,
128
- children: nativeType
129
- })
130
- })]
131
- }), /*#__PURE__*/_jsx(CopyButton, {
132
- value: copyData,
133
- size: 14
134
- })]
135
- }), /*#__PURE__*/_jsxs(ScrollView, {
136
- style: styles.scrollView,
137
- contentContainerStyle: [styles.scrollContent, showHistoryFooter && {
138
- paddingBottom: 100
139
- }],
140
- showsVerticalScrollIndicator: false,
141
- children: [displayCause && /*#__PURE__*/_jsx(AnswerCard, {
142
- cause: displayCause,
143
- renderNumber: currentEvent?.renderNumber
144
- }), /*#__PURE__*/_jsx(DetailsSection, {
145
- render: render,
146
- rendersPerSec: rendersPerSec
147
- }), hiddenEventCount > 0 && /*#__PURE__*/_jsxs(View, {
148
- style: styles.lockedBanner,
149
- children: [/*#__PURE__*/_jsx(Lock, {
150
- size: 14,
151
- color: buoyColors.warning
152
- }), /*#__PURE__*/_jsxs(Text, {
153
- style: styles.lockedBannerText,
154
- children: [hiddenEventCount, " ", hiddenEventCount === 1 ? 'event' : 'events', " hidden"]
155
- }), /*#__PURE__*/_jsx(Text, {
156
- style: styles.lockedBannerSubtext,
157
- children: "Upgrade to Pro"
158
- })]
159
- }), onAddFilter && /*#__PURE__*/_jsx(QuickActionsSection, {
160
- render: render,
161
- onAddFilter: onAddFilter
162
- })]
163
- }), showHistoryFooter && /*#__PURE__*/_jsx(EventStepperFooter, {
164
- currentIndex: selectedEventIndex,
165
- totalItems: totalEvents,
166
- onPrevious: goToPrevious,
167
- onNext: goToNext,
168
- itemLabel: "Render",
169
- subtitle: currentEvent?.timestamp ? formatRelativeTime(new Date(currentEvent.timestamp)) : undefined,
170
- applySafeAreaInset: false,
171
- absolute: true
172
- })]
173
- });
174
- }
175
-
176
- /**
177
- * AnswerCard - The hero section showing WHY the component rendered
178
- * Design: Single badge + what changed below it
179
- */
180
- function AnswerCard({
181
- cause,
182
- renderNumber
183
- }) {
184
- // Use component cause if available, otherwise native cause
185
- const displayCauseType = cause.componentCause || cause.type;
186
- const config = cause.componentCause ? COMPONENT_CAUSE_CONFIG[cause.componentCause] : CAUSE_CONFIG[cause.type];
187
- const hasHookChanges = cause.hookChanges && cause.hookChanges.length > 0;
188
- const hasChangedKeys = cause.changedKeys && cause.changedKeys.length > 0;
189
-
190
- // Get contextual label based on cause type
191
- const getLabel = () => {
192
- if (cause.type === "mount") return "First render";
193
- if (displayCauseType === "parent") return "Triggered by";
194
- return "Changed:";
195
- };
196
- return /*#__PURE__*/_jsxs(View, {
197
- style: styles.answerCard,
198
- children: [/*#__PURE__*/_jsxs(View, {
199
- style: styles.causeBadgeRow,
200
- children: [/*#__PURE__*/_jsx(Text, {
201
- style: styles.causeLabel,
202
- children: getLabel()
203
- }), /*#__PURE__*/_jsx(View, {
204
- style: [styles.causeBadgeLarge, {
205
- backgroundColor: config.color + "20"
206
- }],
207
- children: /*#__PURE__*/_jsx(Text, {
208
- style: [styles.causeBadgeLargeText, {
209
- color: config.color
210
- }],
211
- children: config.label.toUpperCase()
212
- })
213
- })]
214
- }), hasHookChanges && /*#__PURE__*/_jsx(View, {
215
- style: styles.hookChangesContainer,
216
- children: cause.hookChanges.map((hook, index) => {
217
- const hookKey = `${hook.type}[${hook.index}]`;
218
- const oldValue = {
219
- [hookKey]: hook.previousValue
220
- };
221
- const newValue = {
222
- [hookKey]: hook.currentValue
223
- };
224
- return /*#__PURE__*/_jsx(View, {
225
- style: styles.hookDiffContainer,
226
- children: /*#__PURE__*/_jsx(TreeDiffViewer, {
227
- oldValue: oldValue,
228
- newValue: newValue,
229
- theme: "dark",
230
- showUnchanged: false
231
- })
232
- }, index);
233
- })
234
- }), !hasHookChanges && hasChangedKeys && /*#__PURE__*/_jsx(View, {
235
- style: styles.propsChangesContainer,
236
- children: cause.changedKeys.filter(k => !k.includes("(ref only)")).slice(0, 5).map((key, index) => /*#__PURE__*/_jsx(View, {
237
- style: styles.propChangeChip,
238
- children: /*#__PURE__*/_jsx(Text, {
239
- style: styles.propChangeText,
240
- children: key
241
- })
242
- }, index))
243
- })]
244
- });
245
- }
246
-
247
- /**
248
- * DetailsSection - Component identifiers, measurements, and stats
249
- * Helps devs find the component in their codebase
250
- */
251
- function DetailsSection({
252
- render,
253
- rendersPerSec
254
- }) {
255
- const hasIdentifiers = render.testID || render.nativeID || render.accessibilityLabel;
256
- const hasMeasurements = render.measurements;
257
- return /*#__PURE__*/_jsxs(View, {
258
- style: styles.detailsSection,
259
- children: [hasIdentifiers && /*#__PURE__*/_jsxs(View, {
260
- style: styles.detailsCard,
261
- children: [/*#__PURE__*/_jsx(Text, {
262
- style: styles.detailsCardTitle,
263
- children: "Identifiers"
264
- }), render.testID && /*#__PURE__*/_jsx(DetailRow, {
265
- label: "testID",
266
- value: render.testID
267
- }), render.nativeID && /*#__PURE__*/_jsx(DetailRow, {
268
- label: "nativeID",
269
- value: render.nativeID
270
- }), render.accessibilityLabel && /*#__PURE__*/_jsx(DetailRow, {
271
- label: "a11y",
272
- value: render.accessibilityLabel
273
- })]
274
- }), /*#__PURE__*/_jsxs(View, {
275
- style: styles.statsRow,
276
- children: [/*#__PURE__*/_jsxs(View, {
277
- style: styles.statItem,
278
- children: [/*#__PURE__*/_jsx(Text, {
279
- style: [styles.statValue, {
280
- color: render.color
281
- }],
282
- children: render.renderCount
283
- }), /*#__PURE__*/_jsx(Text, {
284
- style: styles.statLabel,
285
- children: "renders"
286
- })]
287
- }), /*#__PURE__*/_jsx(View, {
288
- style: styles.statDivider
289
- }), /*#__PURE__*/_jsxs(View, {
290
- style: styles.statItem,
291
- children: [/*#__PURE__*/_jsx(Text, {
292
- style: styles.statValue,
293
- children: rendersPerSec
294
- }), /*#__PURE__*/_jsx(Text, {
295
- style: styles.statLabel,
296
- children: "/sec"
297
- })]
298
- }), /*#__PURE__*/_jsx(View, {
299
- style: styles.statDivider
300
- }), /*#__PURE__*/_jsxs(View, {
301
- style: styles.statItem,
302
- children: [/*#__PURE__*/_jsx(Text, {
303
- style: styles.statValue,
304
- children: render.nativeTag
305
- }), /*#__PURE__*/_jsx(Text, {
306
- style: styles.statLabel,
307
- children: "tag"
308
- })]
309
- })]
310
- }), hasMeasurements && /*#__PURE__*/_jsxs(View, {
311
- style: styles.measurementsRow,
312
- children: [/*#__PURE__*/_jsxs(View, {
313
- style: styles.measurementItem,
314
- children: [/*#__PURE__*/_jsx(Text, {
315
- style: styles.measurementLabel,
316
- children: "x"
317
- }), /*#__PURE__*/_jsx(Text, {
318
- style: styles.measurementValue,
319
- children: Math.round(render.measurements.x)
320
- })]
321
- }), /*#__PURE__*/_jsxs(View, {
322
- style: styles.measurementItem,
323
- children: [/*#__PURE__*/_jsx(Text, {
324
- style: styles.measurementLabel,
325
- children: "y"
326
- }), /*#__PURE__*/_jsx(Text, {
327
- style: styles.measurementValue,
328
- children: Math.round(render.measurements.y)
329
- })]
330
- }), /*#__PURE__*/_jsxs(View, {
331
- style: styles.measurementItem,
332
- children: [/*#__PURE__*/_jsx(Text, {
333
- style: styles.measurementLabel,
334
- children: "w"
335
- }), /*#__PURE__*/_jsx(Text, {
336
- style: styles.measurementValue,
337
- children: Math.round(render.measurements.width)
338
- })]
339
- }), /*#__PURE__*/_jsxs(View, {
340
- style: styles.measurementItem,
341
- children: [/*#__PURE__*/_jsx(Text, {
342
- style: styles.measurementLabel,
343
- children: "h"
344
- }), /*#__PURE__*/_jsx(Text, {
345
- style: styles.measurementValue,
346
- children: Math.round(render.measurements.height)
347
- })]
348
- })]
349
- })]
350
- });
351
- }
352
-
353
- /**
354
- * DetailRow - Single row for identifier display
355
- */
356
- function DetailRow({
357
- label,
358
- value
359
- }) {
360
- return /*#__PURE__*/_jsxs(View, {
361
- style: styles.detailRow,
362
- children: [/*#__PURE__*/_jsx(Text, {
363
- style: styles.detailLabel,
364
- children: label
365
- }), /*#__PURE__*/_jsx(Text, {
366
- style: styles.detailValue,
367
- numberOfLines: 1,
368
- children: value
369
- })]
370
- });
371
- }
372
-
373
- /**
374
- * QuickActionsSection - Quick filter actions for the component
375
- * Users select a filter option, then use action buttons to include/exclude
376
- */
377
- function QuickActionsSection({
378
- render,
379
- onAddFilter
380
- }) {
381
- const [selectedIndex, setSelectedIndex] = useState(null);
382
-
383
- // Build list of available filter options (most specific to most general)
384
- const filterOptions = useMemo(() => {
385
- const options = [];
386
-
387
- // Most specific first
388
- if (render.nativeID) {
389
- options.push({
390
- type: "nativeID",
391
- value: render.nativeID,
392
- label: "nativeID"
393
- });
394
- }
395
- if (render.testID) {
396
- options.push({
397
- type: "testID",
398
- value: render.testID,
399
- label: "testID"
400
- });
401
- }
402
- if (render.accessibilityLabel) {
403
- options.push({
404
- type: "accessibilityLabel",
405
- value: render.accessibilityLabel,
406
- label: "a11y"
407
- });
408
- }
409
- if (render.componentName) {
410
- options.push({
411
- type: "component",
412
- value: render.componentName,
413
- label: "component"
414
- });
415
- }
416
- // Most general last (always available)
417
- options.push({
418
- type: "viewType",
419
- value: render.viewType,
420
- label: "viewType"
421
- });
422
- return options;
423
- }, [render]);
424
- const selectedOption = selectedIndex !== null ? filterOptions[selectedIndex] : null;
425
- const handleSelectOption = useCallback(index => {
426
- setSelectedIndex(prev => prev === index ? null : index);
427
- }, []);
428
- const handleInclude = useCallback(() => {
429
- if (selectedOption) {
430
- onAddFilter({
431
- type: selectedOption.type,
432
- value: selectedOption.value
433
- }, "include");
434
- setSelectedIndex(null);
435
- }
436
- }, [selectedOption, onAddFilter]);
437
- const handleExclude = useCallback(() => {
438
- if (selectedOption) {
439
- onAddFilter({
440
- type: selectedOption.type,
441
- value: selectedOption.value
442
- }, "exclude");
443
- setSelectedIndex(null);
444
- }
445
- }, [selectedOption, onAddFilter]);
446
- return /*#__PURE__*/_jsxs(View, {
447
- style: styles.quickActionsSection,
448
- children: [/*#__PURE__*/_jsx(Text, {
449
- style: styles.quickActionsTitle,
450
- children: "Quick Filters"
451
- }), /*#__PURE__*/_jsx(View, {
452
- style: styles.filterOptionsList,
453
- children: filterOptions.map((option, index) => /*#__PURE__*/_jsx(FilterOptionCard, {
454
- label: option.label,
455
- value: option.value,
456
- isSelected: selectedIndex === index,
457
- onSelect: () => handleSelectOption(index)
458
- }, option.type))
459
- }), /*#__PURE__*/_jsxs(View, {
460
- style: styles.filterActionButtons,
461
- children: [/*#__PURE__*/_jsxs(TouchableOpacity, {
462
- style: [styles.filterActionButton, styles.filterActionButtonInclude, !selectedOption && styles.filterActionButtonDisabled],
463
- onPress: handleInclude,
464
- disabled: !selectedOption,
465
- activeOpacity: 0.7,
466
- children: [/*#__PURE__*/_jsx(PlusIcon, {
467
- size: 14,
468
- color: selectedOption ? buoyColors.success : buoyColors.textMuted
469
- }), /*#__PURE__*/_jsx(Text, {
470
- style: [styles.filterActionButtonText, {
471
- color: selectedOption ? buoyColors.success : buoyColors.textMuted
472
- }],
473
- children: "Only Show This"
474
- })]
475
- }), /*#__PURE__*/_jsxs(TouchableOpacity, {
476
- style: [styles.filterActionButton, styles.filterActionButtonExclude, !selectedOption && styles.filterActionButtonDisabled],
477
- onPress: handleExclude,
478
- disabled: !selectedOption,
479
- activeOpacity: 0.7,
480
- children: [/*#__PURE__*/_jsx(MinusIcon, {
481
- size: 14,
482
- color: selectedOption ? buoyColors.error : buoyColors.textMuted
483
- }), /*#__PURE__*/_jsx(Text, {
484
- style: [styles.filterActionButtonText, {
485
- color: selectedOption ? buoyColors.error : buoyColors.textMuted
486
- }],
487
- children: "Hide This"
488
- })]
489
- })]
490
- })]
491
- });
492
- }
493
-
494
- /**
495
- * FilterOptionCard - A selectable filter option card
496
- */
497
- function FilterOptionCard({
498
- label,
499
- value,
500
- isSelected,
501
- onSelect
502
- }) {
503
- return /*#__PURE__*/_jsxs(TouchableOpacity, {
504
- style: [styles.filterOptionCard, isSelected && styles.filterOptionCardSelected],
505
- onPress: onSelect,
506
- activeOpacity: 0.7,
507
- children: [/*#__PURE__*/_jsx(Text, {
508
- style: [styles.filterOptionLabel, isSelected && styles.filterOptionLabelSelected],
509
- children: label
510
- }), /*#__PURE__*/_jsx(Text, {
511
- style: [styles.filterOptionValue, isSelected && styles.filterOptionValueSelected],
512
- numberOfLines: 1,
513
- children: value
514
- })]
515
- });
516
- }
517
- const styles = StyleSheet.create({
518
- container: {
519
- flex: 1,
520
- backgroundColor: buoyColors.base
521
- },
522
- // Header
523
- header: {
524
- flexDirection: "row",
525
- alignItems: "center",
526
- justifyContent: "center",
527
- gap: 12,
528
- padding: 16,
529
- paddingBottom: 0
530
- },
531
- // ScrollView
532
- scrollView: {
533
- flex: 1
534
- },
535
- scrollContent: {
536
- padding: 16,
537
- paddingTop: 12,
538
- paddingBottom: 80,
539
- gap: 12
540
- },
541
- headerLeft: {
542
- flex: 1,
543
- flexDirection: "row",
544
- alignItems: "center",
545
- justifyContent: "center",
546
- gap: 10
547
- },
548
- componentName: {
549
- fontSize: 18,
550
- fontWeight: "700",
551
- color: buoyColors.text,
552
- flexShrink: 1
553
- },
554
- nativeTypeBadge: {
555
- backgroundColor: buoyColors.input,
556
- paddingVertical: 3,
557
- paddingHorizontal: 8,
558
- borderRadius: 4
559
- },
560
- nativeTypeText: {
561
- fontSize: 11,
562
- fontWeight: "600",
563
- color: buoyColors.textMuted,
564
- fontFamily: "monospace"
565
- },
566
- // Answer Card
567
- answerCard: {
568
- backgroundColor: buoyColors.card,
569
- borderRadius: 8,
570
- borderWidth: 1,
571
- borderColor: buoyColors.border,
572
- padding: 12,
573
- gap: 6
574
- },
575
- causeBadgeRow: {
576
- flexDirection: "row",
577
- alignItems: "center",
578
- gap: 8
579
- },
580
- causeBadgeLarge: {
581
- paddingVertical: 4,
582
- paddingHorizontal: 10,
583
- borderRadius: 4
584
- },
585
- causeBadgeLargeText: {
586
- fontSize: 11,
587
- fontWeight: "700",
588
- letterSpacing: 0.5
589
- },
590
- causeLabel: {
591
- fontSize: 12,
592
- color: buoyColors.textSecondary,
593
- fontWeight: "500"
594
- },
595
- hookChangesContainer: {
596
- gap: 6
597
- },
598
- hookDiffContainer: {
599
- backgroundColor: buoyColors.input,
600
- borderRadius: 6,
601
- overflow: "hidden"
602
- },
603
- propsChangesContainer: {
604
- flexDirection: "row",
605
- flexWrap: "wrap",
606
- gap: 4
607
- },
608
- propChangeChip: {
609
- backgroundColor: buoyColors.input,
610
- paddingVertical: 2,
611
- paddingHorizontal: 6,
612
- borderRadius: 4
613
- },
614
- propChangeText: {
615
- fontSize: 11,
616
- color: buoyColors.text,
617
- fontFamily: "monospace"
618
- },
619
- // Details Section
620
- detailsSection: {
621
- gap: 10
622
- },
623
- detailsCard: {
624
- backgroundColor: buoyColors.card,
625
- borderRadius: 8,
626
- borderWidth: 1,
627
- borderColor: buoyColors.border,
628
- padding: 12,
629
- gap: 6
630
- },
631
- detailsCardTitle: {
632
- fontSize: 10,
633
- fontWeight: "600",
634
- color: buoyColors.textMuted,
635
- letterSpacing: 0.5,
636
- textTransform: "uppercase",
637
- marginBottom: 4
638
- },
639
- detailRow: {
640
- flexDirection: "row",
641
- alignItems: "center",
642
- gap: 8
643
- },
644
- detailLabel: {
645
- fontSize: 11,
646
- fontWeight: "600",
647
- color: buoyColors.textSecondary,
648
- minWidth: 55
649
- },
650
- detailValue: {
651
- fontSize: 12,
652
- color: buoyColors.text,
653
- fontFamily: "monospace",
654
- flex: 1
655
- },
656
- // Stats Row
657
- statsRow: {
658
- flexDirection: "row",
659
- alignItems: "center",
660
- justifyContent: "center",
661
- backgroundColor: buoyColors.card,
662
- borderRadius: 8,
663
- borderWidth: 1,
664
- borderColor: buoyColors.border,
665
- paddingVertical: 10,
666
- paddingHorizontal: 16
667
- },
668
- statItem: {
669
- flex: 1,
670
- alignItems: "center"
671
- },
672
- statValue: {
673
- fontSize: 16,
674
- fontWeight: "700",
675
- color: buoyColors.text,
676
- fontFamily: "monospace"
677
- },
678
- statLabel: {
679
- fontSize: 10,
680
- color: buoyColors.textMuted,
681
- marginTop: 2
682
- },
683
- statDivider: {
684
- width: 1,
685
- height: 24,
686
- backgroundColor: buoyColors.border,
687
- marginHorizontal: 12
688
- },
689
- // Measurements Row
690
- measurementsRow: {
691
- flexDirection: "row",
692
- alignItems: "center",
693
- justifyContent: "space-around",
694
- backgroundColor: buoyColors.card,
695
- borderRadius: 8,
696
- borderWidth: 1,
697
- borderColor: buoyColors.border,
698
- paddingVertical: 8,
699
- paddingHorizontal: 12
700
- },
701
- measurementItem: {
702
- flexDirection: "row",
703
- alignItems: "baseline",
704
- gap: 4
705
- },
706
- measurementLabel: {
707
- fontSize: 10,
708
- fontWeight: "600",
709
- color: buoyColors.textMuted,
710
- textTransform: "uppercase"
711
- },
712
- measurementValue: {
713
- fontSize: 12,
714
- fontWeight: "600",
715
- color: buoyColors.text,
716
- fontFamily: "monospace"
717
- },
718
- // Quick Actions Section
719
- quickActionsSection: {
720
- backgroundColor: buoyColors.card,
721
- borderRadius: 8,
722
- borderWidth: 1,
723
- borderColor: buoyColors.border,
724
- padding: 12,
725
- gap: 10
726
- },
727
- quickActionsTitle: {
728
- fontSize: 10,
729
- fontWeight: "600",
730
- color: buoyColors.textMuted,
731
- letterSpacing: 0.5,
732
- textTransform: "uppercase",
733
- marginBottom: 2
734
- },
735
- filterOptionsList: {
736
- gap: 6
737
- },
738
- filterOptionCard: {
739
- flexDirection: "row",
740
- alignItems: "center",
741
- backgroundColor: buoyColors.input,
742
- borderRadius: 6,
743
- paddingVertical: 10,
744
- paddingHorizontal: 12,
745
- borderWidth: 1,
746
- borderColor: "transparent",
747
- gap: 10
748
- },
749
- filterOptionCardSelected: {
750
- borderColor: buoyColors.success,
751
- backgroundColor: buoyColors.success + "15"
752
- },
753
- filterOptionLabel: {
754
- fontSize: 10,
755
- fontWeight: "600",
756
- color: buoyColors.textMuted,
757
- minWidth: 70
758
- },
759
- filterOptionLabelSelected: {
760
- color: buoyColors.success
761
- },
762
- filterOptionValue: {
763
- fontSize: 12,
764
- color: buoyColors.text,
765
- fontFamily: "monospace",
766
- flex: 1
767
- },
768
- filterOptionValueSelected: {
769
- color: buoyColors.text
770
- },
771
- filterActionButtons: {
772
- flexDirection: "row",
773
- gap: 8,
774
- marginTop: 12
775
- },
776
- filterActionButton: {
777
- flexDirection: "row",
778
- alignItems: "center",
779
- justifyContent: "center",
780
- gap: 4,
781
- paddingVertical: 8,
782
- paddingHorizontal: 10,
783
- borderRadius: 6,
784
- borderWidth: 1
785
- },
786
- filterActionButtonInclude: {
787
- backgroundColor: buoyColors.success + "15",
788
- borderColor: buoyColors.success + "40"
789
- },
790
- filterActionButtonExclude: {
791
- backgroundColor: buoyColors.error + "15",
792
- borderColor: buoyColors.error + "40"
793
- },
794
- filterActionButtonDisabled: {
795
- backgroundColor: buoyColors.input,
796
- borderColor: buoyColors.border,
797
- opacity: 0.5
798
- },
799
- filterActionButtonText: {
800
- fontSize: 11,
801
- fontWeight: "600"
802
- },
803
- // Locked Banner
804
- lockedBanner: {
805
- flexDirection: "row",
806
- alignItems: "center",
807
- justifyContent: "center",
808
- backgroundColor: buoyColors.card,
809
- borderRadius: 8,
810
- borderWidth: 1,
811
- borderColor: buoyColors.warning + "40",
812
- paddingVertical: 12,
813
- paddingHorizontal: 16,
814
- gap: 8
815
- },
816
- lockedBannerText: {
817
- color: buoyColors.warning,
818
- fontSize: 13,
819
- fontWeight: "600"
820
- },
821
- lockedBannerSubtext: {
822
- color: buoyColors.textMuted,
823
- fontSize: 12
824
- }
825
- });
826
- export default RenderDetailView;
1
+ "use strict";import React,{useMemo,useState,useCallback}from"react";import{View,Text,TouchableOpacity,ScrollView,StyleSheet}from"react-native";import{CopyButton,formatRelativeTime,PlusIcon,MinusIcon,EventStepperFooter,Lock,buoyColors}from"@buoy-gg/shared-ui";import{TreeDiffViewer}from"@buoy-gg/shared-ui/dataViewer";import{CAUSE_CONFIG,COMPONENT_CAUSE_CONFIG}from"./RenderCauseBadge";import{jsx as _jsx,jsxs as _jsxs}from"react/jsx-runtime";function formatRenderDetailForClipboard(e){const t=[];if(t.push(`${e.componentName||e.displayName} (${e.viewType})`),t.push(`Renders: ${e.renderCount}`),e.lastRenderCause){const o=e.lastRenderCause;if(o.componentCause?t.push(`Cause: ${o.componentCause.toUpperCase()} → ${o.type.toUpperCase()}`):t.push(`Cause: ${o.type.toUpperCase()}`),o.hookChanges?.length)for(const e of o.hookChanges)t.push(` ${e.type}[${e.index}]: ${e.previousValue} → ${e.currentValue}`)}if(e.renderHistory?.length){t.push(`\nHistory (${e.renderHistory.length} events):`);for(const o of e.renderHistory){const e=o.cause.componentCause?`${o.cause.componentCause.toUpperCase()} → ${o.cause.type.toUpperCase()}`:o.cause.type.toUpperCase();t.push(` #${o.renderNumber}: ${e}`)}}return t.join("\n")}const FREE_TIER_EVENT_LIMIT=5;export function RenderDetailView({render:e,disableInternalFooter:t=!1,selectedEventIndex:o,onEventIndexChange:s,onAddFilter:r,isPro:l=!1}){const[n,i]=useState(0),a=o??n,d=s??i,c=useMemo(()=>e.renderHistory&&0!==e.renderHistory.length?[...e.renderHistory].sort((e,t)=>e.timestamp-t.timestamp):[],[e.renderHistory]),u=c.length,y=c[a],p=useMemo(()=>l?0:Math.max(0,u-5),[l,u]),b=y?.cause||e.lastRenderCause,x=useCallback(()=>{a>0&&d(a-1)},[a,d]),C=useCallback(()=>{const e=l?u-1:Math.min(4,u-1);a<e&&d(a+1)},[a,u,d,l]),h=useMemo(()=>formatRenderDetailForClipboard(e),[e]),m=e.componentName||e.displayName,g=e.viewType,f=e.lastRenderTime-e.firstRenderTime,j=f>0?(e.renderCount/(f/1e3)).toFixed(1):e.renderCount.toString(),_=!t&&u>1;return _jsxs(View,{style:styles.container,children:[_jsxs(View,{style:styles.header,children:[_jsxs(View,{style:styles.headerLeft,children:[_jsx(Text,{style:styles.componentName,numberOfLines:1,children:m}),_jsx(View,{style:styles.nativeTypeBadge,children:_jsx(Text,{style:styles.nativeTypeText,children:g})})]}),_jsx(CopyButton,{value:h,size:14})]}),_jsxs(ScrollView,{style:styles.scrollView,contentContainerStyle:[styles.scrollContent,_&&{paddingBottom:100}],showsVerticalScrollIndicator:!1,children:[b&&_jsx(AnswerCard,{cause:b,renderNumber:y?.renderNumber}),_jsx(DetailsSection,{render:e,rendersPerSec:j}),p>0&&_jsxs(View,{style:styles.lockedBanner,children:[_jsx(Lock,{size:14,color:buoyColors.warning}),_jsxs(Text,{style:styles.lockedBannerText,children:[p," ",1===p?"event":"events"," hidden"]}),_jsx(Text,{style:styles.lockedBannerSubtext,children:"Upgrade to Pro"})]}),r&&_jsx(QuickActionsSection,{render:e,onAddFilter:r})]}),_&&_jsx(EventStepperFooter,{currentIndex:a,totalItems:u,onPrevious:x,onNext:C,itemLabel:"Render",subtitle:y?.timestamp?formatRelativeTime(new Date(y.timestamp)):void 0,applySafeAreaInset:!1,absolute:!0})]})}function AnswerCard({cause:e,renderNumber:t}){const o=e.componentCause||e.type,s=e.componentCause?COMPONENT_CAUSE_CONFIG[e.componentCause]:CAUSE_CONFIG[e.type],r=e.hookChanges&&e.hookChanges.length>0,l=e.changedKeys&&e.changedKeys.length>0;return _jsxs(View,{style:styles.answerCard,children:[_jsxs(View,{style:styles.causeBadgeRow,children:[_jsx(Text,{style:styles.causeLabel,children:"mount"===e.type?"First render":"parent"===o?"Triggered by":"Changed:"}),_jsx(View,{style:[styles.causeBadgeLarge,{backgroundColor:s.color+"20"}],children:_jsx(Text,{style:[styles.causeBadgeLargeText,{color:s.color}],children:s.label.toUpperCase()})})]}),r&&_jsx(View,{style:styles.hookChangesContainer,children:e.hookChanges.map((e,t)=>{const o=`${e.type}[${e.index}]`,s={[o]:e.previousValue},r={[o]:e.currentValue};return _jsx(View,{style:styles.hookDiffContainer,children:_jsx(TreeDiffViewer,{oldValue:s,newValue:r,theme:"dark",showUnchanged:!1})},t)})}),!r&&l&&_jsx(View,{style:styles.propsChangesContainer,children:e.changedKeys.filter(e=>!e.includes("(ref only)")).slice(0,5).map((e,t)=>_jsx(View,{style:styles.propChangeChip,children:_jsx(Text,{style:styles.propChangeText,children:e})},t))})]})}function DetailsSection({render:e,rendersPerSec:t}){const o=e.testID||e.nativeID||e.accessibilityLabel,s=e.measurements;return _jsxs(View,{style:styles.detailsSection,children:[o&&_jsxs(View,{style:styles.detailsCard,children:[_jsx(Text,{style:styles.detailsCardTitle,children:"Identifiers"}),e.testID&&_jsx(DetailRow,{label:"testID",value:e.testID}),e.nativeID&&_jsx(DetailRow,{label:"nativeID",value:e.nativeID}),e.accessibilityLabel&&_jsx(DetailRow,{label:"a11y",value:e.accessibilityLabel})]}),_jsxs(View,{style:styles.statsRow,children:[_jsxs(View,{style:styles.statItem,children:[_jsx(Text,{style:[styles.statValue,{color:e.color}],children:e.renderCount}),_jsx(Text,{style:styles.statLabel,children:"renders"})]}),_jsx(View,{style:styles.statDivider}),_jsxs(View,{style:styles.statItem,children:[_jsx(Text,{style:styles.statValue,children:t}),_jsx(Text,{style:styles.statLabel,children:"/sec"})]}),_jsx(View,{style:styles.statDivider}),_jsxs(View,{style:styles.statItem,children:[_jsx(Text,{style:styles.statValue,children:e.nativeTag}),_jsx(Text,{style:styles.statLabel,children:"tag"})]})]}),s&&_jsxs(View,{style:styles.measurementsRow,children:[_jsxs(View,{style:styles.measurementItem,children:[_jsx(Text,{style:styles.measurementLabel,children:"x"}),_jsx(Text,{style:styles.measurementValue,children:Math.round(e.measurements.x)})]}),_jsxs(View,{style:styles.measurementItem,children:[_jsx(Text,{style:styles.measurementLabel,children:"y"}),_jsx(Text,{style:styles.measurementValue,children:Math.round(e.measurements.y)})]}),_jsxs(View,{style:styles.measurementItem,children:[_jsx(Text,{style:styles.measurementLabel,children:"w"}),_jsx(Text,{style:styles.measurementValue,children:Math.round(e.measurements.width)})]}),_jsxs(View,{style:styles.measurementItem,children:[_jsx(Text,{style:styles.measurementLabel,children:"h"}),_jsx(Text,{style:styles.measurementValue,children:Math.round(e.measurements.height)})]})]})]})}function DetailRow({label:e,value:t}){return _jsxs(View,{style:styles.detailRow,children:[_jsx(Text,{style:styles.detailLabel,children:e}),_jsx(Text,{style:styles.detailValue,numberOfLines:1,children:t})]})}function QuickActionsSection({render:e,onAddFilter:t}){const[o,s]=useState(null),r=useMemo(()=>{const t=[];return e.nativeID&&t.push({type:"nativeID",value:e.nativeID,label:"nativeID"}),e.testID&&t.push({type:"testID",value:e.testID,label:"testID"}),e.accessibilityLabel&&t.push({type:"accessibilityLabel",value:e.accessibilityLabel,label:"a11y"}),e.componentName&&t.push({type:"component",value:e.componentName,label:"component"}),t.push({type:"viewType",value:e.viewType,label:"viewType"}),t},[e]),l=null!==o?r[o]:null,n=useCallback(e=>{s(t=>t===e?null:e)},[]),i=useCallback(()=>{l&&(t({type:l.type,value:l.value},"include"),s(null))},[l,t]),a=useCallback(()=>{l&&(t({type:l.type,value:l.value},"exclude"),s(null))},[l,t]);return _jsxs(View,{style:styles.quickActionsSection,children:[_jsx(Text,{style:styles.quickActionsTitle,children:"Quick Filters"}),_jsx(View,{style:styles.filterOptionsList,children:r.map((e,t)=>_jsx(FilterOptionCard,{label:e.label,value:e.value,isSelected:o===t,onSelect:()=>n(t)},e.type))}),_jsxs(View,{style:styles.filterActionButtons,children:[_jsxs(TouchableOpacity,{style:[styles.filterActionButton,styles.filterActionButtonInclude,!l&&styles.filterActionButtonDisabled],onPress:i,disabled:!l,activeOpacity:.7,children:[_jsx(PlusIcon,{size:14,color:l?buoyColors.success:buoyColors.textMuted}),_jsx(Text,{style:[styles.filterActionButtonText,{color:l?buoyColors.success:buoyColors.textMuted}],children:"Only Show This"})]}),_jsxs(TouchableOpacity,{style:[styles.filterActionButton,styles.filterActionButtonExclude,!l&&styles.filterActionButtonDisabled],onPress:a,disabled:!l,activeOpacity:.7,children:[_jsx(MinusIcon,{size:14,color:l?buoyColors.error:buoyColors.textMuted}),_jsx(Text,{style:[styles.filterActionButtonText,{color:l?buoyColors.error:buoyColors.textMuted}],children:"Hide This"})]})]})]})}function FilterOptionCard({label:e,value:t,isSelected:o,onSelect:s}){return _jsxs(TouchableOpacity,{style:[styles.filterOptionCard,o&&styles.filterOptionCardSelected],onPress:s,activeOpacity:.7,children:[_jsx(Text,{style:[styles.filterOptionLabel,o&&styles.filterOptionLabelSelected],children:e}),_jsx(Text,{style:[styles.filterOptionValue,o&&styles.filterOptionValueSelected],numberOfLines:1,children:t})]})}const styles=StyleSheet.create({container:{flex:1,backgroundColor:buoyColors.base},header:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:12,padding:16,paddingBottom:0},scrollView:{flex:1},scrollContent:{padding:16,paddingTop:12,paddingBottom:80,gap:12},headerLeft:{flex:1,flexDirection:"row",alignItems:"center",justifyContent:"center",gap:10},componentName:{fontSize:18,fontWeight:"700",color:buoyColors.text,flexShrink:1},nativeTypeBadge:{backgroundColor:buoyColors.input,paddingVertical:3,paddingHorizontal:8,borderRadius:4},nativeTypeText:{fontSize:11,fontWeight:"600",color:buoyColors.textMuted,fontFamily:"monospace"},answerCard:{backgroundColor:buoyColors.card,borderRadius:8,borderWidth:1,borderColor:buoyColors.border,padding:12,gap:6},causeBadgeRow:{flexDirection:"row",alignItems:"center",gap:8},causeBadgeLarge:{paddingVertical:4,paddingHorizontal:10,borderRadius:4},causeBadgeLargeText:{fontSize:11,fontWeight:"700",letterSpacing:.5},causeLabel:{fontSize:12,color:buoyColors.textSecondary,fontWeight:"500"},hookChangesContainer:{gap:6},hookDiffContainer:{backgroundColor:buoyColors.input,borderRadius:6,overflow:"hidden"},propsChangesContainer:{flexDirection:"row",flexWrap:"wrap",gap:4},propChangeChip:{backgroundColor:buoyColors.input,paddingVertical:2,paddingHorizontal:6,borderRadius:4},propChangeText:{fontSize:11,color:buoyColors.text,fontFamily:"monospace"},detailsSection:{gap:10},detailsCard:{backgroundColor:buoyColors.card,borderRadius:8,borderWidth:1,borderColor:buoyColors.border,padding:12,gap:6},detailsCardTitle:{fontSize:10,fontWeight:"600",color:buoyColors.textMuted,letterSpacing:.5,textTransform:"uppercase",marginBottom:4},detailRow:{flexDirection:"row",alignItems:"center",gap:8},detailLabel:{fontSize:11,fontWeight:"600",color:buoyColors.textSecondary,minWidth:55},detailValue:{fontSize:12,color:buoyColors.text,fontFamily:"monospace",flex:1},statsRow:{flexDirection:"row",alignItems:"center",justifyContent:"center",backgroundColor:buoyColors.card,borderRadius:8,borderWidth:1,borderColor:buoyColors.border,paddingVertical:10,paddingHorizontal:16},statItem:{flex:1,alignItems:"center"},statValue:{fontSize:16,fontWeight:"700",color:buoyColors.text,fontFamily:"monospace"},statLabel:{fontSize:10,color:buoyColors.textMuted,marginTop:2},statDivider:{width:1,height:24,backgroundColor:buoyColors.border,marginHorizontal:12},measurementsRow:{flexDirection:"row",alignItems:"center",justifyContent:"space-around",backgroundColor:buoyColors.card,borderRadius:8,borderWidth:1,borderColor:buoyColors.border,paddingVertical:8,paddingHorizontal:12},measurementItem:{flexDirection:"row",alignItems:"baseline",gap:4},measurementLabel:{fontSize:10,fontWeight:"600",color:buoyColors.textMuted,textTransform:"uppercase"},measurementValue:{fontSize:12,fontWeight:"600",color:buoyColors.text,fontFamily:"monospace"},quickActionsSection:{backgroundColor:buoyColors.card,borderRadius:8,borderWidth:1,borderColor:buoyColors.border,padding:12,gap:10},quickActionsTitle:{fontSize:10,fontWeight:"600",color:buoyColors.textMuted,letterSpacing:.5,textTransform:"uppercase",marginBottom:2},filterOptionsList:{gap:6},filterOptionCard:{flexDirection:"row",alignItems:"center",backgroundColor:buoyColors.input,borderRadius:6,paddingVertical:10,paddingHorizontal:12,borderWidth:1,borderColor:"transparent",gap:10},filterOptionCardSelected:{borderColor:buoyColors.success,backgroundColor:buoyColors.success+"15"},filterOptionLabel:{fontSize:10,fontWeight:"600",color:buoyColors.textMuted,minWidth:70},filterOptionLabelSelected:{color:buoyColors.success},filterOptionValue:{fontSize:12,color:buoyColors.text,fontFamily:"monospace",flex:1},filterOptionValueSelected:{color:buoyColors.text},filterActionButtons:{flexDirection:"row",gap:8,marginTop:12},filterActionButton:{flexDirection:"row",alignItems:"center",justifyContent:"center",gap:4,paddingVertical:8,paddingHorizontal:10,borderRadius:6,borderWidth:1},filterActionButtonInclude:{backgroundColor:buoyColors.success+"15",borderColor:buoyColors.success+"40"},filterActionButtonExclude:{backgroundColor:buoyColors.error+"15",borderColor:buoyColors.error+"40"},filterActionButtonDisabled:{backgroundColor:buoyColors.input,borderColor:buoyColors.border,opacity:.5},filterActionButtonText:{fontSize:11,fontWeight:"600"},lockedBanner:{flexDirection:"row",alignItems:"center",justifyContent:"center",backgroundColor:buoyColors.card,borderRadius:8,borderWidth:1,borderColor:buoyColors.warning+"40",paddingVertical:12,paddingHorizontal:16,gap:8},lockedBannerText:{color:buoyColors.warning,fontSize:13,fontWeight:"600"},lockedBannerSubtext:{color:buoyColors.textMuted,fontSize:12}});export default RenderDetailView;