@buoy-gg/highlight-updates 2.1.10 → 2.1.11

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