@buoy-gg/highlight-updates 2.1.9 → 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,1365 @@
1
- "use strict";import React,{useState,useCallback}from"react";import{View,Text,TouchableOpacity,TextInput,StyleSheet,ScrollView,Modal,Pressable,Switch}from"react-native";import{Eye,Filter,Plus,X,Box,Settings,Hash,SectionHeader,buoyColors}from"@buoy-gg/shared-ui";import{IdentifierBadge,IDENTIFIER_CONFIG}from"./IdentifierBadge";import{jsx as _jsx,jsxs as _jsxs,Fragment as _Fragment}from"react/jsx-runtime";const getFilterConfig=e=>IDENTIFIER_CONFIG[e],FILTER_TYPES=["any","viewType","testID","nativeID","component","accessibilityLabel"];function TypePicker({onSelect:e,onCancel:t}){return _jsxs(View,{nativeID:"__rn_buoy__type-picker",style:styles.typePicker,children:[_jsx(View,{style:styles.typePickerRow,children:FILTER_TYPES.map(t=>{const o=getFilterConfig(t),s=o.icon;return _jsxs(TouchableOpacity,{style:[styles.typeOption,{backgroundColor:o.color+"15",borderColor:o.color+"40"}],onPress:()=>e(t),children:[_jsx(s,{size:14,color:o.color}),_jsx(Text,{style:[styles.typeOptionText,{color:o.color}],children:o.label})]},t)})}),_jsx(TouchableOpacity,{onPress:t,style:styles.typePickerCancel,children:_jsx(X,{size:16,color:buoyColors.textMuted})})]})}function PatternInput({type:e,onSubmit:t,onCancel:o}){const[s,n]=useState(""),l=getFilterConfig(e),r=()=>{s.trim()&&t(s.trim())};return _jsxs(View,{nativeID:"__rn_buoy__pattern-input",style:styles.patternInputContainer,children:[_jsx(IdentifierBadge,{type:e,value:"",badgeOnly:!0,compact:!0}),_jsx(TextInput,{value:s,onChangeText:n,onSubmitEditing:r,placeholder:"Enter pattern...",placeholderTextColor:buoyColors.textMuted,style:styles.patternInput,autoFocus:!0,returnKeyType:"done",autoCorrect:!1,autoCapitalize:"none"}),s.trim()&&_jsx(TouchableOpacity,{onPress:r,style:[styles.addPatternButton,{backgroundColor:l.color+"20"}],children:_jsx(Text,{style:[styles.addPatternButtonText,{color:l.color}],children:"Add"})}),_jsx(TouchableOpacity,{onPress:o,style:styles.cancelButton,children:_jsx(X,{size:16,color:buoyColors.textMuted})})]})}function PatternChip({pattern:e,onRemove:t}){const o=getFilterConfig(e.type);return _jsxs(TouchableOpacity,{style:[styles.patternChip,{borderColor:o.color+"40"}],onPress:t,activeOpacity:.7,children:[_jsx(View,{style:[styles.patternChipBadge,{backgroundColor:o.color+"20"}],children:_jsx(Text,{style:[styles.patternChipBadgeText,{color:o.color}],children:o.shortLabel})}),_jsx(Text,{style:styles.patternChipValue,numberOfLines:1,children:e.value}),_jsx(X,{size:12,color:buoyColors.textMuted,style:styles.patternChipX})]})}const ALL_CATEGORY_CONFIG={label:"All",shortLabel:"All",color:buoyColors.textSecondary,icon:Box};function DetectedCategoryBadge({filterType:e,count:t,isSelected:o,onPress:s}){const n="all"===e?ALL_CATEGORY_CONFIG:getFilterConfig(e);return _jsxs(TouchableOpacity,{style:[styles.categoryBadge,{backgroundColor:n.color+"15",borderColor:o?n.color:n.color+"40",borderWidth:o?2:1}],onPress:s,children:[_jsx(n.icon,{size:12,color:n.color}),_jsx(Text,{style:[styles.categoryBadgeText,{color:n.color}],children:n.label}),_jsx(View,{style:[styles.categoryBadgeCountBubble,{backgroundColor:n.color+"25"}],children:_jsx(Text,{style:[styles.categoryBadgeCount,{color:n.color}],children:t})})]})}const BATCH_SIZE_PRESETS=[{value:20,label:"20"},{value:50,label:"50"},{value:100,label:"100"},{value:150,label:"150"},{value:250,label:"250"},{value:500,label:"500"}],DEBUG_LOG_LEVEL_PRESETS=[{value:"off",label:"Off",description:"No debug logging"},{value:"minimal",label:"Minimal",description:"Only hook value changes"},{value:"verbose",label:"Verbose",description:"Component + cause + changes"},{value:"all",label:"All",description:"Full fiber dump"}];export function HighlightFilterView({filters:e,onFilterChange:t,settings:o,onSettingsChange:s,availableProps:n,activeTab:l}){const[r,i]=useState(!1),[a,c]=useState(!1),[d,u]=useState(null),[y,p]=useState(null),[g,x]=useState("all"),[h,b]=useState(null),C=(e=>{switch(e){case"viewType":return n.viewTypes.map(e=>({value:e,type:"viewType"}));case"testID":return n.testIDs.map(e=>({value:e,type:"testID"}));case"nativeID":return n.nativeIDs.map(e=>({value:e,type:"nativeID"}));case"component":return n.componentNames.map(e=>({value:e,type:"component"}));case"accessibilityLabel":return n.accessibilityLabels.map(e=>({value:e,type:"accessibilityLabel"}));default:return[...n.viewTypes.map(e=>({value:e,type:"viewType"})),...n.testIDs.map(e=>({value:e,type:"testID"})),...n.nativeIDs.map(e=>({value:e,type:"nativeID"})),...n.componentNames.map(e=>({value:e,type:"component"})),...n.accessibilityLabels.map(e=>({value:e,type:"accessibilityLabel"}))]}})(g),_=n.viewTypes.length+n.testIDs.length+n.nativeIDs.length+n.componentNames.length+n.accessibilityLabels.length,m=useCallback((o,s)=>{const n=[...e.includePatterns,{type:o,value:s}];t({includePatterns:n}),u(null)},[e.includePatterns,t]),T=useCallback((o,s)=>{const n=[...e.excludePatterns,{type:o,value:s}];t({excludePatterns:n}),p(null)},[e.excludePatterns,t]),j=useCallback(o=>{const s=e.includePatterns.filter((e,t)=>t!==o);t({includePatterns:s})},[e.includePatterns,t]),S=useCallback(o=>{const s=e.excludePatterns.filter((e,t)=>t!==o);t({excludePatterns:s})},[e.excludePatterns,t]),f=useCallback((e,t)=>{b({type:e,value:t})},[]),v=useCallback(()=>{h&&(m(h.type,h.value),b(null))},[h,m]),w=useCallback(()=>{h&&(T(h.type,h.value),b(null))},[h,T]);return _jsx(View,{style:styles.container,children:_jsx(ScrollView,{nativeID:"__rn_buoy__filter-view",style:styles.scrollView,contentContainerStyle:styles.scrollContent,showsVerticalScrollIndicator:!1,children:"filters"===l?_jsxs(_Fragment,{children:[_jsxs(View,{style:styles.section,children:[_jsxs(SectionHeader,{children:[_jsx(SectionHeader.Icon,{icon:Eye,color:buoyColors.success,size:12}),_jsx(SectionHeader.Title,{children:"INCLUDE ONLY"}),e.includePatterns.length>0&&_jsx(SectionHeader.Badge,{count:e.includePatterns.length,color:buoyColors.success})]}),_jsx(Text,{style:styles.sectionDescription,children:"Show only components matching these patterns. If any are set, components must match at least one."}),e.includePatterns.length>0&&_jsx(View,{style:styles.patternChips,children:e.includePatterns.map((e,t)=>_jsx(PatternChip,{pattern:e,onRemove:()=>j(t)},`${e.type}-${e.value}-${t}`))}),_jsx(View,{style:styles.addPatternRow,children:r?_jsx(TypePicker,{onSelect:e=>{i(!1),u(e)},onCancel:()=>i(!1)}):d?_jsx(PatternInput,{type:d,onSubmit:e=>m(d,e),onCancel:()=>u(null)}):_jsxs(TouchableOpacity,{style:[styles.addButton,{borderColor:buoyColors.success+"40"}],onPress:()=>i(!0),children:[_jsx(Plus,{size:14,color:buoyColors.success}),_jsx(Text,{style:[styles.addButtonText,{color:buoyColors.success}],children:"Add include pattern"})]})})]}),_jsxs(View,{style:styles.section,children:[_jsxs(SectionHeader,{children:[_jsx(SectionHeader.Icon,{icon:Filter,color:buoyColors.primary,size:12}),_jsx(SectionHeader.Title,{children:"EXCLUDE"}),e.excludePatterns.length>0&&_jsx(SectionHeader.Badge,{count:e.excludePatterns.length,color:buoyColors.primary})]}),_jsx(Text,{style:styles.sectionDescription,children:"Hide components matching these patterns from the list."}),e.excludePatterns.length>0&&_jsx(View,{style:styles.patternChips,children:e.excludePatterns.map((e,t)=>_jsx(PatternChip,{pattern:e,onRemove:()=>S(t)},`${e.type}-${e.value}-${t}`))}),_jsx(View,{style:styles.addPatternRow,children:a?_jsx(TypePicker,{onSelect:e=>{c(!1),p(e)},onCancel:()=>c(!1)}):y?_jsx(PatternInput,{type:y,onSubmit:e=>T(y,e),onCancel:()=>p(null)}):_jsxs(TouchableOpacity,{style:[styles.addButton,{borderColor:buoyColors.primary+"40"}],onPress:()=>c(!0),children:[_jsx(Plus,{size:14,color:buoyColors.primary}),_jsx(Text,{style:[styles.addButtonText,{color:buoyColors.primary}],children:"Add exclude pattern"})]})})]}),_jsxs(View,{style:styles.section,children:[_jsxs(SectionHeader,{children:[_jsx(SectionHeader.Icon,{icon:Hash,color:buoyColors.warning,size:12}),_jsx(SectionHeader.Title,{children:"RENDER COUNT RANGE"}),(void 0!==e.minRenderCount||void 0!==e.maxRenderCount)&&_jsx(SectionHeader.Badge,{count:1,color:buoyColors.warning})]}),_jsx(Text,{style:styles.sectionDescription,children:"Show only components with render count in a specific range."}),_jsxs(View,{nativeID:"__rn_buoy__render-count-range",style:styles.renderCountRangeContainer,children:[_jsxs(View,{style:styles.renderCountInputRow,children:[_jsxs(View,{style:styles.renderCountInputGroup,children:[_jsx(Text,{style:styles.renderCountLabel,children:"Min"}),_jsx(TextInput,{value:void 0!==e.minRenderCount?String(e.minRenderCount):"",onChangeText:e=>{const o=parseInt(e,10);""===e||void 0===e?t({minRenderCount:void 0}):!isNaN(o)&&o>=0&&t({minRenderCount:o})},placeholder:"0",placeholderTextColor:buoyColors.textMuted,style:styles.renderCountInput,keyboardType:"number-pad",returnKeyType:"done"})]}),_jsx(Text,{style:styles.renderCountSeparator,children:"to"}),_jsxs(View,{style:styles.renderCountInputGroup,children:[_jsx(Text,{style:styles.renderCountLabel,children:"Max"}),_jsx(TextInput,{value:void 0!==e.maxRenderCount?String(e.maxRenderCount):"",onChangeText:e=>{const o=parseInt(e,10);""===e||void 0===e?t({maxRenderCount:void 0}):!isNaN(o)&&o>=0&&t({maxRenderCount:o})},placeholder:"∞",placeholderTextColor:buoyColors.textMuted,style:styles.renderCountInput,keyboardType:"number-pad",returnKeyType:"done"})]})]}),(void 0!==e.minRenderCount||void 0!==e.maxRenderCount)&&_jsxs(TouchableOpacity,{style:styles.clearRangeButton,onPress:()=>t({minRenderCount:void 0,maxRenderCount:void 0}),children:[_jsx(X,{size:12,color:buoyColors.warning}),_jsx(Text,{style:styles.clearRangeButtonText,children:"Clear Range"})]})]})]}),_jsxs(View,{style:styles.section,children:[_jsxs(SectionHeader,{children:[_jsx(SectionHeader.Icon,{icon:Box,color:buoyColors.textSecondary,size:12}),_jsx(SectionHeader.Title,{children:"DETECTED ITEMS"})]}),_jsx(Text,{style:styles.sectionDescription,children:"Tap an item to quickly add it as an exclude pattern."}),_jsxs(ScrollView,{horizontal:!0,showsHorizontalScrollIndicator:!1,style:styles.categoryBadgeScroll,contentContainerStyle:styles.categoryBadgeScrollContent,children:[_>0&&_jsx(DetectedCategoryBadge,{filterType:"all",count:_,isSelected:"all"===g,onPress:()=>x("all")}),n.viewTypes.length>0&&_jsx(DetectedCategoryBadge,{filterType:"viewType",count:n.viewTypes.length,isSelected:"viewType"===g,onPress:()=>x("viewType")}),n.testIDs.length>0&&_jsx(DetectedCategoryBadge,{filterType:"testID",count:n.testIDs.length,isSelected:"testID"===g,onPress:()=>x("testID")}),n.nativeIDs.length>0&&_jsx(DetectedCategoryBadge,{filterType:"nativeID",count:n.nativeIDs.length,isSelected:"nativeID"===g,onPress:()=>x("nativeID")}),n.componentNames.length>0&&_jsx(DetectedCategoryBadge,{filterType:"component",count:n.componentNames.length,isSelected:"component"===g,onPress:()=>x("component")}),n.accessibilityLabels.length>0&&_jsx(DetectedCategoryBadge,{filterType:"accessibilityLabel",count:n.accessibilityLabels.length,isSelected:"accessibilityLabel"===g,onPress:()=>x("accessibilityLabel")})]}),_jsx(View,{nativeID:"__rn_buoy__detected-items",style:styles.detectedItemsContainer,children:C.length>0?_jsx(ScrollView,{style:styles.detectedItemsScroll,contentContainerStyle:styles.detectedItems,nestedScrollEnabled:!0,showsVerticalScrollIndicator:!0,children:C.map(e=>{const t=getFilterConfig(e.type);return _jsx(TouchableOpacity,{style:[styles.detectedItem,{borderColor:t.color+"40"}],onPress:()=>f(e.type,e.value),children:"all"===g?_jsx(IdentifierBadge,{type:e.type,value:e.value,compact:!0,shortLabel:!0}):_jsx(Text,{style:styles.detectedItemText,numberOfLines:1,children:e.value})},`${e.type}-${e.value}`)})}):_jsx(Text,{style:styles.emptyText,children:"No items detected yet. Start tracking to see components here."})})]}),_jsx(Modal,{visible:null!==h,transparent:!0,animationType:"fade",onRequestClose:()=>b(null),children:_jsx(Pressable,{style:styles.modalOverlay,onPress:()=>b(null),children:_jsx(View,{style:styles.actionPopup,children:h&&_jsxs(_Fragment,{children:[_jsx(View,{style:styles.actionPopupHeader,children:_jsx(IdentifierBadge,{type:h.type,value:h.value,compact:!0,shortLabel:!0})}),_jsxs(View,{style:styles.actionPopupButtons,children:[_jsxs(TouchableOpacity,{style:[styles.actionPopupButton,styles.actionPopupInclude],onPress:v,children:[_jsx(Eye,{size:16,color:buoyColors.success}),_jsx(Text,{style:[styles.actionPopupButtonText,{color:buoyColors.success}],children:"Include Only"})]}),_jsxs(TouchableOpacity,{style:[styles.actionPopupButton,styles.actionPopupExclude],onPress:w,children:[_jsx(Filter,{size:16,color:buoyColors.primary}),_jsx(Text,{style:[styles.actionPopupButtonText,{color:buoyColors.primary}],children:"Exclude"})]})]}),_jsx(TouchableOpacity,{style:styles.actionPopupCancel,onPress:()=>b(null),children:_jsx(Text,{style:styles.actionPopupCancelText,children:"Cancel"})})]})})})}),_jsxs(View,{style:styles.section,children:[_jsxs(SectionHeader,{children:[_jsx(SectionHeader.Icon,{icon:Filter,color:buoyColors.textMuted,size:12}),_jsx(SectionHeader.Title,{children:"HOW FILTERS WORK"})]}),_jsx(View,{style:styles.howItWorks,children:_jsxs(Text,{style:styles.howItWorksText,children:[_jsx(Text,{style:styles.howItWorksBold,children:"Any:"})," Matches against all fields","\n",_jsx(Text,{style:styles.howItWorksBold,children:"ViewType:"})," Native component class (RCTView, RCTText)","\n",_jsx(Text,{style:styles.howItWorksBold,children:"testID:"})," Component testID prop","\n",_jsx(Text,{style:styles.howItWorksBold,children:"Component:"})," React component name from fiber"]})})]})]}):_jsx(_Fragment,{children:_jsxs(View,{style:styles.section,children:[_jsxs(SectionHeader,{children:[_jsx(SectionHeader.Icon,{icon:Settings,color:buoyColors.textMuted,size:12}),_jsx(SectionHeader.Title,{children:"SETTINGS"})]}),_jsxs(View,{style:styles.settingsSection,children:[_jsxs(View,{style:styles.settingItem,children:[_jsxs(View,{style:styles.settingHeader,children:[_jsx(Text,{style:styles.settingLabel,children:"Show Render Count"}),_jsx(Switch,{value:o.showRenderCount,onValueChange:e=>{s({showRenderCount:e}),!e&&o.trackRenderCauses&&s({trackRenderCauses:!1})},trackColor:{false:buoyColors.input,true:buoyColors.success+"80"},thumbColor:o.showRenderCount?buoyColors.success:buoyColors.textMuted})]}),_jsx(Text,{style:styles.settingDescription,children:"Display render count badge on highlights. Disabling improves performance by skipping count tracking."})]}),_jsxs(View,{style:[styles.settingItem,styles.settingItemSpaced],children:[_jsxs(View,{style:styles.settingHeader,children:[_jsx(Text,{style:[styles.settingLabel,!o.showRenderCount&&styles.settingLabelDisabled],children:"Track Render Causes"}),_jsx(Switch,{value:o.trackRenderCauses,onValueChange:e=>s({trackRenderCauses:e}),trackColor:{false:buoyColors.input,true:buoyColors.warning+"80"},thumbColor:o.trackRenderCauses?buoyColors.warning:buoyColors.textMuted,disabled:!o.showRenderCount})]}),_jsxs(Text,{style:styles.settingDescription,children:["Detect WHY components render (props, hooks, parent re-render).",!o.showRenderCount&&_jsxs(Text,{style:styles.settingWarning,children:["\n",'Requires "Show Render Count" to be enabled.']})]})]}),_jsxs(View,{style:[styles.settingItem,styles.settingItemSpaced],children:[_jsxs(View,{style:styles.settingHeader,children:[_jsx(Text,{style:[styles.settingLabel,!o.trackRenderCauses&&styles.settingLabelDisabled],children:"Enable Render History"}),_jsx(Switch,{value:o.enableRenderHistory,onValueChange:e=>s({enableRenderHistory:e}),trackColor:{false:buoyColors.input,true:buoyColors.primary+"80"},thumbColor:o.enableRenderHistory?buoyColors.primary:buoyColors.textMuted,disabled:!o.trackRenderCauses})]}),_jsxs(Text,{style:styles.settingDescription,children:["Store render events for each component to view in the History tab.",!o.trackRenderCauses&&_jsxs(Text,{style:styles.settingWarning,children:["\n",'Requires "Track Render Causes" to be enabled.']})]})]}),_jsxs(View,{style:[styles.settingItem,styles.settingItemSpaced],children:[_jsxs(View,{style:styles.settingHeader,children:[_jsx(Text,{style:styles.settingLabel,children:"Debug Log Level"}),_jsx(View,{style:styles.settingValue,children:_jsx(Text,{style:[styles.settingValueText,"off"!==o.debugLogLevel&&{color:buoyColors.warning}],children:DEBUG_LOG_LEVEL_PRESETS.find(e=>e.value===o.debugLogLevel)?.label||"Off"})})]}),_jsx(Text,{style:styles.settingDescription,children:"Control console logging verbosity for render cause detection."}),_jsx(View,{style:styles.batchSizePresets,children:DEBUG_LOG_LEVEL_PRESETS.map(e=>_jsx(TouchableOpacity,{style:[styles.batchSizePreset,o.debugLogLevel===e.value&&styles.batchSizePresetActive,"off"!==e.value&&o.debugLogLevel===e.value&&{backgroundColor:buoyColors.warning+"30",borderColor:buoyColors.warning}],onPress:()=>s({debugLogLevel:e.value}),children:_jsx(Text,{style:[styles.batchSizePresetText,o.debugLogLevel===e.value&&styles.batchSizePresetTextActive,"off"!==e.value&&o.debugLogLevel===e.value&&{color:buoyColors.warning}],children:e.label})},e.value))}),_jsxs(Text,{style:styles.settingDescriptionMuted,children:[DEBUG_LOG_LEVEL_PRESETS.find(e=>e.value===o.debugLogLevel)?.description,"off"!==o.debugLogLevel&&" • Check Metro console for logs"]})]}),_jsxs(View,{style:[styles.settingItem,styles.settingItemSpaced],children:[_jsxs(View,{style:styles.settingHeader,children:[_jsx(Text,{style:styles.settingLabel,children:"Batch Size"}),_jsx(View,{style:styles.settingValue,children:_jsx(Text,{style:styles.settingValueText,children:o.batchSize})})]}),_jsx(Text,{style:styles.settingDescription,children:"Maximum components to highlight per render update. Higher values capture more re-renders but may impact performance on complex screens."}),_jsx(View,{style:styles.batchSizePresets,children:BATCH_SIZE_PRESETS.map(e=>_jsx(TouchableOpacity,{style:[styles.batchSizePreset,o.batchSize===e.value&&styles.batchSizePresetActive],onPress:()=>s({batchSize:e.value}),children:_jsx(Text,{style:[styles.batchSizePresetText,o.batchSize===e.value&&styles.batchSizePresetTextActive],children:e.label})},e.value))})]}),_jsxs(View,{style:[styles.settingItem,styles.settingItemSpaced],children:[_jsxs(View,{style:styles.settingHeader,children:[_jsx(Text,{style:styles.settingLabel,children:"Highlight Dev Tools"}),_jsx(Switch,{value:!o.excludeDevTools,onValueChange:e=>s({excludeDevTools:!e}),trackColor:{false:buoyColors.input,true:buoyColors.primary+"80"},thumbColor:o.excludeDevTools?buoyColors.textMuted:buoyColors.primary})]}),_jsxs(Text,{style:styles.settingDescription,children:["Show re-render highlights on Buoy dev tools (floating menu, modals, etc.). Useful for optimizing the dev tools themselves.",!o.excludeDevTools&&_jsxs(Text,{style:styles.settingWarning,children:["\n","The highlight overlay is always excluded to prevent infinite loops."]})]})]})]})]})})})})}const styles=StyleSheet.create({container:{flex:1,backgroundColor:buoyColors.base},scrollView:{flex:1},scrollContent:{paddingHorizontal:16,paddingTop:12,paddingBottom:32},section:{backgroundColor:buoyColors.card,borderRadius:8,borderWidth:1,borderColor:buoyColors.border+"50",marginBottom:12,overflow:"hidden"},sectionDescription:{fontSize:11,color:buoyColors.textSecondary,paddingHorizontal:16,paddingTop:8,lineHeight:16},patternChips:{flexDirection:"row",flexWrap:"wrap",gap:8,paddingHorizontal:16,paddingTop:12},patternChip:{flexDirection:"row",alignItems:"center",backgroundColor:buoyColors.input,borderRadius:6,borderWidth:1,paddingVertical:4,paddingLeft:4,paddingRight:6,maxWidth:"100%",gap:4},patternChipBadge:{paddingVertical:2,paddingHorizontal:5,borderRadius:4},patternChipBadgeText:{fontSize:9,fontWeight:"700"},patternChipValue:{fontSize:11,color:buoyColors.text,fontFamily:"monospace",flexShrink:1},patternChipX:{marginLeft:2},addPatternRow:{paddingHorizontal:16,paddingTop:12,paddingBottom:16},addButton:{flexDirection:"row",alignItems:"center",justifyContent:"center",paddingVertical:10,paddingHorizontal:16,borderRadius:8,borderWidth:1,borderStyle:"dashed",gap:6},addButtonText:{fontSize:12,fontWeight:"500"},typePicker:{flexDirection:"row",alignItems:"center",gap:8},typePickerRow:{flex:1,flexDirection:"row",flexWrap:"wrap",gap:8},typeOption:{flexDirection:"row",alignItems:"center",paddingVertical:8,paddingHorizontal:12,borderRadius:6,borderWidth:1,backgroundColor:buoyColors.input,gap:6},typeOptionText:{fontSize:11,fontWeight:"600"},typePickerCancel:{padding:8},patternInputContainer:{flexDirection:"row",alignItems:"center",backgroundColor:buoyColors.input,borderRadius:8,borderWidth:1,borderColor:buoyColors.border,paddingLeft:4,paddingRight:8,paddingVertical:4,gap:4},patternInput:{flex:1,fontSize:12,color:buoyColors.text,paddingVertical:6,paddingHorizontal:4},addPatternButton:{paddingVertical:6,paddingHorizontal:10,borderRadius:4},addPatternButtonText:{fontSize:11,fontWeight:"600"},cancelButton:{padding:4},categoryBadgeScroll:{marginTop:12},categoryBadgeScrollContent:{paddingHorizontal:16,gap:8},categoryBadge:{flexDirection:"row",alignItems:"center",paddingVertical:8,paddingLeft:10,paddingRight:6,borderRadius:8,borderWidth:1,gap:6},categoryBadgeText:{fontSize:11,fontWeight:"600"},categoryBadgeCountBubble:{paddingHorizontal:6,paddingVertical:2,borderRadius:10,minWidth:20,alignItems:"center"},categoryBadgeCount:{fontSize:10,fontWeight:"600"},detectedItemsContainer:{paddingHorizontal:16,paddingTop:12,paddingBottom:16},detectedItemsScroll:{maxHeight:200},detectedItems:{flexDirection:"row",flexWrap:"wrap",gap:8},detectedItem:{flexDirection:"row",alignItems:"center",backgroundColor:buoyColors.input,borderRadius:6,borderWidth:1,paddingVertical:6,paddingHorizontal:10,gap:6},detectedItemText:{fontSize:11,color:buoyColors.text,fontFamily:"monospace"},emptyText:{fontSize:11,color:buoyColors.textMuted,fontStyle:"italic",textAlign:"center",paddingVertical:16,paddingHorizontal:16},howItWorks:{paddingHorizontal:16,paddingVertical:12},howItWorksText:{fontSize:11,color:buoyColors.textMuted,lineHeight:18,fontFamily:"monospace"},howItWorksBold:{fontWeight:"700",color:buoyColors.textSecondary},modalOverlay:{flex:1,backgroundColor:"rgba(0, 0, 0, 0.5)",justifyContent:"center",alignItems:"center",padding:32},actionPopup:{backgroundColor:buoyColors.card,borderRadius:12,borderWidth:1,borderColor:buoyColors.border,width:"100%",maxWidth:300,overflow:"hidden"},actionPopupHeader:{padding:16,borderBottomWidth:1,borderBottomColor:buoyColors.border+"50",alignItems:"center"},actionPopupButtons:{flexDirection:"row",padding:12,gap:8},actionPopupButton:{flex:1,flexDirection:"row",alignItems:"center",justifyContent:"center",paddingVertical:12,paddingHorizontal:12,borderRadius:8,gap:8},actionPopupInclude:{backgroundColor:buoyColors.success+"15"},actionPopupExclude:{backgroundColor:buoyColors.primary+"15"},actionPopupButtonText:{fontSize:13,fontWeight:"600"},actionPopupCancel:{padding:12,borderTopWidth:1,borderTopColor:buoyColors.border+"50",alignItems:"center"},actionPopupCancelText:{fontSize:13,color:buoyColors.textMuted,fontWeight:"500"},settingsSection:{paddingHorizontal:16,paddingTop:8,paddingBottom:16},settingItem:{gap:8},settingItemSpaced:{marginTop:16,paddingTop:16,borderTopWidth:1,borderTopColor:buoyColors.border+"30"},settingHeader:{flexDirection:"row",alignItems:"center",justifyContent:"space-between"},settingLabel:{fontSize:13,fontWeight:"600",color:buoyColors.text},settingValue:{backgroundColor:buoyColors.textMuted+"20",paddingHorizontal:10,paddingVertical:4,borderRadius:6},settingValueText:{fontSize:12,fontWeight:"700",color:buoyColors.textMuted,fontFamily:"monospace"},settingDescription:{fontSize:11,color:buoyColors.textSecondary,lineHeight:16},settingDescriptionMuted:{fontSize:10,color:buoyColors.textMuted,lineHeight:14,marginTop:4,fontStyle:"italic"},settingLabelDisabled:{color:buoyColors.textMuted},settingWarning:{color:buoyColors.warning,fontWeight:"500"},batchSizePresets:{flexDirection:"row",flexWrap:"wrap",gap:8,marginTop:4},batchSizePreset:{paddingVertical:8,paddingHorizontal:14,borderRadius:6,backgroundColor:buoyColors.input,borderWidth:1,borderColor:buoyColors.border+"50"},batchSizePresetActive:{backgroundColor:buoyColors.textMuted+"20",borderColor:buoyColors.textMuted},batchSizePresetText:{fontSize:12,fontWeight:"500",color:buoyColors.textSecondary,fontFamily:"monospace"},batchSizePresetTextActive:{color:buoyColors.textMuted,fontWeight:"700"},renderCountRangeContainer:{paddingHorizontal:16,paddingTop:12,paddingBottom:16,gap:12},renderCountInputRow:{flexDirection:"row",alignItems:"center",gap:12},renderCountInputGroup:{flex:1,gap:4},renderCountLabel:{fontSize:10,fontWeight:"600",color:buoyColors.textMuted,textTransform:"uppercase",letterSpacing:.5},renderCountInput:{backgroundColor:buoyColors.input,borderRadius:8,borderWidth:1,borderColor:buoyColors.border,paddingVertical:10,paddingHorizontal:12,fontSize:14,fontWeight:"600",color:buoyColors.text,fontFamily:"monospace",textAlign:"center"},renderCountSeparator:{fontSize:12,color:buoyColors.textMuted,marginTop:18},clearRangeButton:{flexDirection:"row",alignItems:"center",justifyContent:"center",paddingVertical:8,paddingHorizontal:12,borderRadius:6,backgroundColor:buoyColors.warning+"15",borderWidth:1,borderColor:buoyColors.warning+"40",gap:6,alignSelf:"center"},clearRangeButtonText:{fontSize:11,fontWeight:"600",color:buoyColors.warning}});export default HighlightFilterView;
1
+ "use strict";
2
+
3
+ /**
4
+ * HighlightFilterView
5
+ *
6
+ * Simplified filter configuration for tracked component renders.
7
+ * Uses a badge-based approach where users select a filter type
8
+ * (Any, ViewType, testID, Component) then enter a value.
9
+ */
10
+
11
+ import React, { useState, useCallback } from "react";
12
+ import { View, Text, TouchableOpacity, TextInput, StyleSheet, ScrollView, Modal, Pressable, Switch } from "react-native";
13
+ import { Eye, Filter, Plus, X, Box, Settings, Hash, SectionHeader, buoyColors } from "@buoy-gg/shared-ui";
14
+ import { IdentifierBadge, IDENTIFIER_CONFIG } from "./IdentifierBadge";
15
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
16
+ // Use shared identifier config (FilterType is a subset of IdentifierType)
17
+ const getFilterConfig = type => IDENTIFIER_CONFIG[type];
18
+
19
+ // Filter types available for selection (all identifier types)
20
+ const FILTER_TYPES = ["any", "viewType", "testID", "nativeID", "component", "accessibilityLabel"];
21
+
22
+ // Type picker component
23
+ function TypePicker({
24
+ onSelect,
25
+ onCancel
26
+ }) {
27
+ return /*#__PURE__*/_jsxs(View, {
28
+ nativeID: "__rn_buoy__type-picker",
29
+ style: styles.typePicker,
30
+ children: [/*#__PURE__*/_jsx(View, {
31
+ style: styles.typePickerRow,
32
+ children: FILTER_TYPES.map(type => {
33
+ const config = getFilterConfig(type);
34
+ const IconComponent = config.icon;
35
+ return /*#__PURE__*/_jsxs(TouchableOpacity, {
36
+ style: [styles.typeOption, {
37
+ backgroundColor: config.color + "15",
38
+ borderColor: config.color + "40"
39
+ }],
40
+ onPress: () => onSelect(type),
41
+ children: [/*#__PURE__*/_jsx(IconComponent, {
42
+ size: 14,
43
+ color: config.color
44
+ }), /*#__PURE__*/_jsx(Text, {
45
+ style: [styles.typeOptionText, {
46
+ color: config.color
47
+ }],
48
+ children: config.label
49
+ })]
50
+ }, type);
51
+ })
52
+ }), /*#__PURE__*/_jsx(TouchableOpacity, {
53
+ onPress: onCancel,
54
+ style: styles.typePickerCancel,
55
+ children: /*#__PURE__*/_jsx(X, {
56
+ size: 16,
57
+ color: buoyColors.textMuted
58
+ })
59
+ })]
60
+ });
61
+ }
62
+
63
+ // Pattern input with badge prefix
64
+ function PatternInput({
65
+ type,
66
+ onSubmit,
67
+ onCancel
68
+ }) {
69
+ const [value, setValue] = useState("");
70
+ const config = getFilterConfig(type);
71
+ const handleSubmit = () => {
72
+ if (value.trim()) {
73
+ onSubmit(value.trim());
74
+ }
75
+ };
76
+ return /*#__PURE__*/_jsxs(View, {
77
+ nativeID: "__rn_buoy__pattern-input",
78
+ style: styles.patternInputContainer,
79
+ children: [/*#__PURE__*/_jsx(IdentifierBadge, {
80
+ type: type,
81
+ value: "",
82
+ badgeOnly: true,
83
+ compact: true
84
+ }), /*#__PURE__*/_jsx(TextInput, {
85
+ value: value,
86
+ onChangeText: setValue,
87
+ onSubmitEditing: handleSubmit,
88
+ placeholder: "Enter pattern...",
89
+ placeholderTextColor: buoyColors.textMuted,
90
+ style: styles.patternInput,
91
+ autoFocus: true,
92
+ returnKeyType: "done",
93
+ autoCorrect: false,
94
+ autoCapitalize: "none"
95
+ }), value.trim() && /*#__PURE__*/_jsx(TouchableOpacity, {
96
+ onPress: handleSubmit,
97
+ style: [styles.addPatternButton, {
98
+ backgroundColor: config.color + "20"
99
+ }],
100
+ children: /*#__PURE__*/_jsx(Text, {
101
+ style: [styles.addPatternButtonText, {
102
+ color: config.color
103
+ }],
104
+ children: "Add"
105
+ })
106
+ }), /*#__PURE__*/_jsx(TouchableOpacity, {
107
+ onPress: onCancel,
108
+ style: styles.cancelButton,
109
+ children: /*#__PURE__*/_jsx(X, {
110
+ size: 16,
111
+ color: buoyColors.textMuted
112
+ })
113
+ })]
114
+ });
115
+ }
116
+
117
+ // Pattern chip (removable badge) - tap to remove
118
+ function PatternChip({
119
+ pattern,
120
+ onRemove
121
+ }) {
122
+ const config = getFilterConfig(pattern.type);
123
+ return /*#__PURE__*/_jsxs(TouchableOpacity, {
124
+ style: [styles.patternChip, {
125
+ borderColor: config.color + "40"
126
+ }],
127
+ onPress: onRemove,
128
+ activeOpacity: 0.7,
129
+ children: [/*#__PURE__*/_jsx(View, {
130
+ style: [styles.patternChipBadge, {
131
+ backgroundColor: config.color + "20"
132
+ }],
133
+ children: /*#__PURE__*/_jsx(Text, {
134
+ style: [styles.patternChipBadgeText, {
135
+ color: config.color
136
+ }],
137
+ children: config.shortLabel
138
+ })
139
+ }), /*#__PURE__*/_jsx(Text, {
140
+ style: styles.patternChipValue,
141
+ numberOfLines: 1,
142
+ children: pattern.value
143
+ }), /*#__PURE__*/_jsx(X, {
144
+ size: 12,
145
+ color: buoyColors.textMuted,
146
+ style: styles.patternChipX
147
+ })]
148
+ });
149
+ }
150
+
151
+ // Category type including "all"
152
+
153
+ // Config for "all" category
154
+ const ALL_CATEGORY_CONFIG = {
155
+ label: "All",
156
+ shortLabel: "All",
157
+ color: buoyColors.textSecondary,
158
+ icon: Box
159
+ };
160
+
161
+ // Category badge for horizontal scroll - always colored
162
+ function DetectedCategoryBadge({
163
+ filterType,
164
+ count,
165
+ isSelected,
166
+ onPress
167
+ }) {
168
+ // "all" has its own config
169
+ const config = filterType === "all" ? ALL_CATEGORY_CONFIG : getFilterConfig(filterType);
170
+ return /*#__PURE__*/_jsxs(TouchableOpacity, {
171
+ style: [styles.categoryBadge, {
172
+ backgroundColor: config.color + "15",
173
+ borderColor: isSelected ? config.color : config.color + "40",
174
+ borderWidth: isSelected ? 2 : 1
175
+ }],
176
+ onPress: onPress,
177
+ children: [/*#__PURE__*/_jsx(config.icon, {
178
+ size: 12,
179
+ color: config.color
180
+ }), /*#__PURE__*/_jsx(Text, {
181
+ style: [styles.categoryBadgeText, {
182
+ color: config.color
183
+ }],
184
+ children: config.label
185
+ }), /*#__PURE__*/_jsx(View, {
186
+ style: [styles.categoryBadgeCountBubble, {
187
+ backgroundColor: config.color + "25"
188
+ }],
189
+ children: /*#__PURE__*/_jsx(Text, {
190
+ style: [styles.categoryBadgeCount, {
191
+ color: config.color
192
+ }],
193
+ children: count
194
+ })
195
+ })]
196
+ });
197
+ }
198
+
199
+ // Batch size presets for the slider
200
+ const BATCH_SIZE_PRESETS = [{
201
+ value: 20,
202
+ label: "20"
203
+ }, {
204
+ value: 50,
205
+ label: "50"
206
+ }, {
207
+ value: 100,
208
+ label: "100"
209
+ }, {
210
+ value: 150,
211
+ label: "150"
212
+ }, {
213
+ value: 250,
214
+ label: "250"
215
+ }, {
216
+ value: 500,
217
+ label: "500"
218
+ }];
219
+
220
+ // Debug log level presets
221
+ const DEBUG_LOG_LEVEL_PRESETS = [{
222
+ value: "off",
223
+ label: "Off",
224
+ description: "No debug logging"
225
+ }, {
226
+ value: "minimal",
227
+ label: "Minimal",
228
+ description: "Only hook value changes"
229
+ }, {
230
+ value: "verbose",
231
+ label: "Verbose",
232
+ description: "Component + cause + changes"
233
+ }, {
234
+ value: "all",
235
+ label: "All",
236
+ description: "Full fiber dump"
237
+ }];
238
+ export function HighlightFilterView({
239
+ filters,
240
+ onFilterChange,
241
+ settings,
242
+ onSettingsChange,
243
+ availableProps,
244
+ activeTab
245
+ }) {
246
+ // UI state for add inputs
247
+ const [showIncludeTypePicker, setShowIncludeTypePicker] = useState(false);
248
+ const [showExcludeTypePicker, setShowExcludeTypePicker] = useState(false);
249
+ const [includeInputType, setIncludeInputType] = useState(null);
250
+ const [excludeInputType, setExcludeInputType] = useState(null);
251
+
252
+ // State for selected detected category (default to "all")
253
+ const [selectedCategory, setSelectedCategory] = useState("all");
254
+
255
+ // State for action popup when tapping detected item
256
+ const [actionPopupItem, setActionPopupItem] = useState(null);
257
+
258
+ // Get items for selected category with their filter type
259
+ const getItemsForCategory = category => {
260
+ switch (category) {
261
+ case "viewType":
262
+ return availableProps.viewTypes.map(v => ({
263
+ value: v,
264
+ type: "viewType"
265
+ }));
266
+ case "testID":
267
+ return availableProps.testIDs.map(v => ({
268
+ value: v,
269
+ type: "testID"
270
+ }));
271
+ case "nativeID":
272
+ return availableProps.nativeIDs.map(v => ({
273
+ value: v,
274
+ type: "nativeID"
275
+ }));
276
+ case "component":
277
+ return availableProps.componentNames.map(v => ({
278
+ value: v,
279
+ type: "component"
280
+ }));
281
+ case "accessibilityLabel":
282
+ return availableProps.accessibilityLabels.map(v => ({
283
+ value: v,
284
+ type: "accessibilityLabel"
285
+ }));
286
+ case "all":
287
+ default:
288
+ // Combine all items with their types
289
+ return [...availableProps.viewTypes.map(v => ({
290
+ value: v,
291
+ type: "viewType"
292
+ })), ...availableProps.testIDs.map(v => ({
293
+ value: v,
294
+ type: "testID"
295
+ })), ...availableProps.nativeIDs.map(v => ({
296
+ value: v,
297
+ type: "nativeID"
298
+ })), ...availableProps.componentNames.map(v => ({
299
+ value: v,
300
+ type: "component"
301
+ })), ...availableProps.accessibilityLabels.map(v => ({
302
+ value: v,
303
+ type: "accessibilityLabel"
304
+ }))];
305
+ }
306
+ };
307
+ const selectedItems = getItemsForCategory(selectedCategory);
308
+ const totalItemCount = availableProps.viewTypes.length + availableProps.testIDs.length + availableProps.nativeIDs.length + availableProps.componentNames.length + availableProps.accessibilityLabels.length;
309
+
310
+ // Add include pattern
311
+ const handleAddIncludePattern = useCallback((type, value) => {
312
+ const newPatterns = [...filters.includePatterns, {
313
+ type,
314
+ value
315
+ }];
316
+ onFilterChange({
317
+ includePatterns: newPatterns
318
+ });
319
+ setIncludeInputType(null);
320
+ }, [filters.includePatterns, onFilterChange]);
321
+
322
+ // Add exclude pattern
323
+ const handleAddExcludePattern = useCallback((type, value) => {
324
+ const newPatterns = [...filters.excludePatterns, {
325
+ type,
326
+ value
327
+ }];
328
+ onFilterChange({
329
+ excludePatterns: newPatterns
330
+ });
331
+ setExcludeInputType(null);
332
+ }, [filters.excludePatterns, onFilterChange]);
333
+
334
+ // Remove include pattern
335
+ const handleRemoveIncludePattern = useCallback(index => {
336
+ const newPatterns = filters.includePatterns.filter((_, i) => i !== index);
337
+ onFilterChange({
338
+ includePatterns: newPatterns
339
+ });
340
+ }, [filters.includePatterns, onFilterChange]);
341
+
342
+ // Remove exclude pattern
343
+ const handleRemoveExcludePattern = useCallback(index => {
344
+ const newPatterns = filters.excludePatterns.filter((_, i) => i !== index);
345
+ onFilterChange({
346
+ excludePatterns: newPatterns
347
+ });
348
+ }, [filters.excludePatterns, onFilterChange]);
349
+
350
+ // Show action popup for detected item
351
+ const handleDetectedItemPress = useCallback((type, value) => {
352
+ setActionPopupItem({
353
+ type,
354
+ value
355
+ });
356
+ }, []);
357
+
358
+ // Add to include from popup
359
+ const handlePopupInclude = useCallback(() => {
360
+ if (actionPopupItem) {
361
+ handleAddIncludePattern(actionPopupItem.type, actionPopupItem.value);
362
+ setActionPopupItem(null);
363
+ }
364
+ }, [actionPopupItem, handleAddIncludePattern]);
365
+
366
+ // Add to exclude from popup
367
+ const handlePopupExclude = useCallback(() => {
368
+ if (actionPopupItem) {
369
+ handleAddExcludePattern(actionPopupItem.type, actionPopupItem.value);
370
+ setActionPopupItem(null);
371
+ }
372
+ }, [actionPopupItem, handleAddExcludePattern]);
373
+ return /*#__PURE__*/_jsx(View, {
374
+ style: styles.container,
375
+ children: /*#__PURE__*/_jsx(ScrollView, {
376
+ nativeID: "__rn_buoy__filter-view",
377
+ style: styles.scrollView,
378
+ contentContainerStyle: styles.scrollContent,
379
+ showsVerticalScrollIndicator: false,
380
+ children: activeTab === "filters" ? /*#__PURE__*/_jsxs(_Fragment, {
381
+ children: [/*#__PURE__*/_jsxs(View, {
382
+ style: styles.section,
383
+ children: [/*#__PURE__*/_jsxs(SectionHeader, {
384
+ children: [/*#__PURE__*/_jsx(SectionHeader.Icon, {
385
+ icon: Eye,
386
+ color: buoyColors.success,
387
+ size: 12
388
+ }), /*#__PURE__*/_jsx(SectionHeader.Title, {
389
+ children: "INCLUDE ONLY"
390
+ }), filters.includePatterns.length > 0 && /*#__PURE__*/_jsx(SectionHeader.Badge, {
391
+ count: filters.includePatterns.length,
392
+ color: buoyColors.success
393
+ })]
394
+ }), /*#__PURE__*/_jsx(Text, {
395
+ style: styles.sectionDescription,
396
+ children: "Show only components matching these patterns. If any are set, components must match at least one."
397
+ }), filters.includePatterns.length > 0 && /*#__PURE__*/_jsx(View, {
398
+ style: styles.patternChips,
399
+ children: filters.includePatterns.map((pattern, index) => /*#__PURE__*/_jsx(PatternChip, {
400
+ pattern: pattern,
401
+ onRemove: () => handleRemoveIncludePattern(index)
402
+ }, `${pattern.type}-${pattern.value}-${index}`))
403
+ }), /*#__PURE__*/_jsx(View, {
404
+ style: styles.addPatternRow,
405
+ children: showIncludeTypePicker ? /*#__PURE__*/_jsx(TypePicker, {
406
+ onSelect: type => {
407
+ setShowIncludeTypePicker(false);
408
+ setIncludeInputType(type);
409
+ },
410
+ onCancel: () => setShowIncludeTypePicker(false)
411
+ }) : includeInputType ? /*#__PURE__*/_jsx(PatternInput, {
412
+ type: includeInputType,
413
+ onSubmit: value => handleAddIncludePattern(includeInputType, value),
414
+ onCancel: () => setIncludeInputType(null)
415
+ }) : /*#__PURE__*/_jsxs(TouchableOpacity, {
416
+ style: [styles.addButton, {
417
+ borderColor: buoyColors.success + "40"
418
+ }],
419
+ onPress: () => setShowIncludeTypePicker(true),
420
+ children: [/*#__PURE__*/_jsx(Plus, {
421
+ size: 14,
422
+ color: buoyColors.success
423
+ }), /*#__PURE__*/_jsx(Text, {
424
+ style: [styles.addButtonText, {
425
+ color: buoyColors.success
426
+ }],
427
+ children: "Add include pattern"
428
+ })]
429
+ })
430
+ })]
431
+ }), /*#__PURE__*/_jsxs(View, {
432
+ style: styles.section,
433
+ children: [/*#__PURE__*/_jsxs(SectionHeader, {
434
+ children: [/*#__PURE__*/_jsx(SectionHeader.Icon, {
435
+ icon: Filter,
436
+ color: buoyColors.primary,
437
+ size: 12
438
+ }), /*#__PURE__*/_jsx(SectionHeader.Title, {
439
+ children: "EXCLUDE"
440
+ }), filters.excludePatterns.length > 0 && /*#__PURE__*/_jsx(SectionHeader.Badge, {
441
+ count: filters.excludePatterns.length,
442
+ color: buoyColors.primary
443
+ })]
444
+ }), /*#__PURE__*/_jsx(Text, {
445
+ style: styles.sectionDescription,
446
+ children: "Hide components matching these patterns from the list."
447
+ }), filters.excludePatterns.length > 0 && /*#__PURE__*/_jsx(View, {
448
+ style: styles.patternChips,
449
+ children: filters.excludePatterns.map((pattern, index) => /*#__PURE__*/_jsx(PatternChip, {
450
+ pattern: pattern,
451
+ onRemove: () => handleRemoveExcludePattern(index)
452
+ }, `${pattern.type}-${pattern.value}-${index}`))
453
+ }), /*#__PURE__*/_jsx(View, {
454
+ style: styles.addPatternRow,
455
+ children: showExcludeTypePicker ? /*#__PURE__*/_jsx(TypePicker, {
456
+ onSelect: type => {
457
+ setShowExcludeTypePicker(false);
458
+ setExcludeInputType(type);
459
+ },
460
+ onCancel: () => setShowExcludeTypePicker(false)
461
+ }) : excludeInputType ? /*#__PURE__*/_jsx(PatternInput, {
462
+ type: excludeInputType,
463
+ onSubmit: value => handleAddExcludePattern(excludeInputType, value),
464
+ onCancel: () => setExcludeInputType(null)
465
+ }) : /*#__PURE__*/_jsxs(TouchableOpacity, {
466
+ style: [styles.addButton, {
467
+ borderColor: buoyColors.primary + "40"
468
+ }],
469
+ onPress: () => setShowExcludeTypePicker(true),
470
+ children: [/*#__PURE__*/_jsx(Plus, {
471
+ size: 14,
472
+ color: buoyColors.primary
473
+ }), /*#__PURE__*/_jsx(Text, {
474
+ style: [styles.addButtonText, {
475
+ color: buoyColors.primary
476
+ }],
477
+ children: "Add exclude pattern"
478
+ })]
479
+ })
480
+ })]
481
+ }), /*#__PURE__*/_jsxs(View, {
482
+ style: styles.section,
483
+ children: [/*#__PURE__*/_jsxs(SectionHeader, {
484
+ children: [/*#__PURE__*/_jsx(SectionHeader.Icon, {
485
+ icon: Hash,
486
+ color: buoyColors.warning,
487
+ size: 12
488
+ }), /*#__PURE__*/_jsx(SectionHeader.Title, {
489
+ children: "RENDER COUNT RANGE"
490
+ }), (filters.minRenderCount !== undefined || filters.maxRenderCount !== undefined) && /*#__PURE__*/_jsx(SectionHeader.Badge, {
491
+ count: 1,
492
+ color: buoyColors.warning
493
+ })]
494
+ }), /*#__PURE__*/_jsx(Text, {
495
+ style: styles.sectionDescription,
496
+ children: "Show only components with render count in a specific range."
497
+ }), /*#__PURE__*/_jsxs(View, {
498
+ nativeID: "__rn_buoy__render-count-range",
499
+ style: styles.renderCountRangeContainer,
500
+ children: [/*#__PURE__*/_jsxs(View, {
501
+ style: styles.renderCountInputRow,
502
+ children: [/*#__PURE__*/_jsxs(View, {
503
+ style: styles.renderCountInputGroup,
504
+ children: [/*#__PURE__*/_jsx(Text, {
505
+ style: styles.renderCountLabel,
506
+ children: "Min"
507
+ }), /*#__PURE__*/_jsx(TextInput, {
508
+ value: filters.minRenderCount !== undefined ? String(filters.minRenderCount) : "",
509
+ onChangeText: text => {
510
+ const num = parseInt(text, 10);
511
+ if (text === "" || text === undefined) {
512
+ onFilterChange({
513
+ minRenderCount: undefined
514
+ });
515
+ } else if (!isNaN(num) && num >= 0) {
516
+ onFilterChange({
517
+ minRenderCount: num
518
+ });
519
+ }
520
+ },
521
+ placeholder: "0",
522
+ placeholderTextColor: buoyColors.textMuted,
523
+ style: styles.renderCountInput,
524
+ keyboardType: "number-pad",
525
+ returnKeyType: "done"
526
+ })]
527
+ }), /*#__PURE__*/_jsx(Text, {
528
+ style: styles.renderCountSeparator,
529
+ children: "to"
530
+ }), /*#__PURE__*/_jsxs(View, {
531
+ style: styles.renderCountInputGroup,
532
+ children: [/*#__PURE__*/_jsx(Text, {
533
+ style: styles.renderCountLabel,
534
+ children: "Max"
535
+ }), /*#__PURE__*/_jsx(TextInput, {
536
+ value: filters.maxRenderCount !== undefined ? String(filters.maxRenderCount) : "",
537
+ onChangeText: text => {
538
+ const num = parseInt(text, 10);
539
+ if (text === "" || text === undefined) {
540
+ onFilterChange({
541
+ maxRenderCount: undefined
542
+ });
543
+ } else if (!isNaN(num) && num >= 0) {
544
+ onFilterChange({
545
+ maxRenderCount: num
546
+ });
547
+ }
548
+ },
549
+ placeholder: "\u221E",
550
+ placeholderTextColor: buoyColors.textMuted,
551
+ style: styles.renderCountInput,
552
+ keyboardType: "number-pad",
553
+ returnKeyType: "done"
554
+ })]
555
+ })]
556
+ }), (filters.minRenderCount !== undefined || filters.maxRenderCount !== undefined) && /*#__PURE__*/_jsxs(TouchableOpacity, {
557
+ style: styles.clearRangeButton,
558
+ onPress: () => onFilterChange({
559
+ minRenderCount: undefined,
560
+ maxRenderCount: undefined
561
+ }),
562
+ children: [/*#__PURE__*/_jsx(X, {
563
+ size: 12,
564
+ color: buoyColors.warning
565
+ }), /*#__PURE__*/_jsx(Text, {
566
+ style: styles.clearRangeButtonText,
567
+ children: "Clear Range"
568
+ })]
569
+ })]
570
+ })]
571
+ }), /*#__PURE__*/_jsxs(View, {
572
+ style: styles.section,
573
+ children: [/*#__PURE__*/_jsxs(SectionHeader, {
574
+ children: [/*#__PURE__*/_jsx(SectionHeader.Icon, {
575
+ icon: Box,
576
+ color: buoyColors.textSecondary,
577
+ size: 12
578
+ }), /*#__PURE__*/_jsx(SectionHeader.Title, {
579
+ children: "DETECTED ITEMS"
580
+ })]
581
+ }), /*#__PURE__*/_jsx(Text, {
582
+ style: styles.sectionDescription,
583
+ children: "Tap an item to quickly add it as an exclude pattern."
584
+ }), /*#__PURE__*/_jsxs(ScrollView, {
585
+ horizontal: true,
586
+ showsHorizontalScrollIndicator: false,
587
+ style: styles.categoryBadgeScroll,
588
+ contentContainerStyle: styles.categoryBadgeScrollContent,
589
+ children: [totalItemCount > 0 && /*#__PURE__*/_jsx(DetectedCategoryBadge, {
590
+ filterType: "all",
591
+ count: totalItemCount,
592
+ isSelected: selectedCategory === "all",
593
+ onPress: () => setSelectedCategory("all")
594
+ }), availableProps.viewTypes.length > 0 && /*#__PURE__*/_jsx(DetectedCategoryBadge, {
595
+ filterType: "viewType",
596
+ count: availableProps.viewTypes.length,
597
+ isSelected: selectedCategory === "viewType",
598
+ onPress: () => setSelectedCategory("viewType")
599
+ }), availableProps.testIDs.length > 0 && /*#__PURE__*/_jsx(DetectedCategoryBadge, {
600
+ filterType: "testID",
601
+ count: availableProps.testIDs.length,
602
+ isSelected: selectedCategory === "testID",
603
+ onPress: () => setSelectedCategory("testID")
604
+ }), availableProps.nativeIDs.length > 0 && /*#__PURE__*/_jsx(DetectedCategoryBadge, {
605
+ filterType: "nativeID",
606
+ count: availableProps.nativeIDs.length,
607
+ isSelected: selectedCategory === "nativeID",
608
+ onPress: () => setSelectedCategory("nativeID")
609
+ }), availableProps.componentNames.length > 0 && /*#__PURE__*/_jsx(DetectedCategoryBadge, {
610
+ filterType: "component",
611
+ count: availableProps.componentNames.length,
612
+ isSelected: selectedCategory === "component",
613
+ onPress: () => setSelectedCategory("component")
614
+ }), availableProps.accessibilityLabels.length > 0 && /*#__PURE__*/_jsx(DetectedCategoryBadge, {
615
+ filterType: "accessibilityLabel",
616
+ count: availableProps.accessibilityLabels.length,
617
+ isSelected: selectedCategory === "accessibilityLabel",
618
+ onPress: () => setSelectedCategory("accessibilityLabel")
619
+ })]
620
+ }), /*#__PURE__*/_jsx(View, {
621
+ nativeID: "__rn_buoy__detected-items",
622
+ style: styles.detectedItemsContainer,
623
+ children: selectedItems.length > 0 ? /*#__PURE__*/_jsx(ScrollView, {
624
+ style: styles.detectedItemsScroll,
625
+ contentContainerStyle: styles.detectedItems,
626
+ nestedScrollEnabled: true,
627
+ showsVerticalScrollIndicator: true,
628
+ children: selectedItems.map(item => {
629
+ const itemConfig = getFilterConfig(item.type);
630
+ return /*#__PURE__*/_jsx(TouchableOpacity, {
631
+ style: [styles.detectedItem, {
632
+ borderColor: itemConfig.color + "40"
633
+ }],
634
+ onPress: () => handleDetectedItemPress(item.type, item.value),
635
+ children: selectedCategory === "all" ? /*#__PURE__*/_jsx(IdentifierBadge, {
636
+ type: item.type,
637
+ value: item.value,
638
+ compact: true,
639
+ shortLabel: true
640
+ }) : /*#__PURE__*/_jsx(Text, {
641
+ style: styles.detectedItemText,
642
+ numberOfLines: 1,
643
+ children: item.value
644
+ })
645
+ }, `${item.type}-${item.value}`);
646
+ })
647
+ }) : /*#__PURE__*/_jsx(Text, {
648
+ style: styles.emptyText,
649
+ children: "No items detected yet. Start tracking to see components here."
650
+ })
651
+ })]
652
+ }), /*#__PURE__*/_jsx(Modal, {
653
+ visible: actionPopupItem !== null,
654
+ transparent: true,
655
+ animationType: "fade",
656
+ onRequestClose: () => setActionPopupItem(null),
657
+ children: /*#__PURE__*/_jsx(Pressable, {
658
+ style: styles.modalOverlay,
659
+ onPress: () => setActionPopupItem(null),
660
+ children: /*#__PURE__*/_jsx(View, {
661
+ style: styles.actionPopup,
662
+ children: actionPopupItem && /*#__PURE__*/_jsxs(_Fragment, {
663
+ children: [/*#__PURE__*/_jsx(View, {
664
+ style: styles.actionPopupHeader,
665
+ children: /*#__PURE__*/_jsx(IdentifierBadge, {
666
+ type: actionPopupItem.type,
667
+ value: actionPopupItem.value,
668
+ compact: true,
669
+ shortLabel: true
670
+ })
671
+ }), /*#__PURE__*/_jsxs(View, {
672
+ style: styles.actionPopupButtons,
673
+ children: [/*#__PURE__*/_jsxs(TouchableOpacity, {
674
+ style: [styles.actionPopupButton, styles.actionPopupInclude],
675
+ onPress: handlePopupInclude,
676
+ children: [/*#__PURE__*/_jsx(Eye, {
677
+ size: 16,
678
+ color: buoyColors.success
679
+ }), /*#__PURE__*/_jsx(Text, {
680
+ style: [styles.actionPopupButtonText, {
681
+ color: buoyColors.success
682
+ }],
683
+ children: "Include Only"
684
+ })]
685
+ }), /*#__PURE__*/_jsxs(TouchableOpacity, {
686
+ style: [styles.actionPopupButton, styles.actionPopupExclude],
687
+ onPress: handlePopupExclude,
688
+ children: [/*#__PURE__*/_jsx(Filter, {
689
+ size: 16,
690
+ color: buoyColors.primary
691
+ }), /*#__PURE__*/_jsx(Text, {
692
+ style: [styles.actionPopupButtonText, {
693
+ color: buoyColors.primary
694
+ }],
695
+ children: "Exclude"
696
+ })]
697
+ })]
698
+ }), /*#__PURE__*/_jsx(TouchableOpacity, {
699
+ style: styles.actionPopupCancel,
700
+ onPress: () => setActionPopupItem(null),
701
+ children: /*#__PURE__*/_jsx(Text, {
702
+ style: styles.actionPopupCancelText,
703
+ children: "Cancel"
704
+ })
705
+ })]
706
+ })
707
+ })
708
+ })
709
+ }), /*#__PURE__*/_jsxs(View, {
710
+ style: styles.section,
711
+ children: [/*#__PURE__*/_jsxs(SectionHeader, {
712
+ children: [/*#__PURE__*/_jsx(SectionHeader.Icon, {
713
+ icon: Filter,
714
+ color: buoyColors.textMuted,
715
+ size: 12
716
+ }), /*#__PURE__*/_jsx(SectionHeader.Title, {
717
+ children: "HOW FILTERS WORK"
718
+ })]
719
+ }), /*#__PURE__*/_jsx(View, {
720
+ style: styles.howItWorks,
721
+ children: /*#__PURE__*/_jsxs(Text, {
722
+ style: styles.howItWorksText,
723
+ children: [/*#__PURE__*/_jsx(Text, {
724
+ style: styles.howItWorksBold,
725
+ children: "Any:"
726
+ }), " Matches against all fields", "\n", /*#__PURE__*/_jsx(Text, {
727
+ style: styles.howItWorksBold,
728
+ children: "ViewType:"
729
+ }), " Native component class (RCTView, RCTText)", "\n", /*#__PURE__*/_jsx(Text, {
730
+ style: styles.howItWorksBold,
731
+ children: "testID:"
732
+ }), " Component testID prop", "\n", /*#__PURE__*/_jsx(Text, {
733
+ style: styles.howItWorksBold,
734
+ children: "Component:"
735
+ }), " React component name from fiber"]
736
+ })
737
+ })]
738
+ })]
739
+ }) : /*#__PURE__*/_jsx(_Fragment, {
740
+ children: /*#__PURE__*/_jsxs(View, {
741
+ style: styles.section,
742
+ children: [/*#__PURE__*/_jsxs(SectionHeader, {
743
+ children: [/*#__PURE__*/_jsx(SectionHeader.Icon, {
744
+ icon: Settings,
745
+ color: buoyColors.textMuted,
746
+ size: 12
747
+ }), /*#__PURE__*/_jsx(SectionHeader.Title, {
748
+ children: "SETTINGS"
749
+ })]
750
+ }), /*#__PURE__*/_jsxs(View, {
751
+ style: styles.settingsSection,
752
+ children: [/*#__PURE__*/_jsxs(View, {
753
+ style: styles.settingItem,
754
+ children: [/*#__PURE__*/_jsxs(View, {
755
+ style: styles.settingHeader,
756
+ children: [/*#__PURE__*/_jsx(Text, {
757
+ style: styles.settingLabel,
758
+ children: "Show Render Count"
759
+ }), /*#__PURE__*/_jsx(Switch, {
760
+ value: settings.showRenderCount,
761
+ onValueChange: value => {
762
+ onSettingsChange({
763
+ showRenderCount: value
764
+ });
765
+ // If disabling render count, also disable cause tracking
766
+ if (!value && settings.trackRenderCauses) {
767
+ onSettingsChange({
768
+ trackRenderCauses: false
769
+ });
770
+ }
771
+ },
772
+ trackColor: {
773
+ false: buoyColors.input,
774
+ true: buoyColors.success + "80"
775
+ },
776
+ thumbColor: settings.showRenderCount ? buoyColors.success : buoyColors.textMuted
777
+ })]
778
+ }), /*#__PURE__*/_jsx(Text, {
779
+ style: styles.settingDescription,
780
+ children: "Display render count badge on highlights. Disabling improves performance by skipping count tracking."
781
+ })]
782
+ }), /*#__PURE__*/_jsxs(View, {
783
+ style: [styles.settingItem, styles.settingItemSpaced],
784
+ children: [/*#__PURE__*/_jsxs(View, {
785
+ style: styles.settingHeader,
786
+ children: [/*#__PURE__*/_jsx(Text, {
787
+ style: [styles.settingLabel, !settings.showRenderCount && styles.settingLabelDisabled],
788
+ children: "Track Render Causes"
789
+ }), /*#__PURE__*/_jsx(Switch, {
790
+ value: settings.trackRenderCauses,
791
+ onValueChange: value => onSettingsChange({
792
+ trackRenderCauses: value
793
+ }),
794
+ trackColor: {
795
+ false: buoyColors.input,
796
+ true: buoyColors.warning + "80"
797
+ },
798
+ thumbColor: settings.trackRenderCauses ? buoyColors.warning : buoyColors.textMuted,
799
+ disabled: !settings.showRenderCount
800
+ })]
801
+ }), /*#__PURE__*/_jsxs(Text, {
802
+ style: styles.settingDescription,
803
+ children: ["Detect WHY components render (props, hooks, parent re-render).", !settings.showRenderCount && /*#__PURE__*/_jsxs(Text, {
804
+ style: styles.settingWarning,
805
+ children: ["\n", "Requires \"Show Render Count\" to be enabled."]
806
+ })]
807
+ })]
808
+ }), /*#__PURE__*/_jsxs(View, {
809
+ style: [styles.settingItem, styles.settingItemSpaced],
810
+ children: [/*#__PURE__*/_jsxs(View, {
811
+ style: styles.settingHeader,
812
+ children: [/*#__PURE__*/_jsx(Text, {
813
+ style: [styles.settingLabel, !settings.trackRenderCauses && styles.settingLabelDisabled],
814
+ children: "Enable Render History"
815
+ }), /*#__PURE__*/_jsx(Switch, {
816
+ value: settings.enableRenderHistory,
817
+ onValueChange: value => onSettingsChange({
818
+ enableRenderHistory: value
819
+ }),
820
+ trackColor: {
821
+ false: buoyColors.input,
822
+ true: buoyColors.primary + "80"
823
+ },
824
+ thumbColor: settings.enableRenderHistory ? buoyColors.primary : buoyColors.textMuted,
825
+ disabled: !settings.trackRenderCauses
826
+ })]
827
+ }), /*#__PURE__*/_jsxs(Text, {
828
+ style: styles.settingDescription,
829
+ children: ["Store render events for each component to view in the History tab.", !settings.trackRenderCauses && /*#__PURE__*/_jsxs(Text, {
830
+ style: styles.settingWarning,
831
+ children: ["\n", "Requires \"Track Render Causes\" to be enabled."]
832
+ })]
833
+ })]
834
+ }), /*#__PURE__*/_jsxs(View, {
835
+ style: [styles.settingItem, styles.settingItemSpaced],
836
+ children: [/*#__PURE__*/_jsxs(View, {
837
+ style: styles.settingHeader,
838
+ children: [/*#__PURE__*/_jsx(Text, {
839
+ style: styles.settingLabel,
840
+ children: "Debug Log Level"
841
+ }), /*#__PURE__*/_jsx(View, {
842
+ style: styles.settingValue,
843
+ children: /*#__PURE__*/_jsx(Text, {
844
+ style: [styles.settingValueText, settings.debugLogLevel !== "off" && {
845
+ color: buoyColors.warning
846
+ }],
847
+ children: DEBUG_LOG_LEVEL_PRESETS.find(p => p.value === settings.debugLogLevel)?.label || "Off"
848
+ })
849
+ })]
850
+ }), /*#__PURE__*/_jsx(Text, {
851
+ style: styles.settingDescription,
852
+ children: "Control console logging verbosity for render cause detection."
853
+ }), /*#__PURE__*/_jsx(View, {
854
+ style: styles.batchSizePresets,
855
+ children: DEBUG_LOG_LEVEL_PRESETS.map(preset => /*#__PURE__*/_jsx(TouchableOpacity, {
856
+ style: [styles.batchSizePreset, settings.debugLogLevel === preset.value && styles.batchSizePresetActive, preset.value !== "off" && settings.debugLogLevel === preset.value && {
857
+ backgroundColor: buoyColors.warning + "30",
858
+ borderColor: buoyColors.warning
859
+ }],
860
+ onPress: () => onSettingsChange({
861
+ debugLogLevel: preset.value
862
+ }),
863
+ children: /*#__PURE__*/_jsx(Text, {
864
+ style: [styles.batchSizePresetText, settings.debugLogLevel === preset.value && styles.batchSizePresetTextActive, preset.value !== "off" && settings.debugLogLevel === preset.value && {
865
+ color: buoyColors.warning
866
+ }],
867
+ children: preset.label
868
+ })
869
+ }, preset.value))
870
+ }), /*#__PURE__*/_jsxs(Text, {
871
+ style: styles.settingDescriptionMuted,
872
+ children: [DEBUG_LOG_LEVEL_PRESETS.find(p => p.value === settings.debugLogLevel)?.description, settings.debugLogLevel !== "off" && " • Check Metro console for logs"]
873
+ })]
874
+ }), /*#__PURE__*/_jsxs(View, {
875
+ style: [styles.settingItem, styles.settingItemSpaced],
876
+ children: [/*#__PURE__*/_jsxs(View, {
877
+ style: styles.settingHeader,
878
+ children: [/*#__PURE__*/_jsx(Text, {
879
+ style: styles.settingLabel,
880
+ children: "Batch Size"
881
+ }), /*#__PURE__*/_jsx(View, {
882
+ style: styles.settingValue,
883
+ children: /*#__PURE__*/_jsx(Text, {
884
+ style: styles.settingValueText,
885
+ children: settings.batchSize
886
+ })
887
+ })]
888
+ }), /*#__PURE__*/_jsx(Text, {
889
+ style: styles.settingDescription,
890
+ children: "Maximum components to highlight per render update. Higher values capture more re-renders but may impact performance on complex screens."
891
+ }), /*#__PURE__*/_jsx(View, {
892
+ style: styles.batchSizePresets,
893
+ children: BATCH_SIZE_PRESETS.map(preset => /*#__PURE__*/_jsx(TouchableOpacity, {
894
+ style: [styles.batchSizePreset, settings.batchSize === preset.value && styles.batchSizePresetActive],
895
+ onPress: () => onSettingsChange({
896
+ batchSize: preset.value
897
+ }),
898
+ children: /*#__PURE__*/_jsx(Text, {
899
+ style: [styles.batchSizePresetText, settings.batchSize === preset.value && styles.batchSizePresetTextActive],
900
+ children: preset.label
901
+ })
902
+ }, preset.value))
903
+ })]
904
+ }), /*#__PURE__*/_jsxs(View, {
905
+ style: [styles.settingItem, styles.settingItemSpaced],
906
+ children: [/*#__PURE__*/_jsxs(View, {
907
+ style: styles.settingHeader,
908
+ children: [/*#__PURE__*/_jsx(Text, {
909
+ style: styles.settingLabel,
910
+ children: "Highlight Dev Tools"
911
+ }), /*#__PURE__*/_jsx(Switch, {
912
+ value: !settings.excludeDevTools,
913
+ onValueChange: value => onSettingsChange({
914
+ excludeDevTools: !value
915
+ }),
916
+ trackColor: {
917
+ false: buoyColors.input,
918
+ true: buoyColors.primary + "80"
919
+ },
920
+ thumbColor: !settings.excludeDevTools ? buoyColors.primary : buoyColors.textMuted
921
+ })]
922
+ }), /*#__PURE__*/_jsxs(Text, {
923
+ style: styles.settingDescription,
924
+ children: ["Show re-render highlights on Buoy dev tools (floating menu, modals, etc.). Useful for optimizing the dev tools themselves.", !settings.excludeDevTools && /*#__PURE__*/_jsxs(Text, {
925
+ style: styles.settingWarning,
926
+ children: ["\n", "The highlight overlay is always excluded to prevent infinite loops."]
927
+ })]
928
+ })]
929
+ })]
930
+ })]
931
+ })
932
+ })
933
+ })
934
+ });
935
+ }
936
+ const styles = StyleSheet.create({
937
+ container: {
938
+ flex: 1,
939
+ backgroundColor: buoyColors.base
940
+ },
941
+ scrollView: {
942
+ flex: 1
943
+ },
944
+ scrollContent: {
945
+ paddingHorizontal: 16,
946
+ paddingTop: 12,
947
+ paddingBottom: 32
948
+ },
949
+ section: {
950
+ backgroundColor: buoyColors.card,
951
+ borderRadius: 8,
952
+ borderWidth: 1,
953
+ borderColor: buoyColors.border + "50",
954
+ marginBottom: 12,
955
+ overflow: "hidden"
956
+ },
957
+ sectionDescription: {
958
+ fontSize: 11,
959
+ color: buoyColors.textSecondary,
960
+ paddingHorizontal: 16,
961
+ paddingTop: 8,
962
+ lineHeight: 16
963
+ },
964
+ patternChips: {
965
+ flexDirection: "row",
966
+ flexWrap: "wrap",
967
+ gap: 8,
968
+ paddingHorizontal: 16,
969
+ paddingTop: 12
970
+ },
971
+ patternChip: {
972
+ flexDirection: "row",
973
+ alignItems: "center",
974
+ backgroundColor: buoyColors.input,
975
+ borderRadius: 6,
976
+ borderWidth: 1,
977
+ paddingVertical: 4,
978
+ paddingLeft: 4,
979
+ paddingRight: 6,
980
+ maxWidth: "100%",
981
+ gap: 4
982
+ },
983
+ patternChipBadge: {
984
+ paddingVertical: 2,
985
+ paddingHorizontal: 5,
986
+ borderRadius: 4
987
+ },
988
+ patternChipBadgeText: {
989
+ fontSize: 9,
990
+ fontWeight: "700"
991
+ },
992
+ patternChipValue: {
993
+ fontSize: 11,
994
+ color: buoyColors.text,
995
+ fontFamily: "monospace",
996
+ flexShrink: 1
997
+ },
998
+ patternChipX: {
999
+ marginLeft: 2
1000
+ },
1001
+ addPatternRow: {
1002
+ paddingHorizontal: 16,
1003
+ paddingTop: 12,
1004
+ paddingBottom: 16
1005
+ },
1006
+ addButton: {
1007
+ flexDirection: "row",
1008
+ alignItems: "center",
1009
+ justifyContent: "center",
1010
+ paddingVertical: 10,
1011
+ paddingHorizontal: 16,
1012
+ borderRadius: 8,
1013
+ borderWidth: 1,
1014
+ borderStyle: "dashed",
1015
+ gap: 6
1016
+ },
1017
+ addButtonText: {
1018
+ fontSize: 12,
1019
+ fontWeight: "500"
1020
+ },
1021
+ typePicker: {
1022
+ flexDirection: "row",
1023
+ alignItems: "center",
1024
+ gap: 8
1025
+ },
1026
+ typePickerRow: {
1027
+ flex: 1,
1028
+ flexDirection: "row",
1029
+ flexWrap: "wrap",
1030
+ gap: 8
1031
+ },
1032
+ typeOption: {
1033
+ flexDirection: "row",
1034
+ alignItems: "center",
1035
+ paddingVertical: 8,
1036
+ paddingHorizontal: 12,
1037
+ borderRadius: 6,
1038
+ borderWidth: 1,
1039
+ backgroundColor: buoyColors.input,
1040
+ gap: 6
1041
+ },
1042
+ typeOptionText: {
1043
+ fontSize: 11,
1044
+ fontWeight: "600"
1045
+ },
1046
+ typePickerCancel: {
1047
+ padding: 8
1048
+ },
1049
+ patternInputContainer: {
1050
+ flexDirection: "row",
1051
+ alignItems: "center",
1052
+ backgroundColor: buoyColors.input,
1053
+ borderRadius: 8,
1054
+ borderWidth: 1,
1055
+ borderColor: buoyColors.border,
1056
+ paddingLeft: 4,
1057
+ paddingRight: 8,
1058
+ paddingVertical: 4,
1059
+ gap: 4
1060
+ },
1061
+ patternInput: {
1062
+ flex: 1,
1063
+ fontSize: 12,
1064
+ color: buoyColors.text,
1065
+ paddingVertical: 6,
1066
+ paddingHorizontal: 4
1067
+ },
1068
+ addPatternButton: {
1069
+ paddingVertical: 6,
1070
+ paddingHorizontal: 10,
1071
+ borderRadius: 4
1072
+ },
1073
+ addPatternButtonText: {
1074
+ fontSize: 11,
1075
+ fontWeight: "600"
1076
+ },
1077
+ cancelButton: {
1078
+ padding: 4
1079
+ },
1080
+ categoryBadgeScroll: {
1081
+ marginTop: 12
1082
+ },
1083
+ categoryBadgeScrollContent: {
1084
+ paddingHorizontal: 16,
1085
+ gap: 8
1086
+ },
1087
+ categoryBadge: {
1088
+ flexDirection: "row",
1089
+ alignItems: "center",
1090
+ paddingVertical: 8,
1091
+ paddingLeft: 10,
1092
+ paddingRight: 6,
1093
+ borderRadius: 8,
1094
+ borderWidth: 1,
1095
+ gap: 6
1096
+ },
1097
+ categoryBadgeText: {
1098
+ fontSize: 11,
1099
+ fontWeight: "600"
1100
+ },
1101
+ categoryBadgeCountBubble: {
1102
+ paddingHorizontal: 6,
1103
+ paddingVertical: 2,
1104
+ borderRadius: 10,
1105
+ minWidth: 20,
1106
+ alignItems: "center"
1107
+ },
1108
+ categoryBadgeCount: {
1109
+ fontSize: 10,
1110
+ fontWeight: "600"
1111
+ },
1112
+ detectedItemsContainer: {
1113
+ paddingHorizontal: 16,
1114
+ paddingTop: 12,
1115
+ paddingBottom: 16
1116
+ },
1117
+ detectedItemsScroll: {
1118
+ maxHeight: 200
1119
+ },
1120
+ detectedItems: {
1121
+ flexDirection: "row",
1122
+ flexWrap: "wrap",
1123
+ gap: 8
1124
+ },
1125
+ detectedItem: {
1126
+ flexDirection: "row",
1127
+ alignItems: "center",
1128
+ backgroundColor: buoyColors.input,
1129
+ borderRadius: 6,
1130
+ borderWidth: 1,
1131
+ paddingVertical: 6,
1132
+ paddingHorizontal: 10,
1133
+ gap: 6
1134
+ },
1135
+ detectedItemText: {
1136
+ fontSize: 11,
1137
+ color: buoyColors.text,
1138
+ fontFamily: "monospace"
1139
+ },
1140
+ emptyText: {
1141
+ fontSize: 11,
1142
+ color: buoyColors.textMuted,
1143
+ fontStyle: "italic",
1144
+ textAlign: "center",
1145
+ paddingVertical: 16,
1146
+ paddingHorizontal: 16
1147
+ },
1148
+ howItWorks: {
1149
+ paddingHorizontal: 16,
1150
+ paddingVertical: 12
1151
+ },
1152
+ howItWorksText: {
1153
+ fontSize: 11,
1154
+ color: buoyColors.textMuted,
1155
+ lineHeight: 18,
1156
+ fontFamily: "monospace"
1157
+ },
1158
+ howItWorksBold: {
1159
+ fontWeight: "700",
1160
+ color: buoyColors.textSecondary
1161
+ },
1162
+ // Action popup modal styles
1163
+ modalOverlay: {
1164
+ flex: 1,
1165
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
1166
+ justifyContent: "center",
1167
+ alignItems: "center",
1168
+ padding: 32
1169
+ },
1170
+ actionPopup: {
1171
+ backgroundColor: buoyColors.card,
1172
+ borderRadius: 12,
1173
+ borderWidth: 1,
1174
+ borderColor: buoyColors.border,
1175
+ width: "100%",
1176
+ maxWidth: 300,
1177
+ overflow: "hidden"
1178
+ },
1179
+ actionPopupHeader: {
1180
+ padding: 16,
1181
+ borderBottomWidth: 1,
1182
+ borderBottomColor: buoyColors.border + "50",
1183
+ alignItems: "center"
1184
+ },
1185
+ actionPopupButtons: {
1186
+ flexDirection: "row",
1187
+ padding: 12,
1188
+ gap: 8
1189
+ },
1190
+ actionPopupButton: {
1191
+ flex: 1,
1192
+ flexDirection: "row",
1193
+ alignItems: "center",
1194
+ justifyContent: "center",
1195
+ paddingVertical: 12,
1196
+ paddingHorizontal: 12,
1197
+ borderRadius: 8,
1198
+ gap: 8
1199
+ },
1200
+ actionPopupInclude: {
1201
+ backgroundColor: buoyColors.success + "15"
1202
+ },
1203
+ actionPopupExclude: {
1204
+ backgroundColor: buoyColors.primary + "15"
1205
+ },
1206
+ actionPopupButtonText: {
1207
+ fontSize: 13,
1208
+ fontWeight: "600"
1209
+ },
1210
+ actionPopupCancel: {
1211
+ padding: 12,
1212
+ borderTopWidth: 1,
1213
+ borderTopColor: buoyColors.border + "50",
1214
+ alignItems: "center"
1215
+ },
1216
+ actionPopupCancelText: {
1217
+ fontSize: 13,
1218
+ color: buoyColors.textMuted,
1219
+ fontWeight: "500"
1220
+ },
1221
+ // Settings styles
1222
+ settingsSection: {
1223
+ paddingHorizontal: 16,
1224
+ paddingTop: 8,
1225
+ paddingBottom: 16
1226
+ },
1227
+ settingItem: {
1228
+ gap: 8
1229
+ },
1230
+ settingItemSpaced: {
1231
+ marginTop: 16,
1232
+ paddingTop: 16,
1233
+ borderTopWidth: 1,
1234
+ borderTopColor: buoyColors.border + "30"
1235
+ },
1236
+ settingHeader: {
1237
+ flexDirection: "row",
1238
+ alignItems: "center",
1239
+ justifyContent: "space-between"
1240
+ },
1241
+ settingLabel: {
1242
+ fontSize: 13,
1243
+ fontWeight: "600",
1244
+ color: buoyColors.text
1245
+ },
1246
+ settingValue: {
1247
+ backgroundColor: buoyColors.textMuted + "20",
1248
+ paddingHorizontal: 10,
1249
+ paddingVertical: 4,
1250
+ borderRadius: 6
1251
+ },
1252
+ settingValueText: {
1253
+ fontSize: 12,
1254
+ fontWeight: "700",
1255
+ color: buoyColors.textMuted,
1256
+ fontFamily: "monospace"
1257
+ },
1258
+ settingDescription: {
1259
+ fontSize: 11,
1260
+ color: buoyColors.textSecondary,
1261
+ lineHeight: 16
1262
+ },
1263
+ settingDescriptionMuted: {
1264
+ fontSize: 10,
1265
+ color: buoyColors.textMuted,
1266
+ lineHeight: 14,
1267
+ marginTop: 4,
1268
+ fontStyle: "italic"
1269
+ },
1270
+ settingLabelDisabled: {
1271
+ color: buoyColors.textMuted
1272
+ },
1273
+ settingWarning: {
1274
+ color: buoyColors.warning,
1275
+ fontWeight: "500"
1276
+ },
1277
+ batchSizePresets: {
1278
+ flexDirection: "row",
1279
+ flexWrap: "wrap",
1280
+ gap: 8,
1281
+ marginTop: 4
1282
+ },
1283
+ batchSizePreset: {
1284
+ paddingVertical: 8,
1285
+ paddingHorizontal: 14,
1286
+ borderRadius: 6,
1287
+ backgroundColor: buoyColors.input,
1288
+ borderWidth: 1,
1289
+ borderColor: buoyColors.border + "50"
1290
+ },
1291
+ batchSizePresetActive: {
1292
+ backgroundColor: buoyColors.textMuted + "20",
1293
+ borderColor: buoyColors.textMuted
1294
+ },
1295
+ batchSizePresetText: {
1296
+ fontSize: 12,
1297
+ fontWeight: "500",
1298
+ color: buoyColors.textSecondary,
1299
+ fontFamily: "monospace"
1300
+ },
1301
+ batchSizePresetTextActive: {
1302
+ color: buoyColors.textMuted,
1303
+ fontWeight: "700"
1304
+ },
1305
+ // Render count range styles
1306
+ renderCountRangeContainer: {
1307
+ paddingHorizontal: 16,
1308
+ paddingTop: 12,
1309
+ paddingBottom: 16,
1310
+ gap: 12
1311
+ },
1312
+ renderCountInputRow: {
1313
+ flexDirection: "row",
1314
+ alignItems: "center",
1315
+ gap: 12
1316
+ },
1317
+ renderCountInputGroup: {
1318
+ flex: 1,
1319
+ gap: 4
1320
+ },
1321
+ renderCountLabel: {
1322
+ fontSize: 10,
1323
+ fontWeight: "600",
1324
+ color: buoyColors.textMuted,
1325
+ textTransform: "uppercase",
1326
+ letterSpacing: 0.5
1327
+ },
1328
+ renderCountInput: {
1329
+ backgroundColor: buoyColors.input,
1330
+ borderRadius: 8,
1331
+ borderWidth: 1,
1332
+ borderColor: buoyColors.border,
1333
+ paddingVertical: 10,
1334
+ paddingHorizontal: 12,
1335
+ fontSize: 14,
1336
+ fontWeight: "600",
1337
+ color: buoyColors.text,
1338
+ fontFamily: "monospace",
1339
+ textAlign: "center"
1340
+ },
1341
+ renderCountSeparator: {
1342
+ fontSize: 12,
1343
+ color: buoyColors.textMuted,
1344
+ marginTop: 18
1345
+ },
1346
+ clearRangeButton: {
1347
+ flexDirection: "row",
1348
+ alignItems: "center",
1349
+ justifyContent: "center",
1350
+ paddingVertical: 8,
1351
+ paddingHorizontal: 12,
1352
+ borderRadius: 6,
1353
+ backgroundColor: buoyColors.warning + "15",
1354
+ borderWidth: 1,
1355
+ borderColor: buoyColors.warning + "40",
1356
+ gap: 6,
1357
+ alignSelf: "center"
1358
+ },
1359
+ clearRangeButtonText: {
1360
+ fontSize: 11,
1361
+ fontWeight: "600",
1362
+ color: buoyColors.warning
1363
+ }
1364
+ });
1365
+ export default HighlightFilterView;