@buoy-gg/highlight-updates 7.0.38 → 7.0.40

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