mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-03-06 22:39:41 +08:00
refactor: move more header stuff to elements package
This commit is contained in:
@@ -14,10 +14,10 @@ import {
|
||||
createStackNavigator,
|
||||
StackScreenProps,
|
||||
HeaderBackground,
|
||||
useHeaderHeight,
|
||||
Header,
|
||||
StackHeaderProps,
|
||||
} from '@react-navigation/stack';
|
||||
import { useHeaderHeight } from '@react-navigation/elements';
|
||||
import BlurView from '../Shared/BlurView';
|
||||
import Article from '../Shared/Article';
|
||||
import Albums from '../Shared/Albums';
|
||||
|
||||
@@ -11,6 +11,7 @@ import type {
|
||||
DrawerActionHelpers,
|
||||
RouteProp,
|
||||
} from '@react-navigation/native';
|
||||
import type { HeaderOptions } from '@react-navigation/elements';
|
||||
|
||||
export type Scene = {
|
||||
route: Route<string>;
|
||||
@@ -34,79 +35,7 @@ export type DrawerNavigationConfig = {
|
||||
detachInactiveScreens?: boolean;
|
||||
};
|
||||
|
||||
export type DrawerHeaderOptions = {
|
||||
/**
|
||||
* String or a function that returns a React Element to be used by the header.
|
||||
* Defaults to scene `title`.
|
||||
* It receives `allowFontScaling`, `tintColor`, `style` and `children` in the options object as an argument.
|
||||
* The title string is passed in `children`.
|
||||
*/
|
||||
headerTitle?:
|
||||
| string
|
||||
| ((props: {
|
||||
/**
|
||||
* Whether title font should scale to respect Text Size accessibility settings.
|
||||
*/
|
||||
allowFontScaling?: boolean;
|
||||
/**
|
||||
* Tint color for the header.
|
||||
*/
|
||||
tintColor?: string;
|
||||
/**
|
||||
* Content of the title element. Usually the title string.
|
||||
*/
|
||||
children?: string;
|
||||
/**
|
||||
* Style object for the title element.
|
||||
*/
|
||||
style?: StyleProp<TextStyle>;
|
||||
}) => React.ReactNode);
|
||||
/**
|
||||
* How to align the the header title.
|
||||
* Defaults to `center` on iOS and `left` on Android.
|
||||
*/
|
||||
headerTitleAlign?: 'left' | 'center';
|
||||
/**
|
||||
* Style object for the title component.
|
||||
*/
|
||||
headerTitleStyle?: StyleProp<TextStyle>;
|
||||
/**
|
||||
* Whether header title font should scale to respect Text Size accessibility settings. Defaults to `false`.
|
||||
*/
|
||||
headerTitleAllowFontScaling?: boolean;
|
||||
/**
|
||||
* Function which returns a React Element to display on the left side of the header.
|
||||
*/
|
||||
headerLeft?: (props: { tintColor?: string }) => React.ReactNode;
|
||||
/**
|
||||
* Accessibility label for the header left button.
|
||||
*/
|
||||
headerLeftAccessibilityLabel?: string;
|
||||
/**
|
||||
* Function which returns a React Element to display on the right side of the header.
|
||||
*/
|
||||
headerRight?: (props: { tintColor?: string }) => React.ReactNode;
|
||||
/**
|
||||
* Color for material ripple (Android >= 5.0 only).
|
||||
*/
|
||||
headerPressColorAndroid?: string;
|
||||
/**
|
||||
* Tint color for the header.
|
||||
*/
|
||||
headerTintColor?: string;
|
||||
/**
|
||||
* Style object for the header. You can specify a custom background color here, for example.
|
||||
*/
|
||||
headerStyle?: StyleProp<ViewStyle>;
|
||||
/**
|
||||
* Extra padding to add at the top of header to account for translucent status bar.
|
||||
* By default, it uses the top value from the safe area insets of the device.
|
||||
* Pass 0 or a custom value to disable the default behaviour, and customize the height.
|
||||
*/
|
||||
headerStatusBarHeight?: number;
|
||||
};
|
||||
|
||||
export type DrawerNavigationOptions = DrawerHeaderOptions & {
|
||||
export type DrawerNavigationOptions = HeaderOptions & {
|
||||
/**
|
||||
* Title text for the screen.
|
||||
*/
|
||||
|
||||
54
packages/drawer/src/views/DrawerToggleButton.tsx
Normal file
54
packages/drawer/src/views/DrawerToggleButton.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
import * as React from 'react';
|
||||
import { Image, Platform, StyleSheet } from 'react-native';
|
||||
import { PlatformPressable } from '@react-navigation/elements';
|
||||
import {
|
||||
useNavigation,
|
||||
DrawerActions,
|
||||
ParamListBase,
|
||||
} from '@react-navigation/native';
|
||||
import type { DrawerNavigationProp } from '../types';
|
||||
|
||||
type Props = {
|
||||
accessibilityLabel?: string;
|
||||
pressColor?: string;
|
||||
pressOpacity?: number;
|
||||
tintColor?: string;
|
||||
};
|
||||
|
||||
export default function DrawerToggleButton({ tintColor, ...rest }: Props) {
|
||||
const navigation = useNavigation<DrawerNavigationProp<ParamListBase>>();
|
||||
|
||||
return (
|
||||
<PlatformPressable
|
||||
{...rest}
|
||||
accessible
|
||||
accessibilityRole="button"
|
||||
delayPressIn={0}
|
||||
onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}
|
||||
style={styles.touchable}
|
||||
hitSlop={Platform.select({
|
||||
ios: undefined,
|
||||
default: { top: 16, right: 16, bottom: 16, left: 16 },
|
||||
})}
|
||||
borderless
|
||||
>
|
||||
<Image
|
||||
style={[styles.icon, tintColor ? { tintColor } : null]}
|
||||
source={require('./assets/toggle-drawer-icon.png')}
|
||||
fadeDuration={0}
|
||||
/>
|
||||
</PlatformPressable>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
icon: {
|
||||
height: 24,
|
||||
width: 24,
|
||||
margin: 3,
|
||||
resizeMode: 'contain',
|
||||
},
|
||||
touchable: {
|
||||
marginHorizontal: 11,
|
||||
},
|
||||
});
|
||||
@@ -8,7 +8,10 @@ import {
|
||||
NativeEventSubscription,
|
||||
} from 'react-native';
|
||||
import { ScreenContainer } from 'react-native-screens';
|
||||
import { useSafeAreaFrame } from 'react-native-safe-area-context';
|
||||
import {
|
||||
useSafeAreaFrame,
|
||||
useSafeAreaInsets,
|
||||
} from 'react-native-safe-area-context';
|
||||
import {
|
||||
NavigationHelpersContext,
|
||||
NavigationContext,
|
||||
@@ -18,11 +21,11 @@ import {
|
||||
useTheme,
|
||||
ParamListBase,
|
||||
} from '@react-navigation/native';
|
||||
import { SafeAreaProviderCompat } from '@react-navigation/elements';
|
||||
import { Header, SafeAreaProviderCompat } from '@react-navigation/elements';
|
||||
|
||||
import { GestureHandlerRootView } from './GestureHandler';
|
||||
import ScreenFallback from './ScreenFallback';
|
||||
import Header from './Header';
|
||||
import DrawerToggleButton from './DrawerToggleButton';
|
||||
import DrawerContent from './DrawerContent';
|
||||
import Drawer from './Drawer';
|
||||
import DrawerStatusContext from '../utils/DrawerStatusContext';
|
||||
@@ -93,7 +96,9 @@ function DrawerViewBase({
|
||||
} = descriptors[activeKey].options;
|
||||
|
||||
const [loaded, setLoaded] = React.useState([activeKey]);
|
||||
|
||||
const dimensions = useSafeAreaFrame();
|
||||
const insets = useSafeAreaInsets();
|
||||
|
||||
const { colors } = useTheme();
|
||||
|
||||
@@ -149,6 +154,12 @@ function DrawerViewBase({
|
||||
);
|
||||
};
|
||||
|
||||
const [headerHeights, setHeaderHeights] = React.useState<
|
||||
Record<string, number>
|
||||
>({});
|
||||
|
||||
const isParentHeaderShown = React.useContext(Header.ShownContext);
|
||||
|
||||
const renderSceneContent = () => {
|
||||
return (
|
||||
// @ts-ignore
|
||||
@@ -168,10 +179,32 @@ function DrawerViewBase({
|
||||
}
|
||||
|
||||
const {
|
||||
header = (props: DrawerHeaderProps) => <Header {...props} />,
|
||||
header = ({ layout, options }: DrawerHeaderProps) => (
|
||||
<Header
|
||||
{...options}
|
||||
layout={layout}
|
||||
headerTitle={
|
||||
options.headerTitle !== undefined
|
||||
? options.headerTitle
|
||||
: options.title !== undefined
|
||||
? options.title
|
||||
: route.name
|
||||
}
|
||||
headerLeft={
|
||||
options.headerLeft ??
|
||||
((props) => <DrawerToggleButton {...props} />)
|
||||
}
|
||||
/>
|
||||
),
|
||||
headerShown = true,
|
||||
headerStatusBarHeight = isParentHeaderShown ? 0 : insets.top,
|
||||
} = descriptor.options;
|
||||
|
||||
const headerHeight = headerShown
|
||||
? headerHeights[route.key] ??
|
||||
Header.getDefaultHeight(dimensions, headerStatusBarHeight)
|
||||
: 0;
|
||||
|
||||
return (
|
||||
<ScreenFallback
|
||||
key={route.key}
|
||||
@@ -182,16 +215,36 @@ function DrawerViewBase({
|
||||
{headerShown ? (
|
||||
<NavigationContext.Provider value={descriptor.navigation}>
|
||||
<NavigationRouteContext.Provider value={route}>
|
||||
{header({
|
||||
layout: dimensions,
|
||||
route: descriptor.route,
|
||||
navigation: descriptor.navigation as DrawerNavigationProp<ParamListBase>,
|
||||
options: descriptor.options,
|
||||
})}
|
||||
<View
|
||||
onLayout={(e) => {
|
||||
const { height } = e.nativeEvent.layout;
|
||||
|
||||
setHeaderHeights((heights) => {
|
||||
if (heights[route.key] === height) {
|
||||
return heights;
|
||||
}
|
||||
|
||||
return { ...heights, [route.key]: height };
|
||||
});
|
||||
}}
|
||||
>
|
||||
{header({
|
||||
layout: dimensions,
|
||||
route: descriptor.route,
|
||||
navigation: descriptor.navigation as DrawerNavigationProp<ParamListBase>,
|
||||
options: descriptor.options,
|
||||
})}
|
||||
</View>
|
||||
</NavigationRouteContext.Provider>
|
||||
</NavigationContext.Provider>
|
||||
) : null}
|
||||
{descriptor.render()}
|
||||
<Header.ShownContext.Provider
|
||||
value={isParentHeaderShown || headerShown !== false}
|
||||
>
|
||||
<Header.HeightContext.Provider value={headerHeight}>
|
||||
{descriptor.render()}
|
||||
</Header.HeightContext.Provider>
|
||||
</Header.ShownContext.Provider>
|
||||
</ScreenFallback>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-navigation/native": "^5.0.5",
|
||||
"react": "*",
|
||||
"react-native": "*",
|
||||
"react-native-safe-area-context": ">= 3.0.0"
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
import * as React from 'react';
|
||||
import { Text, View, Image, StyleSheet, Platform } from 'react-native';
|
||||
import { Text, View, StyleSheet, Platform } from 'react-native';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { PlatformPressable } from '@react-navigation/elements';
|
||||
import { DrawerActions, useTheme } from '@react-navigation/native';
|
||||
import type { Layout, DrawerHeaderProps } from '../types';
|
||||
import { useTheme } from '@react-navigation/native';
|
||||
import HeaderShownContext from './HeaderShownContext';
|
||||
import HeaderHeightContext from './HeaderHeightContext';
|
||||
import type { HeaderOptions } from './types';
|
||||
|
||||
export const getDefaultHeaderHeight = (
|
||||
layout: Layout,
|
||||
statusBarHeight: number
|
||||
): number => {
|
||||
type Layout = { width: number; height: number };
|
||||
|
||||
type Props = HeaderOptions & {
|
||||
/**
|
||||
* Layout of the screen.
|
||||
*/
|
||||
layout: Layout;
|
||||
};
|
||||
|
||||
const getDefaultHeight = (layout: Layout, statusBarHeight: number): number => {
|
||||
const isLandscape = layout.width > layout.height;
|
||||
|
||||
let headerHeight;
|
||||
@@ -28,17 +35,14 @@ export const getDefaultHeaderHeight = (
|
||||
return headerHeight + statusBarHeight;
|
||||
};
|
||||
|
||||
export default function HeaderSegment({
|
||||
route,
|
||||
navigation,
|
||||
options,
|
||||
layout,
|
||||
}: DrawerHeaderProps) {
|
||||
export default function Header(props: Props) {
|
||||
const insets = useSafeAreaInsets();
|
||||
const { colors } = useTheme();
|
||||
|
||||
const isParentHeaderShown = React.useContext(HeaderShownContext);
|
||||
|
||||
const {
|
||||
title,
|
||||
layout,
|
||||
headerTitle,
|
||||
headerTitleAlign = Platform.select({
|
||||
ios: 'center',
|
||||
@@ -47,52 +51,34 @@ export default function HeaderSegment({
|
||||
headerLeft,
|
||||
headerLeftAccessibilityLabel,
|
||||
headerRight,
|
||||
headerRightAccessibilityLabel,
|
||||
headerPressColor,
|
||||
headerPressOpacity,
|
||||
headerTitleAllowFontScaling,
|
||||
headerTitleStyle,
|
||||
headerTintColor,
|
||||
headerPressColorAndroid,
|
||||
headerStyle,
|
||||
headerStatusBarHeight = insets.top,
|
||||
} = options;
|
||||
headerStatusBarHeight = isParentHeaderShown ? 0 : insets.top,
|
||||
} = props;
|
||||
|
||||
const currentTitle =
|
||||
typeof headerTitle !== 'function' && headerTitle !== undefined
|
||||
? headerTitle
|
||||
: title !== undefined
|
||||
? title
|
||||
: route.name;
|
||||
const defaultHeight = getDefaultHeight(layout, headerStatusBarHeight);
|
||||
|
||||
const defaultHeight = getDefaultHeaderHeight(layout, headerStatusBarHeight);
|
||||
const leftButton = headerLeft
|
||||
? headerLeft({
|
||||
tintColor: headerTintColor,
|
||||
pressColor: headerPressColor,
|
||||
pressOpacity: headerPressOpacity,
|
||||
accessibilityLabel: headerLeftAccessibilityLabel,
|
||||
})
|
||||
: null;
|
||||
|
||||
const leftButton = headerLeft ? (
|
||||
headerLeft({ tintColor: headerTintColor })
|
||||
) : (
|
||||
<PlatformPressable
|
||||
accessible
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={headerLeftAccessibilityLabel}
|
||||
delayPressIn={0}
|
||||
onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}
|
||||
style={styles.touchable}
|
||||
pressColor={headerPressColorAndroid}
|
||||
hitSlop={Platform.select({
|
||||
ios: undefined,
|
||||
default: { top: 16, right: 16, bottom: 16, left: 16 },
|
||||
})}
|
||||
borderless
|
||||
>
|
||||
<Image
|
||||
style={[
|
||||
styles.icon,
|
||||
headerTintColor ? { tintColor: headerTintColor } : null,
|
||||
]}
|
||||
source={require('./assets/toggle-drawer-icon.png')}
|
||||
fadeDuration={0}
|
||||
/>
|
||||
</PlatformPressable>
|
||||
);
|
||||
const rightButton = headerRight
|
||||
? headerRight({ tintColor: headerTintColor })
|
||||
? headerRight({
|
||||
tintColor: headerTintColor,
|
||||
pressColor: headerPressColor,
|
||||
pressOpacity: headerPressOpacity,
|
||||
accessibilityLabel: headerRightAccessibilityLabel,
|
||||
})
|
||||
: null;
|
||||
|
||||
return (
|
||||
@@ -134,7 +120,6 @@ export default function HeaderSegment({
|
||||
>
|
||||
{typeof headerTitle === 'function' ? (
|
||||
headerTitle({
|
||||
children: currentTitle,
|
||||
allowFontScaling: headerTitleAllowFontScaling,
|
||||
tintColor: headerTintColor,
|
||||
style: headerTitleStyle,
|
||||
@@ -152,7 +137,7 @@ export default function HeaderSegment({
|
||||
headerTitleStyle,
|
||||
]}
|
||||
>
|
||||
{currentTitle}
|
||||
{headerTitle}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
@@ -167,6 +152,10 @@ export default function HeaderSegment({
|
||||
);
|
||||
}
|
||||
|
||||
Header.getDefaultHeight = getDefaultHeight;
|
||||
Header.ShownContext = HeaderShownContext;
|
||||
Header.HeightContext = HeaderHeightContext;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
...Platform.select({
|
||||
@@ -208,15 +197,6 @@ const styles = StyleSheet.create({
|
||||
fontWeight: '500',
|
||||
},
|
||||
}),
|
||||
icon: {
|
||||
height: 24,
|
||||
width: 24,
|
||||
margin: 3,
|
||||
resizeMode: 'contain',
|
||||
},
|
||||
touchable: {
|
||||
marginHorizontal: 11,
|
||||
},
|
||||
left: {
|
||||
flexGrow: 1,
|
||||
flexBasis: 0,
|
||||
8
packages/elements/src/HeaderHeightContext.tsx
Normal file
8
packages/elements/src/HeaderHeightContext.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
import { getNamedContext } from '@react-navigation/native';
|
||||
|
||||
const HeaderHeightContext = getNamedContext<number | undefined>(
|
||||
'HeaderHeightContext',
|
||||
undefined
|
||||
);
|
||||
|
||||
export default HeaderHeightContext;
|
||||
5
packages/elements/src/HeaderShownContext.tsx
Normal file
5
packages/elements/src/HeaderShownContext.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import { getNamedContext } from '@react-navigation/native';
|
||||
|
||||
const HeaderShownContext = getNamedContext('HeaderShownContext', false);
|
||||
|
||||
export default HeaderShownContext;
|
||||
@@ -1,3 +1,8 @@
|
||||
export { default as Header } from './Header';
|
||||
export { default as PlatformPressable } from './PlatformPressable';
|
||||
export { default as ResourceSavingScene } from './ResourceSavingScene';
|
||||
export { default as SafeAreaProviderCompat } from './SafeAreaProviderCompat';
|
||||
|
||||
export { default as useHeaderHeight } from './useHeaderHeight';
|
||||
|
||||
export * from './types';
|
||||
|
||||
87
packages/elements/src/types.tsx
Normal file
87
packages/elements/src/types.tsx
Normal file
@@ -0,0 +1,87 @@
|
||||
import type { StyleProp, ViewStyle, TextStyle } from 'react-native';
|
||||
|
||||
export type HeaderOptions = {
|
||||
/**
|
||||
* String or a function that returns a React Element to be used by the header.
|
||||
* Defaults to scene `title`.
|
||||
* It receives `allowFontScaling`, `tintColor`, `style` and `children` in the options object as an argument.
|
||||
* The title string is passed in `children`.
|
||||
*/
|
||||
headerTitle?:
|
||||
| string
|
||||
| ((props: {
|
||||
/**
|
||||
* Whether title font should scale to respect Text Size accessibility settings.
|
||||
*/
|
||||
allowFontScaling?: boolean;
|
||||
/**
|
||||
* Tint color for the header.
|
||||
*/
|
||||
tintColor?: string;
|
||||
/**
|
||||
* Style object for the title element.
|
||||
*/
|
||||
style?: StyleProp<TextStyle>;
|
||||
}) => React.ReactNode);
|
||||
/**
|
||||
* How to align the the header title.
|
||||
* Defaults to `center` on iOS and `left` on Android.
|
||||
*/
|
||||
headerTitleAlign?: 'left' | 'center';
|
||||
/**
|
||||
* Style object for the title component.
|
||||
*/
|
||||
headerTitleStyle?: StyleProp<TextStyle>;
|
||||
/**
|
||||
* Whether header title font should scale to respect Text Size accessibility settings. Defaults to `false`.
|
||||
*/
|
||||
headerTitleAllowFontScaling?: boolean;
|
||||
/**
|
||||
* Function which returns a React Element to display on the left side of the header.
|
||||
*/
|
||||
headerLeft?: (props: {
|
||||
tintColor?: string;
|
||||
pressColor?: string;
|
||||
pressOpacity?: number;
|
||||
accessibilityLabel?: string;
|
||||
}) => React.ReactNode;
|
||||
/**
|
||||
* Accessibility label for the header left button.
|
||||
*/
|
||||
headerLeftAccessibilityLabel?: string;
|
||||
/**
|
||||
* Function which returns a React Element to display on the right side of the header.
|
||||
*/
|
||||
headerRight?: (props: {
|
||||
tintColor?: string;
|
||||
pressColor?: string;
|
||||
pressOpacity?: number;
|
||||
accessibilityLabel?: string;
|
||||
}) => React.ReactNode;
|
||||
/**
|
||||
* Accessibility label for the header right button.
|
||||
*/
|
||||
headerRightAccessibilityLabel?: string;
|
||||
/**
|
||||
* Color for material ripple (Android >= 5.0 only).
|
||||
*/
|
||||
headerPressColor?: string;
|
||||
/**
|
||||
* Color for material ripple (Android >= 5.0 only).
|
||||
*/
|
||||
headerPressOpacity?: number;
|
||||
/**
|
||||
* Tint color for the header.
|
||||
*/
|
||||
headerTintColor?: string;
|
||||
/**
|
||||
* Style object for the header. You can specify a custom background color here, for example.
|
||||
*/
|
||||
headerStyle?: StyleProp<ViewStyle>;
|
||||
/**
|
||||
* Extra padding to add at the top of header to account for translucent status bar.
|
||||
* By default, it uses the top value from the safe area insets of the device.
|
||||
* Pass 0 or a custom value to disable the default behaviour, and customize the height.
|
||||
*/
|
||||
headerStatusBarHeight?: number;
|
||||
};
|
||||
@@ -1,12 +1,12 @@
|
||||
import * as React from 'react';
|
||||
import HeaderHeightContext from './HeaderHeightContext';
|
||||
|
||||
export default function useFloatingHeaderHeight() {
|
||||
export default function useHeaderHeight() {
|
||||
const height = React.useContext(HeaderHeightContext);
|
||||
|
||||
if (height === undefined) {
|
||||
throw new Error(
|
||||
"Couldn't find the header height. Are you inside a screen in Stack?"
|
||||
"Couldn't find the header height. Are you inside a screen in a navigator with a header?"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
{
|
||||
"extends": "../../tsconfig",
|
||||
"references": [
|
||||
{ "path": "../core" },
|
||||
{ "path": "../routers" },
|
||||
{ "path": "../native" }
|
||||
],
|
||||
"compilerOptions": {
|
||||
"outDir": "./lib/typescript"
|
||||
}
|
||||
|
||||
21
packages/native/src/getNamedContext.tsx
Normal file
21
packages/native/src/getNamedContext.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import * as React from 'react';
|
||||
|
||||
const contexts = new Map<string, React.Context<any>>();
|
||||
|
||||
export default function getNamedContext<T>(
|
||||
name: string,
|
||||
initialValue: T
|
||||
): React.Context<T> {
|
||||
let context = contexts.get(name);
|
||||
|
||||
if (context) {
|
||||
return context;
|
||||
}
|
||||
|
||||
context = React.createContext<T>(initialValue);
|
||||
context.displayName = name;
|
||||
|
||||
contexts.set(name, context);
|
||||
|
||||
return context;
|
||||
}
|
||||
@@ -17,4 +17,6 @@ export { default as useLinkBuilder } from './useLinkBuilder';
|
||||
|
||||
export { default as ServerContainer } from './ServerContainer';
|
||||
|
||||
export { default as getNamedContext } from './getNamedContext';
|
||||
|
||||
export * from './types';
|
||||
|
||||
@@ -38,11 +38,9 @@ export {
|
||||
* Utilities
|
||||
*/
|
||||
export { default as CardAnimationContext } from './utils/CardAnimationContext';
|
||||
export { default as HeaderHeightContext } from './utils/HeaderHeightContext';
|
||||
export { default as GestureHandlerRefContext } from './utils/GestureHandlerRefContext';
|
||||
|
||||
export { default as useCardAnimation } from './utils/useCardAnimation';
|
||||
export { default as useHeaderHeight } from './utils/useHeaderHeight';
|
||||
export { default as useGestureHandlerRef } from './utils/useGestureHandlerRef';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export default React.createContext<number | undefined>(undefined);
|
||||
@@ -1,5 +0,0 @@
|
||||
import * as React from 'react';
|
||||
|
||||
const HeaderShownContext = React.createContext(false);
|
||||
|
||||
export default HeaderShownContext;
|
||||
@@ -1,9 +1,9 @@
|
||||
import * as React from 'react';
|
||||
import { StackActions, useNavigationState } from '@react-navigation/native';
|
||||
import { Header as BaseHeader } from '@react-navigation/elements';
|
||||
|
||||
import HeaderSegment from './HeaderSegment';
|
||||
import HeaderTitle from './HeaderTitle';
|
||||
import HeaderShownContext from '../../utils/HeaderShownContext';
|
||||
import ModalPresentationContext from '../../utils/ModalPresentationContext';
|
||||
import debounce from '../../utils/debounce';
|
||||
import type { StackHeaderProps, StackHeaderTitleProps } from '../../types';
|
||||
@@ -57,7 +57,7 @@ export default React.memo(function Header({
|
||||
);
|
||||
|
||||
const isModal = React.useContext(ModalPresentationContext);
|
||||
const isParentHeaderShown = React.useContext(HeaderShownContext);
|
||||
const isParentHeaderShown = React.useContext(BaseHeader.ShownContext);
|
||||
const isFirstRouteInParent = useNavigationState(
|
||||
(state) => state.routes[0].key === route.key
|
||||
);
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
ViewStyle,
|
||||
} from 'react-native';
|
||||
import type { EdgeInsets } from 'react-native-safe-area-context';
|
||||
import { Header as BaseHeader } from '@react-navigation/elements';
|
||||
import HeaderBackButton from './HeaderBackButton';
|
||||
import HeaderBackground from './HeaderBackground';
|
||||
import memoize from '../../utils/memoize';
|
||||
@@ -51,29 +52,6 @@ const warnIfHeaderStylesDefined = (styles: Record<string, any>) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const getDefaultHeaderHeight = (
|
||||
layout: Layout,
|
||||
statusBarHeight: number
|
||||
): number => {
|
||||
const isLandscape = layout.width > layout.height;
|
||||
|
||||
let headerHeight;
|
||||
|
||||
if (Platform.OS === 'ios') {
|
||||
if (isLandscape && !Platform.isPad) {
|
||||
headerHeight = 32;
|
||||
} else {
|
||||
headerHeight = 44;
|
||||
}
|
||||
} else if (Platform.OS === 'android') {
|
||||
headerHeight = 56;
|
||||
} else {
|
||||
headerHeight = 64;
|
||||
}
|
||||
|
||||
return headerHeight + statusBarHeight;
|
||||
};
|
||||
|
||||
export default function HeaderSegment(props: Props) {
|
||||
const [leftLabelLayout, setLeftLabelLayout] = React.useState<
|
||||
Layout | undefined
|
||||
@@ -176,7 +154,10 @@ export default function HeaderSegment(props: Props) {
|
||||
styleInterpolator,
|
||||
} = props;
|
||||
|
||||
const defaultHeight = getDefaultHeaderHeight(layout, headerStatusBarHeight);
|
||||
const defaultHeight = BaseHeader.getDefaultHeight(
|
||||
layout,
|
||||
headerStatusBarHeight
|
||||
);
|
||||
|
||||
const {
|
||||
height = defaultHeight,
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import * as React from 'react';
|
||||
import { Animated, View, StyleSheet, StyleProp, ViewStyle } from 'react-native';
|
||||
import { Route, useTheme } from '@react-navigation/native';
|
||||
import { Header as BaseHeader } from '@react-navigation/elements';
|
||||
import type { Props as HeaderContainerProps } from '../Header/HeaderContainer';
|
||||
import Card from './Card';
|
||||
import { forModalPresentationIOS } from '../../TransitionConfigs/CardStyleInterpolators';
|
||||
import HeaderHeightContext from '../../utils/HeaderHeightContext';
|
||||
import HeaderShownContext from '../../utils/HeaderShownContext';
|
||||
import PreviousSceneContext from '../../utils/PreviousSceneContext';
|
||||
import ModalPresentationContext from '../../utils/ModalPresentationContext';
|
||||
import type {
|
||||
@@ -244,13 +243,13 @@ function CardContainer({
|
||||
<View style={styles.container}>
|
||||
<View style={styles.scene}>
|
||||
<PreviousSceneContext.Provider value={previousScene}>
|
||||
<HeaderShownContext.Provider
|
||||
<BaseHeader.ShownContext.Provider
|
||||
value={isParentHeaderShown || headerShown !== false}
|
||||
>
|
||||
<HeaderHeightContext.Provider value={headerHeight}>
|
||||
<BaseHeader.HeightContext.Provider value={headerHeight}>
|
||||
{renderScene({ route: scene.descriptor.route })}
|
||||
</HeaderHeightContext.Provider>
|
||||
</HeaderShownContext.Provider>
|
||||
</BaseHeader.HeightContext.Provider>
|
||||
</BaseHeader.ShownContext.Provider>
|
||||
</PreviousSceneContext.Provider>
|
||||
</View>
|
||||
{headerMode !== 'float' ? (
|
||||
|
||||
@@ -11,14 +11,16 @@ import type {
|
||||
Route,
|
||||
StackNavigationState,
|
||||
} from '@react-navigation/native';
|
||||
import { SafeAreaProviderCompat } from '@react-navigation/elements';
|
||||
import {
|
||||
Header as BaseHeader,
|
||||
SafeAreaProviderCompat,
|
||||
} from '@react-navigation/elements';
|
||||
|
||||
import {
|
||||
MaybeScreenContainer,
|
||||
MaybeScreen,
|
||||
shouldUseActivityState,
|
||||
} from '../Screens';
|
||||
import { getDefaultHeaderHeight } from '../Header/HeaderSegment';
|
||||
import type { Props as HeaderContainerProps } from '../Header/HeaderContainer';
|
||||
import CardContainer from './CardContainer';
|
||||
import {
|
||||
@@ -118,7 +120,7 @@ const getHeaderHeights = (
|
||||
acc[curr.key] =
|
||||
typeof height === 'number'
|
||||
? height
|
||||
: getDefaultHeaderHeight(layout, headerStatusBarHeight);
|
||||
: BaseHeader.getDefaultHeight(layout, headerStatusBarHeight);
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
@@ -11,7 +11,10 @@ import {
|
||||
Route,
|
||||
ParamListBase,
|
||||
} from '@react-navigation/native';
|
||||
import { SafeAreaProviderCompat } from '@react-navigation/elements';
|
||||
import {
|
||||
Header as BaseHeader,
|
||||
SafeAreaProviderCompat,
|
||||
} from '@react-navigation/elements';
|
||||
|
||||
import { GestureHandlerRootView } from '../GestureHandler';
|
||||
import CardStack from './CardStack';
|
||||
@@ -19,7 +22,6 @@ import KeyboardManager from '../KeyboardManager';
|
||||
import HeaderContainer, {
|
||||
Props as HeaderContainerProps,
|
||||
} from '../Header/HeaderContainer';
|
||||
import HeaderShownContext from '../../utils/HeaderShownContext';
|
||||
import type {
|
||||
StackNavigationHelpers,
|
||||
StackNavigationConfig,
|
||||
@@ -460,7 +462,7 @@ export default class StackView extends React.Component<Props, State> {
|
||||
{(insets) => (
|
||||
<KeyboardManager enabled={keyboardHandlingEnabled !== false}>
|
||||
{(props) => (
|
||||
<HeaderShownContext.Consumer>
|
||||
<BaseHeader.ShownContext.Consumer>
|
||||
{(isParentHeaderShown) => (
|
||||
<CardStack
|
||||
mode={mode}
|
||||
@@ -487,7 +489,7 @@ export default class StackView extends React.Component<Props, State> {
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
</HeaderShownContext.Consumer>
|
||||
</BaseHeader.ShownContext.Consumer>
|
||||
)}
|
||||
</KeyboardManager>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user