// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. import React, {forwardRef} from 'react'; import Animated, {useAnimatedStyle, useDerivedValue} from 'react-native-reanimated'; import {SEARCH_INPUT_HEIGHT, SEARCH_INPUT_MARGIN} from '@constants/view'; import {useTheme} from '@context/theme'; import useHeaderHeight, {MAX_OVERSCROLL} from '@hooks/header'; import {clamp} from '@utils/gallery'; import {makeStyleSheetFromTheme} from '@utils/theme'; import Header, {type HeaderRightButton} from './header'; import NavigationHeaderLargeTitle from './large'; import NavigationSearch from './search'; import type {SearchProps, SearchRef} from '@components/search'; type Props = SearchProps & { hasSearch?: boolean; isLargeTitle?: boolean; leftComponent?: React.ReactElement; onBackPress?: () => void; onTitlePress?: () => void; rightButtons?: HeaderRightButton[]; scrollValue?: Animated.SharedValue; lockValue?: number; hideHeader?: () => void; showBackButton?: boolean; subtitle?: string; subtitleCompanion?: React.ReactElement; title?: string; titleCompanion?: React.ReactElement; } const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ container: { backgroundColor: theme.sidebarBg, position: 'absolute', width: '100%', zIndex: 10, }, })); const NavigationHeader = forwardRef(({ hasSearch = false, isLargeTitle = false, leftComponent, onBackPress, onTitlePress, rightButtons, scrollValue, lockValue, showBackButton, subtitle, subtitleCompanion, title = '', titleCompanion, hideHeader, ...searchProps }: Props, ref) => { const theme = useTheme(); const styles = getStyleSheet(theme); const {largeHeight, defaultHeight, headerOffset} = useHeaderHeight(); const minScrollValue = useDerivedValue(() => scrollValue?.value || 0, [scrollValue]); const containerHeight = useAnimatedStyle(() => { const calculatedHeight = (isLargeTitle ? largeHeight : defaultHeight) - minScrollValue.value; const height = lockValue || calculatedHeight; return { height: Math.max(height, defaultHeight), minHeight: defaultHeight, maxHeight: largeHeight + MAX_OVERSCROLL, }; }, [defaultHeight, largeHeight, lockValue, isLargeTitle]); const translateY = useDerivedValue(() => ( lockValue ? -lockValue : Math.min(-minScrollValue.value, headerOffset) ), [lockValue, headerOffset]); const searchTopStyle = useAnimatedStyle(() => { const margin = clamp(-minScrollValue.value, -headerOffset, headerOffset); const marginTop = (lockValue ? -lockValue : margin) - SEARCH_INPUT_HEIGHT - SEARCH_INPUT_MARGIN; return {marginTop}; }, [lockValue, headerOffset]); return (
{isLargeTitle && } {hasSearch && } ); }); NavigationHeader.displayName = 'NavHeader'; export default NavigationHeader;