import { Route, useTheme } from '@react-navigation/native'; import * as React from 'react'; import { Platform } from 'react-native'; import { SearchBarProps } from '../../types'; import { isSearchBarAvailableForCurrentPlatform, executeNativeBackPress, } from '../../utils'; import { ScreenStackHeaderBackButtonImage, ScreenStackHeaderCenterView, ScreenStackHeaderConfig, ScreenStackHeaderLeftView, ScreenStackHeaderRightView, ScreenStackHeaderSearchBarView, } from '../../components/ScreenStackHeaderConfig'; import SearchBar from '../../components/SearchBar'; import { NativeStackNavigationOptions } from '../types'; import { useBackPressSubscription } from '../utils/useBackPressSubscription'; import { processFonts } from './FontProcessor'; import warnOnce from 'warn-once'; type Props = NativeStackNavigationOptions & { route: Route; }; export default function HeaderConfig({ backButtonImage, backButtonInCustomView, direction, disableBackButtonMenu, backButtonDisplayMode = 'default', headerBackTitle, headerBackTitleStyle = {}, headerBackTitleVisible = true, headerCenter, headerHideBackButton, headerHideShadow, headerLargeStyle = {}, headerLargeTitle, headerLargeTitleHideShadow, headerLargeTitleStyle = {}, headerLeft, headerRight, headerShown, headerStyle = {}, headerTintColor, headerTitle, headerTitleStyle = {}, headerTopInsetEnabled = true, headerTranslucent, route, searchBar, title, }: Props): JSX.Element { const { colors } = useTheme(); const tintColor = headerTintColor ?? colors.primary; // We need to use back press subscription here to override back button behavior on JS side. // Because screens are usually used with react-navigation and this library overrides back button // we need to handle it first in case when search bar is open const { handleAttached, handleDetached, clearSubscription, createSubscription, } = useBackPressSubscription({ onBackPress: executeNativeBackPress, isDisabled: !searchBar || !!searchBar.disableBackButtonOverride, }); const [backTitleFontFamily, largeTitleFontFamily, titleFontFamily] = processFonts([ headerBackTitleStyle.fontFamily, headerLargeTitleStyle.fontFamily, headerTitleStyle.fontFamily, ]); // We want to clear clearSubscription only when components unmounts or search bar changes // eslint-disable-next-line react-hooks/exhaustive-deps React.useEffect(() => clearSubscription, [searchBar]); const processedSearchBarOptions = React.useMemo(() => { if ( Platform.OS === 'android' && searchBar && !searchBar.disableBackButtonOverride ) { const onFocus: SearchBarProps['onFocus'] = (...args) => { createSubscription(); searchBar.onFocus?.(...args); }; const onClose: SearchBarProps['onClose'] = (...args) => { clearSubscription(); searchBar.onClose?.(...args); }; return { ...searchBar, onFocus, onClose }; } return searchBar; }, [searchBar, createSubscription, clearSubscription]); // @ts-ignore isVision is not yet in the type definitions (RN 0.74+) const isVisionOS = Platform?.isVision; warnOnce( isVisionOS && (headerTitleStyle.color !== undefined || headerTintColor !== undefined), 'headerTitleStyle.color and headerTintColor are not supported on visionOS.', ); return ( ); }