@buoy-gg/highlight-updates 7.0.38 → 7.0.40

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