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