mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-13 22:42:25 +08:00
Compare commits
21 Commits
@react-nav
...
@react-nav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
65b6a3d864 | ||
|
|
211f1f2c0e | ||
|
|
22b7c3f6c1 | ||
|
|
6ebe0824df | ||
|
|
82900cceff | ||
|
|
dc4ffc0171 | ||
|
|
9c30c42c0b | ||
|
|
ea8ea20127 | ||
|
|
2f282f1070 | ||
|
|
5165eb76aa | ||
|
|
7c722d2028 | ||
|
|
7f015130df | ||
|
|
7580efce89 | ||
|
|
1179d56c50 | ||
|
|
a6e498170f | ||
|
|
4af9d10298 | ||
|
|
08e74af545 | ||
|
|
1e05895b24 | ||
|
|
929c3e3a3b | ||
|
|
b5d539a11b | ||
|
|
7da45e1e89 |
@@ -4,42 +4,41 @@ beforeEach(async () => {
|
||||
await page.click('[data-testid=LinkComponent]');
|
||||
});
|
||||
|
||||
it('loads the article page', async () => {
|
||||
expect(await page.evaluate(() => location.pathname + location.search)).toBe(
|
||||
'/link-component/article/gandalf'
|
||||
);
|
||||
const getPageInfo = async () => ({
|
||||
url: await page.evaluate(() => location.pathname + location.search),
|
||||
title: await page.evaluate(() => document.title),
|
||||
heading: (await page.accessibility.snapshot())?.children?.find(
|
||||
(it) => it.role === 'heading'
|
||||
)?.name,
|
||||
});
|
||||
|
||||
expect(
|
||||
((await page.accessibility.snapshot()) as any)?.children?.find(
|
||||
(it: any) => it.role === 'heading'
|
||||
)?.name
|
||||
).toBe('Article by Gandalf');
|
||||
it('loads the article page', async () => {
|
||||
const { url, title, heading } = await getPageInfo();
|
||||
|
||||
expect(url).toBe('/link-component/article/gandalf');
|
||||
expect(title).toBe('Article by Gandalf - React Navigation Example');
|
||||
expect(heading).toBe('Article by Gandalf');
|
||||
});
|
||||
|
||||
it('goes to the album page and goes back', async () => {
|
||||
await page.click('[href="/link-component/music"]');
|
||||
|
||||
expect(await page.evaluate(() => location.pathname + location.search)).toBe(
|
||||
'/link-component/music'
|
||||
);
|
||||
{
|
||||
const { url, title, heading } = await getPageInfo();
|
||||
|
||||
expect(
|
||||
((await page.accessibility.snapshot()) as any)?.children?.find(
|
||||
(it: any) => it.role === 'heading'
|
||||
)?.name
|
||||
).toBe('Albums');
|
||||
expect(url).toBe('/link-component/music');
|
||||
expect(title).toBe('Albums - React Navigation Example');
|
||||
expect(heading).toBe('Albums');
|
||||
}
|
||||
|
||||
await page.click('[aria-label="Article by Gandalf, back"]');
|
||||
|
||||
await page.waitForNavigation();
|
||||
|
||||
expect(await page.evaluate(() => location.pathname + location.search)).toBe(
|
||||
'/link-component/article/gandalf'
|
||||
);
|
||||
{
|
||||
const { url, title, heading } = await getPageInfo();
|
||||
|
||||
expect(
|
||||
((await page.accessibility.snapshot()) as any)?.children?.find(
|
||||
(it: any) => it.role === 'heading'
|
||||
)?.name
|
||||
).toBe('Article by Gandalf');
|
||||
expect(url).toBe('/link-component/article/gandalf');
|
||||
expect(title).toBe('Article by Gandalf - React Navigation Example');
|
||||
expect(heading).toBe('Article by Gandalf');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
"@types/cheerio": "^0.22.28",
|
||||
"@types/jest-dev-server": "^4.2.0",
|
||||
"@types/koa": "^2.13.1",
|
||||
"@types/mock-require": "^2.0.0",
|
||||
"@types/node-fetch": "^2.5.9",
|
||||
"@types/react": "~16.9.35",
|
||||
"@types/react-dom": "~16.9.8",
|
||||
@@ -54,6 +55,7 @@
|
||||
"expo-cli": "^4.4.4",
|
||||
"jest": "^26.6.3",
|
||||
"jest-dev-server": "^4.4.0",
|
||||
"mock-require": "^3.0.3",
|
||||
"mock-require-assets": "^0.0.1",
|
||||
"node-fetch": "^2.6.1",
|
||||
"nodemon": "^2.0.6",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'mock-require-assets';
|
||||
|
||||
import mock from 'mock-require';
|
||||
import Module from 'module';
|
||||
|
||||
// We need to make sure that .web.xx extensions are resolved before .xx
|
||||
@@ -10,3 +11,14 @@ Module._extensions = Object.fromEntries(
|
||||
return b[0].split('.').length - a[0].split('.').length;
|
||||
})
|
||||
);
|
||||
|
||||
// Set __DEV__ that expo needs
|
||||
// @ts-expect-error
|
||||
global.__DEV__ = process.env.NODE_ENV !== 'production';
|
||||
|
||||
// Reanimated doesn't support SSR :(
|
||||
mock(
|
||||
'react-native-reanimated',
|
||||
// eslint-disable-next-line import/no-commonjs
|
||||
{ ...require('react-native-reanimated/mock').default, call() {} }
|
||||
);
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
import * as React from 'react';
|
||||
import { ScrollView, StyleSheet } from 'react-native';
|
||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
import { BlurView } from 'expo-blur';
|
||||
import {
|
||||
getFocusedRouteNameFromRoute,
|
||||
ParamListBase,
|
||||
NavigatorScreenParams,
|
||||
} from '@react-navigation/native';
|
||||
import type { StackScreenProps } from '@react-navigation/stack';
|
||||
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
||||
import {
|
||||
createBottomTabNavigator,
|
||||
useBottomTabBarHeight,
|
||||
} from '@react-navigation/bottom-tabs';
|
||||
import { HeaderBackButton } from '@react-navigation/elements';
|
||||
import Albums from '../Shared/Albums';
|
||||
import Contacts from '../Shared/Contacts';
|
||||
@@ -28,6 +33,16 @@ type BottomTabParams = {
|
||||
TabChat: undefined;
|
||||
};
|
||||
|
||||
const AlbumsScreen = () => {
|
||||
const tabBarHeight = useBottomTabBarHeight();
|
||||
|
||||
return (
|
||||
<ScrollView contentContainerStyle={{ paddingBottom: tabBarHeight }}>
|
||||
<Albums scrollEnabled={false} />
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
const BottomTabs = createBottomTabNavigator<BottomTabParams>();
|
||||
|
||||
export default function BottomTabsScreen({
|
||||
@@ -78,10 +93,18 @@ export default function BottomTabsScreen({
|
||||
/>
|
||||
<BottomTabs.Screen
|
||||
name="TabAlbums"
|
||||
component={Albums}
|
||||
component={AlbumsScreen}
|
||||
options={{
|
||||
title: 'Albums',
|
||||
tabBarIcon: getTabBarIcon('image-album'),
|
||||
tabBarStyle: { position: 'absolute' },
|
||||
tabBarBackground: () => (
|
||||
<BlurView
|
||||
tint="light"
|
||||
intensity={100}
|
||||
style={StyleSheet.absoluteFill}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</BottomTabs.Navigator>
|
||||
|
||||
@@ -5,7 +5,6 @@ import type { ParamListBase } from '@react-navigation/native';
|
||||
import {
|
||||
createStackNavigator,
|
||||
StackScreenProps,
|
||||
TransitionPresets,
|
||||
} from '@react-navigation/stack';
|
||||
import Article from '../Shared/Article';
|
||||
import Albums from '../Shared/Albums';
|
||||
@@ -119,7 +118,7 @@ export default function MixedStackScreen({ navigation }: Props) {
|
||||
component={AlbumsScreen}
|
||||
options={{
|
||||
title: 'Albums',
|
||||
...TransitionPresets.ModalPresentationIOS,
|
||||
presentation: 'modal',
|
||||
}}
|
||||
/>
|
||||
</MixedStack.Navigator>
|
||||
|
||||
@@ -82,7 +82,7 @@ export default function ModalStackScreen({ navigation }: Props) {
|
||||
}, [navigation]);
|
||||
|
||||
return (
|
||||
<ModalStack.Navigator screenOptions={{ animationPresentation: 'modal' }}>
|
||||
<ModalStack.Navigator screenOptions={{ presentation: 'modal' }}>
|
||||
<ModalStack.Screen
|
||||
name="Article"
|
||||
component={ArticleScreen}
|
||||
|
||||
@@ -84,9 +84,7 @@ export default function TransparentStackScreen({ navigation }: Props) {
|
||||
}, [navigation]);
|
||||
|
||||
return (
|
||||
<TransparentStack.Navigator
|
||||
screenOptions={{ animationPresentation: 'modal' }}
|
||||
>
|
||||
<TransparentStack.Navigator screenOptions={{ presentation: 'modal' }}>
|
||||
<TransparentStack.Screen
|
||||
name="Article"
|
||||
component={ArticleScreen}
|
||||
|
||||
@@ -206,7 +206,7 @@ export default function App() {
|
||||
return () => Dimensions.removeEventListener('change', onDimensionsChange);
|
||||
}, []);
|
||||
|
||||
const navigationRef = useNavigationContainerRef<RootStackParamList>();
|
||||
const navigationRef = useNavigationContainerRef();
|
||||
|
||||
useReduxDevToolsExtension(navigationRef);
|
||||
|
||||
|
||||
@@ -3,6 +3,54 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [6.0.0-next.11](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@6.0.0-next.10...@react-navigation/bottom-tabs@6.0.0-next.11) (2021-05-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix tab bar height including extra bottom inset ([7c722d2](https://github.com/react-navigation/react-navigation/commit/7c722d2028e914e8f143b9385ebf5e1c00131a01))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add a tabBarBackground option to bottom tabs ([2f282f1](https://github.com/react-navigation/react-navigation/commit/2f282f107053a65b69f80edb5d9c858cfa569aa2))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.10](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@6.0.0-next.9...@react-navigation/bottom-tabs@6.0.0-next.10) (2021-05-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add a deprecation warning for mode prop in stack ([a6e4981](https://github.com/react-navigation/react-navigation/commit/a6e498170f59648190fa5513e273ca523e56c5d5))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* return a NavigationContent component from useNavigationBuilder ([1179d56](https://github.com/react-navigation/react-navigation/commit/1179d56c5008270753feef41acdc1dbd2191efcf))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.9](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@6.0.0-next.8...@react-navigation/bottom-tabs@6.0.0-next.9) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.8](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@6.0.0-next.7...@react-navigation/bottom-tabs@6.0.0-next.8) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.7](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@6.0.0-next.6...@react-navigation/bottom-tabs@6.0.0-next.7) (2021-05-09)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/bottom-tabs",
|
||||
"description": "Bottom tab navigator following iOS design guidelines",
|
||||
"version": "6.0.0-next.7",
|
||||
"version": "6.0.0-next.11",
|
||||
"keywords": [
|
||||
"react-native-component",
|
||||
"react-component",
|
||||
@@ -36,12 +36,12 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/elements": "^1.0.0-next.6",
|
||||
"@react-navigation/elements": "^1.0.0-next.10",
|
||||
"color": "^3.1.3",
|
||||
"warn-once": "^0.0.1"
|
||||
"warn-once": "^0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-navigation/native": "^6.0.0-next.4",
|
||||
"@react-navigation/native": "^6.0.0-next.8",
|
||||
"@testing-library/react-native": "^7.2.0",
|
||||
"@types/color": "^3.0.1",
|
||||
"@types/react": "^16.9.53",
|
||||
|
||||
@@ -70,7 +70,12 @@ function BottomTabNavigator({
|
||||
);
|
||||
}
|
||||
|
||||
const { state, descriptors, navigation } = useNavigationBuilder<
|
||||
const {
|
||||
state,
|
||||
descriptors,
|
||||
navigation,
|
||||
NavigationContent,
|
||||
} = useNavigationBuilder<
|
||||
TabNavigationState<ParamListBase>,
|
||||
TabRouterOptions,
|
||||
TabActionHelpers<ParamListBase>,
|
||||
@@ -85,13 +90,15 @@ function BottomTabNavigator({
|
||||
});
|
||||
|
||||
return (
|
||||
<BottomTabView
|
||||
{...rest}
|
||||
state={state}
|
||||
navigation={navigation}
|
||||
descriptors={descriptors}
|
||||
sceneContainerStyle={sceneContainerStyle}
|
||||
/>
|
||||
<NavigationContent>
|
||||
<BottomTabView
|
||||
{...rest}
|
||||
state={state}
|
||||
navigation={navigation}
|
||||
descriptors={descriptors}
|
||||
sceneContainerStyle={sceneContainerStyle}
|
||||
/>
|
||||
</NavigationContent>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -229,6 +229,15 @@ export type BottomTabNavigationOptions = HeaderOptions & {
|
||||
*/
|
||||
tabBarStyle?: Animated.WithAnimatedValue<StyleProp<ViewStyle>>;
|
||||
|
||||
/**
|
||||
* Component to use as background for the tab bar.
|
||||
* You could render an image, a gradient, blur view etc.
|
||||
*
|
||||
* When using `BlurView`, make sure to set `position: 'absolute'` in `tabBarStyle` as well.
|
||||
* You'd also need to use `useBottomTabBarHeight()` to add a bottom padding to your content.
|
||||
*/
|
||||
tabBarBackground?: () => React.ReactNode;
|
||||
|
||||
/**
|
||||
* Whether this screen should be unmounted when navigating away from it.
|
||||
* Defaults to `false`.
|
||||
|
||||
@@ -144,6 +144,7 @@ export default function BottomTabBar({
|
||||
tabBarHideOnKeyboard = false,
|
||||
tabBarVisibilityAnimationConfig,
|
||||
tabBarStyle,
|
||||
tabBarBackground,
|
||||
} = focusedOptions;
|
||||
|
||||
const dimensions = useSafeAreaFrame();
|
||||
@@ -211,15 +212,7 @@ export default function BottomTabBar({
|
||||
const handleLayout = (e: LayoutChangeEvent) => {
|
||||
const { height, width } = e.nativeEvent.layout;
|
||||
|
||||
const topBorderWidth =
|
||||
// @ts-ignore
|
||||
StyleSheet.flatten([styles.tabBar, tabBarStyle])?.borderTopWidth;
|
||||
|
||||
onHeightChange?.(
|
||||
height +
|
||||
paddingBottom +
|
||||
(typeof topBorderWidth === 'number' ? topBorderWidth : 0)
|
||||
);
|
||||
onHeightChange?.(height);
|
||||
|
||||
setLayout((layout) => {
|
||||
if (height === layout.height && width === layout.width) {
|
||||
@@ -252,12 +245,15 @@ export default function BottomTabBar({
|
||||
layout,
|
||||
});
|
||||
|
||||
const tabBarBackgroundElement = tabBarBackground?.();
|
||||
|
||||
return (
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.tabBar,
|
||||
{
|
||||
backgroundColor: colors.card,
|
||||
backgroundColor:
|
||||
tabBarBackgroundElement != null ? 'transparent' : colors.card,
|
||||
borderTopColor: colors.border,
|
||||
},
|
||||
{
|
||||
@@ -286,6 +282,9 @@ export default function BottomTabBar({
|
||||
pointerEvents={isTabBarHidden ? 'none' : 'auto'}
|
||||
onLayout={handleLayout}
|
||||
>
|
||||
<View pointerEvents="none" style={StyleSheet.absoluteFill}>
|
||||
{tabBarBackgroundElement}
|
||||
</View>
|
||||
<View accessibilityRole="tablist" style={styles.content}>
|
||||
{routes.map((route, index) => {
|
||||
const focused = index === state.index;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { StyleSheet, Platform } from 'react-native';
|
||||
import { SafeAreaInsetsContext } from 'react-native-safe-area-context';
|
||||
import {
|
||||
NavigationHelpersContext,
|
||||
import type {
|
||||
ParamListBase,
|
||||
TabNavigationState,
|
||||
} from '@react-navigation/native';
|
||||
@@ -89,72 +88,70 @@ export default function BottomTabView(props: Props) {
|
||||
const { routes } = state;
|
||||
|
||||
return (
|
||||
<NavigationHelpersContext.Provider value={navigation}>
|
||||
<SafeAreaProviderCompat>
|
||||
<MaybeScreenContainer
|
||||
enabled={detachInactiveScreens}
|
||||
style={styles.container}
|
||||
>
|
||||
{routes.map((route, index) => {
|
||||
const descriptor = descriptors[route.key];
|
||||
const { lazy = true, unmountOnBlur } = descriptor.options;
|
||||
const isFocused = state.index === index;
|
||||
<SafeAreaProviderCompat>
|
||||
<MaybeScreenContainer
|
||||
enabled={detachInactiveScreens}
|
||||
style={styles.container}
|
||||
>
|
||||
{routes.map((route, index) => {
|
||||
const descriptor = descriptors[route.key];
|
||||
const { lazy = true, unmountOnBlur } = descriptor.options;
|
||||
const isFocused = state.index === index;
|
||||
|
||||
if (unmountOnBlur && !isFocused) {
|
||||
return null;
|
||||
}
|
||||
if (unmountOnBlur && !isFocused) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (lazy && !loaded.includes(route.key) && !isFocused) {
|
||||
// Don't render a lazy screen if we've never navigated to it
|
||||
return null;
|
||||
}
|
||||
if (lazy && !loaded.includes(route.key) && !isFocused) {
|
||||
// Don't render a lazy screen if we've never navigated to it
|
||||
return null;
|
||||
}
|
||||
|
||||
const {
|
||||
header = ({ layout, options }: BottomTabHeaderProps) => (
|
||||
<Header
|
||||
{...options}
|
||||
layout={layout}
|
||||
title={getHeaderTitle(options, route.name)}
|
||||
/>
|
||||
),
|
||||
} = descriptor.options;
|
||||
const {
|
||||
header = ({ layout, options }: BottomTabHeaderProps) => (
|
||||
<Header
|
||||
{...options}
|
||||
layout={layout}
|
||||
title={getHeaderTitle(options, route.name)}
|
||||
/>
|
||||
),
|
||||
} = descriptor.options;
|
||||
|
||||
return (
|
||||
<MaybeScreen
|
||||
key={route.key}
|
||||
style={StyleSheet.absoluteFill}
|
||||
visible={isFocused}
|
||||
enabled={detachInactiveScreens}
|
||||
>
|
||||
<BottomTabBarHeightContext.Provider value={tabBarHeight}>
|
||||
<Screen
|
||||
focused={isFocused}
|
||||
route={descriptor.route}
|
||||
navigation={descriptor.navigation}
|
||||
headerShown={descriptor.options.headerShown}
|
||||
headerStatusBarHeight={
|
||||
descriptor.options.headerStatusBarHeight
|
||||
}
|
||||
header={header({
|
||||
layout: dimensions,
|
||||
route: descriptor.route,
|
||||
navigation: descriptor.navigation as BottomTabNavigationProp<ParamListBase>,
|
||||
options: descriptor.options,
|
||||
})}
|
||||
style={sceneContainerStyle}
|
||||
>
|
||||
{descriptor.render()}
|
||||
</Screen>
|
||||
</BottomTabBarHeightContext.Provider>
|
||||
</MaybeScreen>
|
||||
);
|
||||
})}
|
||||
</MaybeScreenContainer>
|
||||
<BottomTabBarHeightCallbackContext.Provider value={setTabBarHeight}>
|
||||
{renderTabBar()}
|
||||
</BottomTabBarHeightCallbackContext.Provider>
|
||||
</SafeAreaProviderCompat>
|
||||
</NavigationHelpersContext.Provider>
|
||||
return (
|
||||
<MaybeScreen
|
||||
key={route.key}
|
||||
style={StyleSheet.absoluteFill}
|
||||
visible={isFocused}
|
||||
enabled={detachInactiveScreens}
|
||||
>
|
||||
<BottomTabBarHeightContext.Provider value={tabBarHeight}>
|
||||
<Screen
|
||||
focused={isFocused}
|
||||
route={descriptor.route}
|
||||
navigation={descriptor.navigation}
|
||||
headerShown={descriptor.options.headerShown}
|
||||
headerStatusBarHeight={
|
||||
descriptor.options.headerStatusBarHeight
|
||||
}
|
||||
header={header({
|
||||
layout: dimensions,
|
||||
route: descriptor.route,
|
||||
navigation: descriptor.navigation as BottomTabNavigationProp<ParamListBase>,
|
||||
options: descriptor.options,
|
||||
})}
|
||||
style={sceneContainerStyle}
|
||||
>
|
||||
{descriptor.render()}
|
||||
</Screen>
|
||||
</BottomTabBarHeightContext.Provider>
|
||||
</MaybeScreen>
|
||||
);
|
||||
})}
|
||||
</MaybeScreenContainer>
|
||||
<BottomTabBarHeightCallbackContext.Provider value={setTabBarHeight}>
|
||||
{renderTabBar()}
|
||||
</BottomTabBarHeightCallbackContext.Provider>
|
||||
</SafeAreaProviderCompat>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,50 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [6.0.0-next.8](https://github.com/react-navigation/react-navigation/compare/@react-navigation/core@6.0.0-next.7...@react-navigation/core@6.0.0-next.8) (2021-05-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix type error when passing unannotated navigation ref ([dc4ffc0](https://github.com/react-navigation/react-navigation/commit/dc4ffc0171b4535fe1b6e839b9d54350121bcf55))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.7](https://github.com/react-navigation/react-navigation/compare/@react-navigation/core@6.0.0-next.6...@react-navigation/core@6.0.0-next.7) (2021-05-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* return a NavigationContent component from useNavigationBuilder ([1179d56](https://github.com/react-navigation/react-navigation/commit/1179d56c5008270753feef41acdc1dbd2191efcf))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.6](https://github.com/react-navigation/react-navigation/compare/@react-navigation/core@6.0.0-next.5...@react-navigation/core@6.0.0-next.6) (2021-05-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix type annotations for useNavigation (again) ([929c3e3](https://github.com/react-navigation/react-navigation/commit/929c3e3a3b3eb32d197ef1f887dc4cbdce48eaff))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.5](https://github.com/react-navigation/react-navigation/compare/@react-navigation/core@6.0.0-next.4...@react-navigation/core@6.0.0-next.5) (2021-05-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix type annotations for useNavigation ([7da45e1](https://github.com/react-navigation/react-navigation/commit/7da45e1e8951ff46e09db4ebc2c88085c67ab8e9))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.4](https://github.com/react-navigation/react-navigation/compare/@react-navigation/core@6.0.0-next.3...@react-navigation/core@6.0.0-next.4) (2021-05-09)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/core",
|
||||
"description": "Core utilities for building navigators",
|
||||
"version": "6.0.0-next.4",
|
||||
"version": "6.0.0-next.8",
|
||||
"keywords": [
|
||||
"react",
|
||||
"react-native",
|
||||
|
||||
30
packages/core/src/useComponent.tsx
Normal file
30
packages/core/src/useComponent.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export default function useComponent<
|
||||
T extends React.ComponentType<any>,
|
||||
P extends {}
|
||||
>(Component: T, props: P) {
|
||||
const propsRef = React.useRef<P | null>(props);
|
||||
|
||||
// Normally refs shouldn't be mutated in render
|
||||
// But we return a component which will be rendered
|
||||
// So it's just for immediate consumption
|
||||
propsRef.current = props;
|
||||
|
||||
React.useEffect(() => {
|
||||
propsRef.current = null;
|
||||
});
|
||||
|
||||
return React.useRef((rest: Omit<React.ComponentProps<T>, keyof P>) => {
|
||||
const props = propsRef.current;
|
||||
|
||||
if (props === null) {
|
||||
throw new Error(
|
||||
'The returned component must be rendered in the same render phase as the hook.'
|
||||
);
|
||||
}
|
||||
|
||||
// @ts-expect-error: the props should be fine here
|
||||
return <Component {...props} {...rest} />;
|
||||
}).current;
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import type { NavigationProp } from './types';
|
||||
* @returns Navigation prop of the parent screen.
|
||||
*/
|
||||
export default function useNavigation<
|
||||
T extends NavigationProp<any> = NavigationProp<ReactNavigation.RootParamList>
|
||||
T = NavigationProp<ReactNavigation.RootParamList>
|
||||
>(): T {
|
||||
const navigation = React.useContext(NavigationContext);
|
||||
|
||||
@@ -18,5 +18,6 @@ export default function useNavigation<
|
||||
);
|
||||
}
|
||||
|
||||
return navigation as T;
|
||||
// FIXME: Figure out a better way to do this
|
||||
return (navigation as unknown) as T;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
} from '@react-navigation/routers';
|
||||
import NavigationStateContext from './NavigationStateContext';
|
||||
import NavigationRouteContext from './NavigationRouteContext';
|
||||
import NavigationHelpersContext from './NavigationHelpersContext';
|
||||
import Group from './Group';
|
||||
import Screen from './Screen';
|
||||
import useEventEmitter from './useEventEmitter';
|
||||
@@ -29,6 +30,7 @@ import useKeyedChildListeners from './useKeyedChildListeners';
|
||||
import useOnGetState from './useOnGetState';
|
||||
import useScheduleUpdate from './useScheduleUpdate';
|
||||
import useCurrentRender from './useCurrentRender';
|
||||
import useComponent from './useComponent';
|
||||
import isArrayEqual from './isArrayEqual';
|
||||
import {
|
||||
DefaultNavigatorOptions,
|
||||
@@ -586,9 +588,14 @@ export default function useNavigationBuilder<
|
||||
descriptors,
|
||||
});
|
||||
|
||||
const NavigationContent = useComponent(NavigationHelpersContext.Provider, {
|
||||
value: navigation,
|
||||
});
|
||||
|
||||
return {
|
||||
state,
|
||||
navigation,
|
||||
descriptors,
|
||||
NavigationContent,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import * as React from 'react';
|
||||
import type { ParamListBase } from '@react-navigation/routers';
|
||||
import createNavigationContainerRef from './createNavigationContainerRef';
|
||||
import type { NavigationContainerRefWithCurrent } from './types';
|
||||
|
||||
export default function useNavigationContainerRef<
|
||||
ParamList extends ParamListBase
|
||||
ParamList extends {} = ReactNavigation.RootParamList
|
||||
>(): NavigationContainerRefWithCurrent<ParamList> {
|
||||
const navigation = React.useRef<NavigationContainerRefWithCurrent<ParamList> | null>(
|
||||
null
|
||||
|
||||
@@ -3,6 +3,41 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [6.0.0-next.8](https://github.com/react-navigation/react-navigation/compare/@react-navigation/devtools@6.0.0-next.7...@react-navigation/devtools@6.0.0-next.8) (2021-05-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix type error when passing unannotated navigation ref ([dc4ffc0](https://github.com/react-navigation/react-navigation/commit/dc4ffc0171b4535fe1b6e839b9d54350121bcf55))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.7](https://github.com/react-navigation/react-navigation/compare/@react-navigation/devtools@6.0.0-next.6...@react-navigation/devtools@6.0.0-next.7) (2021-05-10)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/devtools
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.6](https://github.com/react-navigation/react-navigation/compare/@react-navigation/devtools@6.0.0-next.5...@react-navigation/devtools@6.0.0-next.6) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/devtools
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.5](https://github.com/react-navigation/react-navigation/compare/@react-navigation/devtools@6.0.0-next.4...@react-navigation/devtools@6.0.0-next.5) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/devtools
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.4](https://github.com/react-navigation/react-navigation/compare/@react-navigation/devtools@6.0.0-next.3...@react-navigation/devtools@6.0.0-next.4) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/devtools
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/devtools",
|
||||
"description": "Developer tools for React Navigation",
|
||||
"version": "6.0.0-next.4",
|
||||
"version": "6.0.0-next.8",
|
||||
"keywords": [
|
||||
"react",
|
||||
"react-native",
|
||||
@@ -36,7 +36,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/core": "^6.0.0-next.4",
|
||||
"@react-navigation/core": "^6.0.0-next.8",
|
||||
"deep-equal": "^2.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -3,7 +3,6 @@ import type {
|
||||
NavigationContainerRef,
|
||||
NavigationState,
|
||||
NavigationAction,
|
||||
ParamListBase,
|
||||
} from '@react-navigation/core';
|
||||
import deepEqual from 'deep-equal';
|
||||
|
||||
@@ -23,7 +22,7 @@ type DevToolsExtension = {
|
||||
declare const __REDUX_DEVTOOLS_EXTENSION__: DevToolsExtension | undefined;
|
||||
|
||||
export default function useReduxDevToolsExtension(
|
||||
ref: React.RefObject<NavigationContainerRef<ParamListBase>>
|
||||
ref: React.RefObject<NavigationContainerRef<any>>
|
||||
) {
|
||||
const devToolsRef = React.useRef<DevToolsConnection>();
|
||||
|
||||
|
||||
@@ -3,6 +3,49 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [6.0.0-next.10](https://github.com/react-navigation/react-navigation/compare/@react-navigation/drawer@6.0.0-next.9...@react-navigation/drawer@6.0.0-next.10) (2021-05-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix drawer content padding in RTL ([ea8ea20](https://github.com/react-navigation/react-navigation/commit/ea8ea20127d979d8c8ddbddf56de1bdfdf0243f9))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.9](https://github.com/react-navigation/react-navigation/compare/@react-navigation/drawer@6.0.0-next.8...@react-navigation/drawer@6.0.0-next.9) (2021-05-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add a deprecation warning for mode prop in stack ([a6e4981](https://github.com/react-navigation/react-navigation/commit/a6e498170f59648190fa5513e273ca523e56c5d5))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* return a NavigationContent component from useNavigationBuilder ([1179d56](https://github.com/react-navigation/react-navigation/commit/1179d56c5008270753feef41acdc1dbd2191efcf))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.8](https://github.com/react-navigation/react-navigation/compare/@react-navigation/drawer@6.0.0-next.7...@react-navigation/drawer@6.0.0-next.8) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/drawer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.7](https://github.com/react-navigation/react-navigation/compare/@react-navigation/drawer@6.0.0-next.6...@react-navigation/drawer@6.0.0-next.7) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/drawer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.6](https://github.com/react-navigation/react-navigation/compare/@react-navigation/drawer@6.0.0-next.5...@react-navigation/drawer@6.0.0-next.6) (2021-05-09)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/drawer",
|
||||
"description": "Drawer navigator component with animated transitions and gesturess",
|
||||
"version": "6.0.0-next.6",
|
||||
"version": "6.0.0-next.10",
|
||||
"keywords": [
|
||||
"react-native-component",
|
||||
"react-component",
|
||||
@@ -41,12 +41,12 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/elements": "^1.0.0-next.6",
|
||||
"@react-navigation/elements": "^1.0.0-next.10",
|
||||
"color": "^3.1.3",
|
||||
"warn-once": "^0.0.1"
|
||||
"warn-once": "^0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-navigation/native": "^6.0.0-next.4",
|
||||
"@react-navigation/native": "^6.0.0-next.8",
|
||||
"@testing-library/react-native": "^7.2.0",
|
||||
"@types/react": "^16.9.53",
|
||||
"@types/react-native": "~0.64.4",
|
||||
|
||||
@@ -67,7 +67,12 @@ function DrawerNavigator({
|
||||
);
|
||||
}
|
||||
|
||||
const { state, descriptors, navigation } = useNavigationBuilder<
|
||||
const {
|
||||
state,
|
||||
descriptors,
|
||||
navigation,
|
||||
NavigationContent,
|
||||
} = useNavigationBuilder<
|
||||
DrawerNavigationState<ParamListBase>,
|
||||
DrawerRouterOptions,
|
||||
DrawerActionHelpers<ParamListBase>,
|
||||
@@ -83,12 +88,14 @@ function DrawerNavigator({
|
||||
});
|
||||
|
||||
return (
|
||||
<DrawerView
|
||||
{...rest}
|
||||
state={state}
|
||||
descriptors={descriptors}
|
||||
navigation={navigation}
|
||||
/>
|
||||
<NavigationContent>
|
||||
<DrawerView
|
||||
{...rest}
|
||||
state={state}
|
||||
descriptors={descriptors}
|
||||
navigation={navigation}
|
||||
/>
|
||||
</NavigationContent>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import * as React from 'react';
|
||||
import { ScrollView, StyleSheet, ScrollViewProps } from 'react-native';
|
||||
import {
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
ScrollViewProps,
|
||||
I18nManager,
|
||||
} from 'react-native';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import DrawerPositionContext from '../utils/DrawerPositionContext';
|
||||
|
||||
@@ -16,14 +21,18 @@ export default function DrawerContentScrollView({
|
||||
const drawerPosition = React.useContext(DrawerPositionContext);
|
||||
const insets = useSafeAreaInsets();
|
||||
|
||||
const isRight = I18nManager.isRTL
|
||||
? drawerPosition === 'left'
|
||||
: drawerPosition === 'right';
|
||||
|
||||
return (
|
||||
<ScrollView
|
||||
{...rest}
|
||||
contentContainerStyle={[
|
||||
{
|
||||
paddingTop: insets.top + 4,
|
||||
paddingLeft: drawerPosition === 'left' ? insets.left : 0,
|
||||
paddingRight: drawerPosition === 'right' ? insets.right : 0,
|
||||
paddingStart: !isRight ? insets.left : 0,
|
||||
paddingEnd: isRight ? insets.right : 0,
|
||||
},
|
||||
contentContainerStyle,
|
||||
]}
|
||||
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
import { useSafeAreaFrame } from 'react-native-safe-area-context';
|
||||
import Animated from 'react-native-reanimated';
|
||||
import {
|
||||
NavigationHelpersContext,
|
||||
DrawerNavigationState,
|
||||
DrawerActions,
|
||||
useTheme,
|
||||
@@ -296,13 +295,11 @@ function DrawerViewBase({
|
||||
|
||||
export default function DrawerView({ navigation, ...rest }: Props) {
|
||||
return (
|
||||
<NavigationHelpersContext.Provider value={navigation}>
|
||||
<SafeAreaProviderCompat>
|
||||
<GestureHandlerWrapper style={styles.content}>
|
||||
<DrawerViewBase navigation={navigation} {...rest} />
|
||||
</GestureHandlerWrapper>
|
||||
</SafeAreaProviderCompat>
|
||||
</NavigationHelpersContext.Provider>
|
||||
<SafeAreaProviderCompat>
|
||||
<GestureHandlerWrapper style={styles.content}>
|
||||
<DrawerViewBase navigation={navigation} {...rest} />
|
||||
</GestureHandlerWrapper>
|
||||
</SafeAreaProviderCompat>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,41 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.0.0-next.10](https://github.com/react-navigation/react-navigation/compare/@react-navigation/elements@1.0.0-next.9...@react-navigation/elements@1.0.0-next.10) (2021-05-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix drawer content padding in RTL ([ea8ea20](https://github.com/react-navigation/react-navigation/commit/ea8ea20127d979d8c8ddbddf56de1bdfdf0243f9))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [1.0.0-next.9](https://github.com/react-navigation/react-navigation/compare/@react-navigation/elements@1.0.0-next.8...@react-navigation/elements@1.0.0-next.9) (2021-05-10)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/elements
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [1.0.0-next.8](https://github.com/react-navigation/react-navigation/compare/@react-navigation/elements@1.0.0-next.7...@react-navigation/elements@1.0.0-next.8) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/elements
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [1.0.0-next.7](https://github.com/react-navigation/react-navigation/compare/@react-navigation/elements@1.0.0-next.6...@react-navigation/elements@1.0.0-next.7) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/elements
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [1.0.0-next.6](https://github.com/react-navigation/react-navigation/compare/@react-navigation/elements@1.0.0-next.5...@react-navigation/elements@1.0.0-next.6) (2021-05-09)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/elements",
|
||||
"description": "UI Components for React Navigation",
|
||||
"version": "1.0.0-next.6",
|
||||
"version": "1.0.0-next.10",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
"react-navigation",
|
||||
@@ -38,7 +38,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-masked-view/masked-view": "^0.2.3",
|
||||
"@react-navigation/native": "^6.0.0-next.4",
|
||||
"@react-navigation/native": "^6.0.0-next.8",
|
||||
"@testing-library/react-native": "^7.2.0",
|
||||
"@types/react": "^16.9.53",
|
||||
"@types/react-native": "~0.64.4",
|
||||
|
||||
@@ -214,7 +214,7 @@ export default function Header(props: Props) {
|
||||
style={[
|
||||
styles.left,
|
||||
headerTitleAlign === 'center' && styles.expand,
|
||||
{ marginLeft: insets.left },
|
||||
{ marginStart: insets.left },
|
||||
leftContainerStyle,
|
||||
]}
|
||||
>
|
||||
@@ -236,7 +236,7 @@ export default function Header(props: Props) {
|
||||
style={[
|
||||
styles.right,
|
||||
styles.expand,
|
||||
{ marginRight: insets.right },
|
||||
{ marginEnd: insets.right },
|
||||
rightContainerStyle,
|
||||
]}
|
||||
>
|
||||
|
||||
@@ -3,6 +3,41 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [6.0.0-next.8](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-bottom-tabs@6.0.0-next.7...@react-navigation/material-bottom-tabs@6.0.0-next.8) (2021-05-16)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.7](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-bottom-tabs@6.0.0-next.6...@react-navigation/material-bottom-tabs@6.0.0-next.7) (2021-05-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* return a NavigationContent component from useNavigationBuilder ([1179d56](https://github.com/react-navigation/react-navigation/commit/1179d56c5008270753feef41acdc1dbd2191efcf))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.6](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-bottom-tabs@6.0.0-next.5...@react-navigation/material-bottom-tabs@6.0.0-next.6) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.5](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-bottom-tabs@6.0.0-next.4...@react-navigation/material-bottom-tabs@6.0.0-next.5) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.4](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-bottom-tabs@6.0.0-next.3...@react-navigation/material-bottom-tabs@6.0.0-next.4) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/material-bottom-tabs",
|
||||
"description": "Integration for bottom navigation component from react-native-paper",
|
||||
"version": "6.0.0-next.4",
|
||||
"version": "6.0.0-next.8",
|
||||
"keywords": [
|
||||
"react-native-component",
|
||||
"react-component",
|
||||
@@ -41,7 +41,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-navigation/native": "^6.0.0-next.4",
|
||||
"@react-navigation/native": "^6.0.0-next.8",
|
||||
"@testing-library/react-native": "^7.2.0",
|
||||
"@types/react": "^16.9.53",
|
||||
"@types/react-native": "~0.64.4",
|
||||
|
||||
@@ -28,7 +28,12 @@ function MaterialBottomTabNavigator({
|
||||
screenOptions,
|
||||
...rest
|
||||
}: Props) {
|
||||
const { state, descriptors, navigation } = useNavigationBuilder<
|
||||
const {
|
||||
state,
|
||||
descriptors,
|
||||
navigation,
|
||||
NavigationContent,
|
||||
} = useNavigationBuilder<
|
||||
TabNavigationState<ParamListBase>,
|
||||
TabRouterOptions,
|
||||
TabActionHelpers<ParamListBase>,
|
||||
@@ -42,12 +47,14 @@ function MaterialBottomTabNavigator({
|
||||
});
|
||||
|
||||
return (
|
||||
<MaterialBottomTabView
|
||||
{...rest}
|
||||
state={state}
|
||||
navigation={navigation}
|
||||
descriptors={descriptors}
|
||||
/>
|
||||
<NavigationContent>
|
||||
<MaterialBottomTabView
|
||||
{...rest}
|
||||
state={state}
|
||||
navigation={navigation}
|
||||
descriptors={descriptors}
|
||||
/>
|
||||
</NavigationContent>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import * as React from 'react';
|
||||
import { Text, StyleSheet, Platform } from 'react-native';
|
||||
import { BottomNavigation, DefaultTheme, DarkTheme } from 'react-native-paper';
|
||||
import {
|
||||
NavigationHelpersContext,
|
||||
Route,
|
||||
TabNavigationState,
|
||||
TabActions,
|
||||
@@ -75,7 +74,7 @@ try {
|
||||
};
|
||||
}
|
||||
|
||||
function MaterialBottomTabViewInner({
|
||||
export default function MaterialBottomTabView({
|
||||
state,
|
||||
navigation,
|
||||
descriptors,
|
||||
@@ -192,14 +191,6 @@ function MaterialBottomTabViewInner({
|
||||
);
|
||||
}
|
||||
|
||||
export default function MaterialBottomTabView(props: Props) {
|
||||
return (
|
||||
<NavigationHelpersContext.Provider value={props.navigation}>
|
||||
<MaterialBottomTabViewInner {...props} />
|
||||
</NavigationHelpersContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
icon: {
|
||||
backgroundColor: 'transparent',
|
||||
|
||||
@@ -3,6 +3,46 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [6.0.0-next.9](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-top-tabs@6.0.0-next.8...@react-navigation/material-top-tabs@6.0.0-next.9) (2021-05-16)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.8](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-top-tabs@6.0.0-next.7...@react-navigation/material-top-tabs@6.0.0-next.8) (2021-05-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add a deprecation warning for mode prop in stack ([a6e4981](https://github.com/react-navigation/react-navigation/commit/a6e498170f59648190fa5513e273ca523e56c5d5))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* return a NavigationContent component from useNavigationBuilder ([1179d56](https://github.com/react-navigation/react-navigation/commit/1179d56c5008270753feef41acdc1dbd2191efcf))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.7](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-top-tabs@6.0.0-next.6...@react-navigation/material-top-tabs@6.0.0-next.7) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.6](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-top-tabs@6.0.0-next.5...@react-navigation/material-top-tabs@6.0.0-next.6) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.5](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-top-tabs@6.0.0-next.4...@react-navigation/material-top-tabs@6.0.0-next.5) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/material-top-tabs",
|
||||
"description": "Integration for the animated tab view component from react-native-tab-view",
|
||||
"version": "6.0.0-next.5",
|
||||
"version": "6.0.0-next.9",
|
||||
"keywords": [
|
||||
"react-native-component",
|
||||
"react-component",
|
||||
@@ -42,10 +42,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"color": "^3.1.3",
|
||||
"warn-once": "^0.0.1"
|
||||
"warn-once": "^0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-navigation/native": "^6.0.0-next.4",
|
||||
"@react-navigation/native": "^6.0.0-next.8",
|
||||
"@testing-library/react-native": "^7.2.0",
|
||||
"@types/react": "^16.9.53",
|
||||
"@types/react-native": "~0.64.4",
|
||||
|
||||
@@ -71,7 +71,12 @@ function MaterialTopTabNavigator({
|
||||
);
|
||||
}
|
||||
|
||||
const { state, descriptors, navigation } = useNavigationBuilder<
|
||||
const {
|
||||
state,
|
||||
descriptors,
|
||||
navigation,
|
||||
NavigationContent,
|
||||
} = useNavigationBuilder<
|
||||
TabNavigationState<ParamListBase>,
|
||||
TabRouterOptions,
|
||||
TabActionHelpers<ParamListBase>,
|
||||
@@ -85,12 +90,14 @@ function MaterialTopTabNavigator({
|
||||
});
|
||||
|
||||
return (
|
||||
<MaterialTopTabView
|
||||
{...rest}
|
||||
state={state}
|
||||
navigation={navigation}
|
||||
descriptors={descriptors}
|
||||
/>
|
||||
<NavigationContent>
|
||||
<MaterialTopTabView
|
||||
{...rest}
|
||||
state={state}
|
||||
navigation={navigation}
|
||||
descriptors={descriptors}
|
||||
/>
|
||||
</NavigationContent>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { TabView, SceneRendererProps } from 'react-native-tab-view';
|
||||
import {
|
||||
NavigationHelpersContext,
|
||||
TabNavigationState,
|
||||
TabActions,
|
||||
ParamListBase,
|
||||
@@ -43,29 +42,27 @@ export default function MaterialTopTabView({
|
||||
};
|
||||
|
||||
return (
|
||||
<NavigationHelpersContext.Provider value={navigation}>
|
||||
<TabView<Route<string>>
|
||||
{...rest}
|
||||
onIndexChange={(index) =>
|
||||
navigation.dispatch({
|
||||
...TabActions.jumpTo(state.routes[index].name),
|
||||
target: state.key,
|
||||
})
|
||||
}
|
||||
renderScene={({ route }) => descriptors[route.key].render()}
|
||||
navigationState={state}
|
||||
renderTabBar={renderTabBar}
|
||||
renderLazyPlaceholder={({ route }) =>
|
||||
descriptors[route.key].options.lazyPlaceholder?.() ?? null
|
||||
}
|
||||
lazy={({ route }) => descriptors[route.key].options.lazy === true}
|
||||
onSwipeStart={() => navigation.emit({ type: 'swipeStart' })}
|
||||
onSwipeEnd={() => navigation.emit({ type: 'swipeEnd' })}
|
||||
sceneContainerStyle={[
|
||||
{ backgroundColor: colors.background },
|
||||
sceneContainerStyle,
|
||||
]}
|
||||
/>
|
||||
</NavigationHelpersContext.Provider>
|
||||
<TabView<Route<string>>
|
||||
{...rest}
|
||||
onIndexChange={(index) =>
|
||||
navigation.dispatch({
|
||||
...TabActions.jumpTo(state.routes[index].name),
|
||||
target: state.key,
|
||||
})
|
||||
}
|
||||
renderScene={({ route }) => descriptors[route.key].render()}
|
||||
navigationState={state}
|
||||
renderTabBar={renderTabBar}
|
||||
renderLazyPlaceholder={({ route }) =>
|
||||
descriptors[route.key].options.lazyPlaceholder?.() ?? null
|
||||
}
|
||||
lazy={({ route }) => descriptors[route.key].options.lazy === true}
|
||||
onSwipeStart={() => navigation.emit({ type: 'swipeStart' })}
|
||||
onSwipeEnd={() => navigation.emit({ type: 'swipeEnd' })}
|
||||
sceneContainerStyle={[
|
||||
{ backgroundColor: colors.background },
|
||||
sceneContainerStyle,
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,44 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [6.0.0-next.8](https://github.com/react-navigation/react-navigation/compare/@react-navigation/native@6.0.0-next.7...@react-navigation/native@6.0.0-next.8) (2021-05-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add ability to pass generic params to Link ([9c30c42](https://github.com/react-navigation/react-navigation/commit/9c30c42c0bddbc90c58b79a8be6d57e57a131e77))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.7](https://github.com/react-navigation/react-navigation/compare/@react-navigation/native@6.0.0-next.6...@react-navigation/native@6.0.0-next.7) (2021-05-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* return a NavigationContent component from useNavigationBuilder ([1179d56](https://github.com/react-navigation/react-navigation/commit/1179d56c5008270753feef41acdc1dbd2191efcf))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.6](https://github.com/react-navigation/react-navigation/compare/@react-navigation/native@6.0.0-next.5...@react-navigation/native@6.0.0-next.6) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/native
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.5](https://github.com/react-navigation/react-navigation/compare/@react-navigation/native@6.0.0-next.4...@react-navigation/native@6.0.0-next.5) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/native
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.4](https://github.com/react-navigation/react-navigation/compare/@react-navigation/native@6.0.0-next.3...@react-navigation/native@6.0.0-next.4) (2021-05-09)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/native",
|
||||
"description": "React Native integration for React Navigation",
|
||||
"version": "6.0.0-next.4",
|
||||
"version": "6.0.0-next.8",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
"react-navigation",
|
||||
@@ -37,7 +37,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/core": "^6.0.0-next.4",
|
||||
"@react-navigation/core": "^6.0.0-next.8",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"nanoid": "^3.1.22"
|
||||
},
|
||||
|
||||
@@ -4,8 +4,8 @@ import type { NavigationAction } from '@react-navigation/core';
|
||||
import useLinkProps from './useLinkProps';
|
||||
import type { To } from './useLinkTo';
|
||||
|
||||
type Props = {
|
||||
to: To;
|
||||
type Props<ParamList extends ReactNavigation.RootParamList> = {
|
||||
to: To<ParamList>;
|
||||
action?: NavigationAction;
|
||||
target?: string;
|
||||
onPress?: (
|
||||
@@ -21,8 +21,12 @@ type Props = {
|
||||
* @param props.action Optional action to use for in-page navigation. By default, the path is parsed to an action based on linking config.
|
||||
* @param props.children Child elements to render the content.
|
||||
*/
|
||||
export default function Link({ to, action, ...rest }: Props) {
|
||||
const props = useLinkProps({ to, action });
|
||||
export default function Link<ParamList extends ReactNavigation.RootParamList>({
|
||||
to,
|
||||
action,
|
||||
...rest
|
||||
}: Props<ParamList>) {
|
||||
const props = useLinkProps<ParamList>({ to, action });
|
||||
|
||||
const onPress = (
|
||||
e: React.MouseEvent<HTMLAnchorElement, MouseEvent> | GestureResponderEvent
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
createNavigatorFactory,
|
||||
StackRouter,
|
||||
TabRouter,
|
||||
NavigationHelpersContext,
|
||||
createNavigationContainerRef,
|
||||
ParamListBase,
|
||||
} from '@react-navigation/core';
|
||||
@@ -22,36 +21,36 @@ it('integrates with the history API', () => {
|
||||
jest.useFakeTimers();
|
||||
|
||||
const createStackNavigator = createNavigatorFactory((props: any) => {
|
||||
const { navigation, state, descriptors } = useNavigationBuilder(
|
||||
const { state, descriptors, NavigationContent } = useNavigationBuilder(
|
||||
StackRouter,
|
||||
props
|
||||
);
|
||||
|
||||
return (
|
||||
<NavigationHelpersContext.Provider value={navigation}>
|
||||
<NavigationContent>
|
||||
{state.routes.map((route, i) => (
|
||||
<div key={route.key} aria-current={state.index === i || undefined}>
|
||||
{descriptors[route.key].render()}
|
||||
</div>
|
||||
))}
|
||||
</NavigationHelpersContext.Provider>
|
||||
</NavigationContent>
|
||||
);
|
||||
});
|
||||
|
||||
const createTabNavigator = createNavigatorFactory((props: any) => {
|
||||
const { navigation, state, descriptors } = useNavigationBuilder(
|
||||
const { state, descriptors, NavigationContent } = useNavigationBuilder(
|
||||
TabRouter,
|
||||
props
|
||||
);
|
||||
|
||||
return (
|
||||
<NavigationHelpersContext.Provider value={navigation}>
|
||||
<NavigationContent>
|
||||
{state.routes.map((route, i) => (
|
||||
<div key={route.key} aria-current={state.index === i || undefined}>
|
||||
{descriptors[route.key].render()}
|
||||
</div>
|
||||
))}
|
||||
</NavigationHelpersContext.Provider>
|
||||
</NavigationContent>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
createNavigatorFactory,
|
||||
StackRouter,
|
||||
TabRouter,
|
||||
NavigationHelpersContext,
|
||||
NavigatorScreenParams,
|
||||
} from '@react-navigation/core';
|
||||
import { renderToString } from 'react-dom/server';
|
||||
@@ -23,17 +22,17 @@ jest.mock('../useLinking', () => require('../useLinking.tsx').default);
|
||||
|
||||
it('renders correct state with location', () => {
|
||||
const createStackNavigator = createNavigatorFactory((props: any) => {
|
||||
const { navigation, state, descriptors } = useNavigationBuilder(
|
||||
const { state, descriptors, NavigationContent } = useNavigationBuilder(
|
||||
StackRouter,
|
||||
props
|
||||
);
|
||||
|
||||
return (
|
||||
<NavigationHelpersContext.Provider value={navigation}>
|
||||
<NavigationContent>
|
||||
{state.routes.map((route) => (
|
||||
<div key={route.key}>{descriptors[route.key].render()}</div>
|
||||
))}
|
||||
</NavigationHelpersContext.Provider>
|
||||
</NavigationContent>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -116,17 +115,17 @@ it('renders correct state with location', () => {
|
||||
|
||||
it('gets the current options', () => {
|
||||
const createTabNavigator = createNavigatorFactory((props: any) => {
|
||||
const { navigation, state, descriptors } = useNavigationBuilder(
|
||||
const { state, descriptors, NavigationContent } = useNavigationBuilder(
|
||||
TabRouter,
|
||||
props
|
||||
);
|
||||
|
||||
return (
|
||||
<NavigationHelpersContext.Provider value={navigation}>
|
||||
<NavigationContent>
|
||||
{state.routes.map((route) => (
|
||||
<div key={route.key}>{descriptors[route.key].render()}</div>
|
||||
))}
|
||||
</NavigationHelpersContext.Provider>
|
||||
</NavigationContent>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ export * from '@react-navigation/core';
|
||||
|
||||
export { default as NavigationContainer } from './NavigationContainer';
|
||||
|
||||
export { default as useBackButton } from './useBackButton';
|
||||
export { default as useScrollToTop } from './useScrollToTop';
|
||||
|
||||
export { default as DefaultTheme } from './theming/DefaultTheme';
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
} from '@react-navigation/core';
|
||||
import useLinkTo, { To } from './useLinkTo';
|
||||
|
||||
type Props = {
|
||||
to: To;
|
||||
type Props<ParamList extends ReactNavigation.RootParamList> = {
|
||||
to: To<ParamList>;
|
||||
action?: NavigationAction;
|
||||
};
|
||||
|
||||
@@ -17,9 +17,11 @@ type Props = {
|
||||
* @param props.to Absolute path to screen (e.g. `/feeds/hot`).
|
||||
* @param props.action Optional action to use for in-page navigation. By default, the path is parsed to an action based on linking config.
|
||||
*/
|
||||
export default function useLinkProps({ to, action }: Props) {
|
||||
export default function useLinkProps<
|
||||
ParamList extends ReactNavigation.RootParamList
|
||||
>({ to, action }: Props<ParamList>) {
|
||||
const navigation = React.useContext(NavigationHelpersContext);
|
||||
const linkTo = useLinkTo();
|
||||
const linkTo = useLinkTo<ParamList>();
|
||||
|
||||
const onPress = (
|
||||
e?: React.MouseEvent<HTMLAnchorElement, MouseEvent> | GestureResponderEvent
|
||||
|
||||
@@ -21,12 +21,14 @@ export type To<
|
||||
params: ParamList[RouteName];
|
||||
});
|
||||
|
||||
export default function useLinkTo() {
|
||||
export default function useLinkTo<
|
||||
ParamList extends ReactNavigation.RootParamList
|
||||
>() {
|
||||
const navigation = React.useContext(NavigationContext);
|
||||
const linking = React.useContext(LinkingContext);
|
||||
|
||||
const linkTo = React.useCallback(
|
||||
(to: To) => {
|
||||
(to: To<ParamList>) => {
|
||||
if (navigation === undefined) {
|
||||
throw new Error(
|
||||
"Couldn't find a navigation object. Is your component inside a screen in a navigator?"
|
||||
@@ -42,6 +44,7 @@ export default function useLinkTo() {
|
||||
}
|
||||
|
||||
if (typeof to !== 'string') {
|
||||
// @ts-expect-error: This is fine
|
||||
root.navigate(to.screen, to.params);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,62 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [6.0.0-next.16](https://github.com/react-navigation/react-navigation/compare/@react-navigation/stack@6.0.0-next.15...@react-navigation/stack@6.0.0-next.16) (2021-05-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* don't enable animation & gestures for first screen ([6ebe082](https://github.com/react-navigation/react-navigation/commit/6ebe0824df3df4973190428a14286aab0d14d3c1))
|
||||
* make stack screens accessible on web without screens ([22b7c3f](https://github.com/react-navigation/react-navigation/commit/22b7c3f6c18a73fc55b0289b91b8d3a96f5be29c))
|
||||
* move keyboardHandlingEnabled to screen options ([82900cc](https://github.com/react-navigation/react-navigation/commit/82900cceffa3e338b7b93e831f9ba6cbb3784815))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.15](https://github.com/react-navigation/react-navigation/compare/@react-navigation/stack@6.0.0-next.14...@react-navigation/stack@6.0.0-next.15) (2021-05-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add a deprecation warning for mode prop in stack ([a6e4981](https://github.com/react-navigation/react-navigation/commit/a6e498170f59648190fa5513e273ca523e56c5d5))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* return a NavigationContent component from useNavigationBuilder ([1179d56](https://github.com/react-navigation/react-navigation/commit/1179d56c5008270753feef41acdc1dbd2191efcf))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.14](https://github.com/react-navigation/react-navigation/compare/@react-navigation/stack@6.0.0-next.13...@react-navigation/stack@6.0.0-next.14) (2021-05-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix modal animation not being set properly ([08e74af](https://github.com/react-navigation/react-navigation/commit/08e74af54529582dcbc8d91e77bfed70f006f00d))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.13](https://github.com/react-navigation/react-navigation/compare/@react-navigation/stack@6.0.0-next.12...@react-navigation/stack@6.0.0-next.13) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/stack
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.12](https://github.com/react-navigation/react-navigation/compare/@react-navigation/stack@6.0.0-next.11...@react-navigation/stack@6.0.0-next.12) (2021-05-09)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/stack
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [6.0.0-next.11](https://github.com/react-navigation/react-navigation/compare/@react-navigation/stack@6.0.0-next.10...@react-navigation/stack@6.0.0-next.11) (2021-05-09)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/stack",
|
||||
"description": "Stack navigator component for iOS and Android with animated transitions and gestures",
|
||||
"version": "6.0.0-next.11",
|
||||
"version": "6.0.0-next.16",
|
||||
"keywords": [
|
||||
"react-native-component",
|
||||
"react-component",
|
||||
@@ -40,13 +40,13 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/elements": "^1.0.0-next.6",
|
||||
"@react-navigation/elements": "^1.0.0-next.10",
|
||||
"color": "^3.1.3",
|
||||
"react-native-iphone-x-helper": "^1.3.0",
|
||||
"warn-once": "^0.0.1"
|
||||
"warn-once": "^0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-navigation/native": "^6.0.0-next.4",
|
||||
"@react-navigation/native": "^6.0.0-next.8",
|
||||
"@testing-library/react-native": "^7.2.0",
|
||||
"@types/color": "^3.0.1",
|
||||
"@types/react": "^16.9.53",
|
||||
|
||||
@@ -30,20 +30,33 @@ function StackNavigator({
|
||||
screenOptions,
|
||||
...rest
|
||||
}: Props) {
|
||||
// @ts-expect-error: mode is deprecated
|
||||
const mode = rest.mode as 'card' | 'modal' | undefined;
|
||||
|
||||
// @ts-expect-error: headerMode='none' is deprecated
|
||||
const headerMode = rest.headerMode as StackHeaderMode | 'none' | undefined;
|
||||
|
||||
warnOnce(
|
||||
mode != null,
|
||||
`Stack Navigator: 'mode="${mode}"' is deprecated. Use 'presentation: "${mode}"' in 'screenOptions' instead.`
|
||||
);
|
||||
|
||||
warnOnce(
|
||||
headerMode === 'none',
|
||||
`Stack Navigator: 'headerMode="none"' is deprecated. Use 'headerShown: false' in 'screenOptions' instead.`
|
||||
);
|
||||
|
||||
warnOnce(
|
||||
headerMode && headerMode !== 'none',
|
||||
headerMode != null && headerMode !== 'none',
|
||||
`Stack Navigator: 'headerMode' is moved to 'options'. Moved it to 'screenOptions' to keep current behavior.`
|
||||
);
|
||||
|
||||
const { state, descriptors, navigation } = useNavigationBuilder<
|
||||
const {
|
||||
state,
|
||||
descriptors,
|
||||
navigation,
|
||||
NavigationContent,
|
||||
} = useNavigationBuilder<
|
||||
StackNavigationState<ParamListBase>,
|
||||
StackRouterOptions,
|
||||
StackActionHelpers<ParamListBase>,
|
||||
@@ -54,6 +67,7 @@ function StackNavigator({
|
||||
children,
|
||||
screenOptions,
|
||||
defaultScreenOptions: () => ({
|
||||
presentation: mode,
|
||||
headerShown: headerMode ? headerMode !== 'none' : true,
|
||||
headerMode: headerMode && headerMode !== 'none' ? headerMode : undefined,
|
||||
}),
|
||||
@@ -85,12 +99,14 @@ function StackNavigator({
|
||||
);
|
||||
|
||||
return (
|
||||
<StackView
|
||||
{...rest}
|
||||
state={state}
|
||||
descriptors={descriptors}
|
||||
navigation={navigation}
|
||||
/>
|
||||
<NavigationContent>
|
||||
<StackView
|
||||
{...rest}
|
||||
state={state}
|
||||
descriptors={descriptors}
|
||||
navigation={navigation}
|
||||
/>
|
||||
</NavigationContent>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -246,22 +246,25 @@ export type StackNavigationOptions = StackHeaderOptions &
|
||||
* so that the previous screen isn't transformed or invisible.
|
||||
*/
|
||||
cardStyle?: StyleProp<ViewStyle>;
|
||||
/**
|
||||
* Whether this screen should be presented as a modal or a regular card.
|
||||
*
|
||||
* Specifying this will configure several options:
|
||||
* - `card`: Use the default OS animations for iOS and Android screen transitions.
|
||||
* - `modal`: Use Modal animations. This changes a few things:
|
||||
* - Sets `headerMode` to `screen` for the screen unless specified otherwise.
|
||||
* - Changes the screen animation to match the platform behavior for modals.
|
||||
* - Adjusts the `detachPreviousScreen` option so that the previous screen stays rendered.
|
||||
*
|
||||
* Defaults to 'card'.
|
||||
*/
|
||||
presentation?: 'card' | 'modal';
|
||||
/**
|
||||
* Whether transition animation should be enabled the screen.
|
||||
* If you set it to `false`, the screen won't animate when pushing or popping.
|
||||
* Defaults to `true` on Android and iOS, `false` on Web.
|
||||
*/
|
||||
animationEnabled?: boolean;
|
||||
/**
|
||||
* Whether this screen should be presented as a modal or a regular card.
|
||||
*
|
||||
* If you haven't customized the animations separately, the animation will change based on the value:
|
||||
* - 'modal' - modal animation on iOS and Android. It'll also default `headerMode` to `screen`.
|
||||
* - 'card' - horizontal slide animation on iOS, OS-default animation on Android.
|
||||
*
|
||||
* Defaults to 'card'.
|
||||
*/
|
||||
animationPresentation?: 'card' | 'modal';
|
||||
/**
|
||||
* The type of animation to use when this screen replaces another screen. Defaults to `push`.
|
||||
* When `pop` is used, the `pop` animation is applied to the screen being replaced.
|
||||
@@ -289,18 +292,19 @@ export type StackNavigationOptions = StackHeaderOptions &
|
||||
* Defaults to `false` for the last screen for modals, otherwise `true`.
|
||||
*/
|
||||
detachPreviousScreen?: boolean;
|
||||
/**
|
||||
* If `false`, the keyboard will NOT automatically dismiss when navigating to a new screen from this screen.
|
||||
* Defaults to `true`.
|
||||
*/
|
||||
keyboardHandlingEnabled?: boolean;
|
||||
};
|
||||
|
||||
export type StackNavigationConfig = {
|
||||
/**
|
||||
* If `false`, the keyboard will NOT automatically dismiss when navigating to a new screen.
|
||||
* Defaults to `true`.
|
||||
*/
|
||||
keyboardHandlingEnabled?: boolean;
|
||||
/**
|
||||
* Whether inactive screens should be detached from the view hierarchy to save memory.
|
||||
* Make sure to call `enableScreens` from `react-native-screens` to make it work.
|
||||
* Defaults to `true` on Android, depends on the version of `react-native-screens` on iOS.
|
||||
* This will have no effect if you disable `react-native-screens`.
|
||||
*
|
||||
* Defaults to `true`.
|
||||
*/
|
||||
detachInactiveScreens?: boolean;
|
||||
};
|
||||
@@ -332,7 +336,7 @@ export type StackCardInterpolationProps = {
|
||||
progress: Animated.AnimatedInterpolation;
|
||||
};
|
||||
/**
|
||||
* Values for the current screen the screen after this one in the stack.
|
||||
* Values for the screen after this one in the stack.
|
||||
* This can be `undefined` in case the screen animating is the last one.
|
||||
*/
|
||||
next?: {
|
||||
@@ -411,7 +415,7 @@ export type StackHeaderInterpolationProps = {
|
||||
progress: Animated.AnimatedInterpolation;
|
||||
};
|
||||
/**
|
||||
* Values for the current screen the screen after this one in the stack.
|
||||
* Values for the screen after this one in the stack.
|
||||
* This can be `undefined` in case the screen animating is the last one.
|
||||
*/
|
||||
next?: {
|
||||
|
||||
105
packages/stack/src/utils/useKeyboardManager.tsx
Normal file
105
packages/stack/src/utils/useKeyboardManager.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import * as React from 'react';
|
||||
import { TextInput, Keyboard, HostComponent } from 'react-native';
|
||||
|
||||
type InputRef = React.ElementRef<HostComponent<unknown>> | undefined;
|
||||
|
||||
export default function useKeyboardManager(isEnabled: () => boolean) {
|
||||
// Numeric id of the previously focused text input
|
||||
// When a gesture didn't change the tab, we can restore the focused input with this
|
||||
const previouslyFocusedTextInputRef = React.useRef<InputRef>(undefined);
|
||||
const startTimestampRef = React.useRef<number>(0);
|
||||
const keyboardTimeoutRef = React.useRef<any>();
|
||||
|
||||
const clearKeyboardTimeout = React.useCallback(() => {
|
||||
if (keyboardTimeoutRef.current !== undefined) {
|
||||
clearTimeout(keyboardTimeoutRef.current);
|
||||
keyboardTimeoutRef.current = undefined;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const onPageChangeStart = React.useCallback(() => {
|
||||
if (!isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearKeyboardTimeout();
|
||||
|
||||
const input: InputRef = TextInput.State.currentlyFocusedInput();
|
||||
|
||||
// When a page change begins, blur the currently focused input
|
||||
input?.blur();
|
||||
|
||||
// Store the id of this input so we can refocus it if change was cancelled
|
||||
previouslyFocusedTextInputRef.current = input;
|
||||
|
||||
// Store timestamp for touch start
|
||||
startTimestampRef.current = Date.now();
|
||||
}, [clearKeyboardTimeout, isEnabled]);
|
||||
|
||||
const onPageChangeConfirm = React.useCallback(
|
||||
(force: boolean) => {
|
||||
if (!isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearKeyboardTimeout();
|
||||
|
||||
if (force) {
|
||||
// Always dismiss input, even if we don't have a ref to it
|
||||
// We might not have the ref if onPageChangeStart was never called
|
||||
// This can happen if page change was not from a gesture
|
||||
Keyboard.dismiss();
|
||||
} else {
|
||||
const input = previouslyFocusedTextInputRef.current;
|
||||
|
||||
// Dismiss the keyboard only if an input was a focused before
|
||||
// This makes sure we don't dismiss input on going back and focusing an input
|
||||
input?.blur();
|
||||
}
|
||||
|
||||
// Cleanup the ID on successful page change
|
||||
previouslyFocusedTextInputRef.current = undefined;
|
||||
},
|
||||
[clearKeyboardTimeout, isEnabled]
|
||||
);
|
||||
|
||||
const onPageChangeCancel = React.useCallback(() => {
|
||||
if (!isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearKeyboardTimeout();
|
||||
|
||||
// The page didn't change, we should restore the focus of text input
|
||||
const input = previouslyFocusedTextInputRef.current;
|
||||
|
||||
if (input) {
|
||||
// If the interaction was super short we should make sure keyboard won't hide again.
|
||||
|
||||
// Too fast input refocus will result only in keyboard flashing on screen and hiding right away.
|
||||
// During first ~100ms keyboard will be dismissed no matter what,
|
||||
// so we have to make sure it won't interrupt input refocus logic.
|
||||
// That's why when the interaction is shorter than 100ms we add delay so it won't hide once again.
|
||||
// Subtracting timestamps makes us sure the delay is executed only when needed.
|
||||
if (Date.now() - startTimestampRef.current < 100) {
|
||||
keyboardTimeoutRef.current = setTimeout(() => {
|
||||
input?.focus();
|
||||
previouslyFocusedTextInputRef.current = undefined;
|
||||
}, 100);
|
||||
} else {
|
||||
input?.focus();
|
||||
previouslyFocusedTextInputRef.current = undefined;
|
||||
}
|
||||
}
|
||||
}, [clearKeyboardTimeout, isEnabled]);
|
||||
|
||||
React.useEffect(() => {
|
||||
return () => clearKeyboardTimeout();
|
||||
}, [clearKeyboardTimeout]);
|
||||
|
||||
return {
|
||||
onPageChangeStart,
|
||||
onPageChangeConfirm,
|
||||
onPageChangeCancel,
|
||||
};
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import { TextInput, Keyboard, HostComponent } from 'react-native';
|
||||
|
||||
type Props = {
|
||||
enabled: boolean;
|
||||
children: (props: {
|
||||
onPageChangeStart: () => void;
|
||||
onPageChangeConfirm: (force: boolean) => void;
|
||||
onPageChangeCancel: () => void;
|
||||
}) => React.ReactNode;
|
||||
};
|
||||
|
||||
type InputRef = React.ElementRef<HostComponent<unknown>> | undefined;
|
||||
|
||||
export default class KeyboardManager extends React.Component<Props> {
|
||||
componentWillUnmount() {
|
||||
this.clearKeyboardTimeout();
|
||||
}
|
||||
|
||||
// Numeric id of the previously focused text input
|
||||
// When a gesture didn't change the tab, we can restore the focused input with this
|
||||
private previouslyFocusedTextInput: InputRef = undefined;
|
||||
private startTimestamp: number = 0;
|
||||
private keyboardTimeout: any;
|
||||
|
||||
private clearKeyboardTimeout = () => {
|
||||
if (this.keyboardTimeout !== undefined) {
|
||||
clearTimeout(this.keyboardTimeout);
|
||||
this.keyboardTimeout = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
private handlePageChangeStart = () => {
|
||||
if (!this.props.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.clearKeyboardTimeout();
|
||||
|
||||
const input: InputRef = TextInput.State.currentlyFocusedInput();
|
||||
|
||||
// When a page change begins, blur the currently focused input
|
||||
input?.blur();
|
||||
|
||||
// Store the id of this input so we can refocus it if change was cancelled
|
||||
this.previouslyFocusedTextInput = input;
|
||||
|
||||
// Store timestamp for touch start
|
||||
this.startTimestamp = Date.now();
|
||||
};
|
||||
|
||||
private handlePageChangeConfirm = (force: boolean) => {
|
||||
if (!this.props.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.clearKeyboardTimeout();
|
||||
|
||||
if (force) {
|
||||
// Always dismiss input, even if we don't have a ref to it
|
||||
// We might not have the ref if onPageChangeStart was never called
|
||||
// This can happen if page change was not from a gesture
|
||||
Keyboard.dismiss();
|
||||
} else {
|
||||
const input = this.previouslyFocusedTextInput;
|
||||
|
||||
// Dismiss the keyboard only if an input was a focused before
|
||||
// This makes sure we don't dismiss input on going back and focusing an input
|
||||
input?.blur();
|
||||
}
|
||||
|
||||
// Cleanup the ID on successful page change
|
||||
this.previouslyFocusedTextInput = undefined;
|
||||
};
|
||||
|
||||
private handlePageChangeCancel = () => {
|
||||
if (!this.props.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.clearKeyboardTimeout();
|
||||
|
||||
// The page didn't change, we should restore the focus of text input
|
||||
const input = this.previouslyFocusedTextInput;
|
||||
|
||||
if (input) {
|
||||
// If the interaction was super short we should make sure keyboard won't hide again.
|
||||
|
||||
// Too fast input refocus will result only in keyboard flashing on screen and hiding right away.
|
||||
// During first ~100ms keyboard will be dismissed no matter what,
|
||||
// so we have to make sure it won't interrupt input refocus logic.
|
||||
// That's why when the interaction is shorter than 100ms we add delay so it won't hide once again.
|
||||
// Subtracting timestamps makes us sure the delay is executed only when needed.
|
||||
if (Date.now() - this.startTimestamp < 100) {
|
||||
this.keyboardTimeout = setTimeout(() => {
|
||||
input?.focus();
|
||||
this.previouslyFocusedTextInput = undefined;
|
||||
}, 100);
|
||||
} else {
|
||||
input?.focus();
|
||||
this.previouslyFocusedTextInput = undefined;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return this.props.children({
|
||||
onPageChangeStart: this.handlePageChangeStart,
|
||||
onPageChangeConfirm: this.handlePageChangeConfirm,
|
||||
onPageChangeCancel: this.handlePageChangeCancel,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import type { Props as HeaderContainerProps } from '../Header/HeaderContainer';
|
||||
import Card from './Card';
|
||||
import { forModalPresentationIOS } from '../../TransitionConfigs/CardStyleInterpolators';
|
||||
import ModalPresentationContext from '../../utils/ModalPresentationContext';
|
||||
import useKeyboardManager from '../../utils/useKeyboardManager';
|
||||
import type { Layout, Scene } from '../../types';
|
||||
|
||||
type Props = {
|
||||
@@ -37,9 +38,6 @@ type Props = {
|
||||
closing: boolean
|
||||
) => void;
|
||||
onTransitionEnd?: (props: { route: Route<string> }, closing: boolean) => void;
|
||||
onPageChangeStart?: () => void;
|
||||
onPageChangeConfirm?: (force: boolean) => void;
|
||||
onPageChangeCancel?: () => void;
|
||||
onGestureStart?: (props: { route: Route<string> }) => void;
|
||||
onGestureEnd?: (props: { route: Route<string> }) => void;
|
||||
onGestureCancel?: (props: { route: Route<string> }) => void;
|
||||
@@ -70,9 +68,6 @@ function CardContainer({
|
||||
layout,
|
||||
onCloseRoute,
|
||||
onOpenRoute,
|
||||
onPageChangeCancel,
|
||||
onPageChangeConfirm,
|
||||
onPageChangeStart,
|
||||
onGestureCancel,
|
||||
onGestureEnd,
|
||||
onGestureStart,
|
||||
@@ -88,6 +83,20 @@ function CardContainer({
|
||||
}: Props) {
|
||||
const parentHeaderHeight = React.useContext(HeaderHeightContext);
|
||||
|
||||
const {
|
||||
onPageChangeStart,
|
||||
onPageChangeCancel,
|
||||
onPageChangeConfirm,
|
||||
} = useKeyboardManager(
|
||||
React.useCallback(() => {
|
||||
const { options, navigation } = scene.descriptor;
|
||||
|
||||
return (
|
||||
navigation.isFocused() && options.keyboardHandlingEnabled !== false
|
||||
);
|
||||
}, [scene.descriptor])
|
||||
);
|
||||
|
||||
const handleOpen = () => {
|
||||
const { route } = scene.descriptor;
|
||||
|
||||
@@ -170,7 +179,9 @@ function CardContainer({
|
||||
}, [pointerEvents, scene.progress.next]);
|
||||
|
||||
const {
|
||||
animationPresentation,
|
||||
presentation,
|
||||
detachPreviousScreen,
|
||||
animationEnabled,
|
||||
cardOverlay,
|
||||
cardOverlayEnabled,
|
||||
cardShadowEnabled,
|
||||
@@ -228,9 +239,7 @@ function CardContainer({
|
||||
accessibilityElementsHidden={!focused}
|
||||
importantForAccessibility={focused ? 'auto' : 'no-hide-descendants'}
|
||||
pointerEvents={active ? 'box-none' : pointerEvents}
|
||||
pageOverflowEnabled={
|
||||
headerMode !== 'float' && animationPresentation !== 'modal'
|
||||
}
|
||||
pageOverflowEnabled={headerMode !== 'float' && presentation !== 'modal'}
|
||||
headerDarkContent={headerDarkContent}
|
||||
containerStyle={
|
||||
hasAbsoluteFloatHeader && headerMode !== 'screen'
|
||||
@@ -243,6 +252,15 @@ function CardContainer({
|
||||
// This is necessary to avoid unfocused larger pages increasing scroll area
|
||||
// The issue can be seen on the web when a smaller screen is pushed over a larger one
|
||||
overflow: active ? undefined : 'hidden',
|
||||
display:
|
||||
// Hide unfocused screens when animation isn't enabled
|
||||
// This is also necessary for a11y on web
|
||||
animationEnabled === false &&
|
||||
detachPreviousScreen !== false &&
|
||||
presentation !== 'modal' &&
|
||||
!focused
|
||||
? 'none'
|
||||
: 'flex',
|
||||
},
|
||||
StyleSheet.absoluteFill,
|
||||
]}
|
||||
|
||||
@@ -63,9 +63,6 @@ type Props = {
|
||||
closing: boolean
|
||||
) => void;
|
||||
onTransitionEnd: (props: { route: Route<string> }, closing: boolean) => void;
|
||||
onPageChangeStart?: () => void;
|
||||
onPageChangeConfirm?: (force: boolean) => void;
|
||||
onPageChangeCancel?: () => void;
|
||||
onGestureStart?: (props: { route: Route<string> }) => void;
|
||||
onGestureEnd?: (props: { route: Route<string> }) => void;
|
||||
onGestureCancel?: (props: { route: Route<string> }) => void;
|
||||
@@ -122,8 +119,8 @@ const getDistanceFromOptions = (
|
||||
descriptor?: StackDescriptor
|
||||
) => {
|
||||
const {
|
||||
animationPresentation,
|
||||
gestureDirection = animationPresentation === 'modal'
|
||||
presentation,
|
||||
gestureDirection = presentation === 'modal'
|
||||
? ModalTransition.gestureDirection
|
||||
: DefaultTransition.gestureDirection,
|
||||
} = (descriptor?.options || {}) as StackNavigationOptions;
|
||||
@@ -214,20 +211,30 @@ export default class CardStack extends React.Component<Props, State> {
|
||||
props.descriptors[previousRoute?.key] ||
|
||||
state.descriptors[previousRoute?.key];
|
||||
|
||||
const { options } = descriptor;
|
||||
// When a screen is not the last, it should use next screen's transition config
|
||||
// Many transitions also animate the previous screen, so using 2 different transitions doesn't look right
|
||||
// For example combining a slide and a modal transition would look wrong otherwise
|
||||
// With this approach, combining different transition styles in the same navigator mostly looks right
|
||||
// This will still be broken when 2 transitions have different idle state (e.g. modal presentation),
|
||||
// but majority of the transitions look alright
|
||||
const optionsForTransitionConfig =
|
||||
index !== self.length - 1 && nextDescriptor
|
||||
? nextDescriptor.options
|
||||
: descriptor.options;
|
||||
|
||||
let defaultTransitionPreset =
|
||||
options.animationPresentation === 'modal'
|
||||
optionsForTransitionConfig.presentation === 'modal'
|
||||
? ModalTransition
|
||||
: DefaultTransition;
|
||||
|
||||
const {
|
||||
animationEnabled = Platform.OS !== 'web' &&
|
||||
animationEnabled = index !== 0 &&
|
||||
Platform.OS !== 'web' &&
|
||||
Platform.OS !== 'windows' &&
|
||||
Platform.OS !== 'macos',
|
||||
gestureEnabled = Platform.OS === 'ios' &&
|
||||
animationEnabled &&
|
||||
index !== 0,
|
||||
gestureEnabled = index !== 0 &&
|
||||
Platform.OS === 'ios' &&
|
||||
animationEnabled,
|
||||
gestureDirection = defaultTransitionPreset.gestureDirection,
|
||||
transitionSpec = defaultTransitionPreset.transitionSpec,
|
||||
cardStyleInterpolator = animationEnabled === false
|
||||
@@ -236,52 +243,16 @@ export default class CardStack extends React.Component<Props, State> {
|
||||
headerStyleInterpolator = defaultTransitionPreset.headerStyleInterpolator,
|
||||
cardOverlayEnabled = Platform.OS !== 'ios' ||
|
||||
cardStyleInterpolator === forModalPresentationIOS,
|
||||
} = options;
|
||||
|
||||
let transitionConfig = {
|
||||
gestureDirection,
|
||||
transitionSpec,
|
||||
cardStyleInterpolator,
|
||||
headerStyleInterpolator,
|
||||
cardOverlayEnabled,
|
||||
};
|
||||
|
||||
// When a screen is not the last, it should use next screen's transition config
|
||||
// Many transitions also animate the previous screen, so using 2 different transitions doesn't look right
|
||||
// For example combining a slide and a modal transition would look wrong otherwise
|
||||
// With this approach, combining different transition styles in the same navigator mostly looks right
|
||||
// This will still be broken when 2 transitions have different idle state (e.g. modal presentation),
|
||||
// but majority of the transitions look alright
|
||||
if (index !== self.length - 1) {
|
||||
if (nextDescriptor) {
|
||||
const {
|
||||
animationEnabled,
|
||||
gestureDirection = defaultTransitionPreset.gestureDirection,
|
||||
transitionSpec = defaultTransitionPreset.transitionSpec,
|
||||
cardStyleInterpolator = animationEnabled === false
|
||||
? forNoAnimationCard
|
||||
: defaultTransitionPreset.cardStyleInterpolator,
|
||||
headerStyleInterpolator = defaultTransitionPreset.headerStyleInterpolator,
|
||||
cardOverlayEnabled = descriptor.options.cardOverlayEnabled ??
|
||||
cardStyleInterpolator === forModalPresentationIOS,
|
||||
} = nextDescriptor.options;
|
||||
|
||||
transitionConfig = {
|
||||
gestureDirection,
|
||||
transitionSpec,
|
||||
cardStyleInterpolator,
|
||||
headerStyleInterpolator,
|
||||
cardOverlayEnabled,
|
||||
};
|
||||
}
|
||||
}
|
||||
} = optionsForTransitionConfig;
|
||||
|
||||
const headerMode: StackHeaderMode =
|
||||
options.headerMode ??
|
||||
(options.animationPresentation !== 'modal' &&
|
||||
transitionConfig.cardStyleInterpolator !== forModalPresentationIOS &&
|
||||
descriptor.options.headerMode ??
|
||||
(!(
|
||||
optionsForTransitionConfig.presentation === 'modal' ||
|
||||
cardStyleInterpolator === forModalPresentationIOS
|
||||
) &&
|
||||
Platform.OS === 'ios' &&
|
||||
options.header === undefined
|
||||
descriptor.options.header === undefined
|
||||
? 'float'
|
||||
: 'screen');
|
||||
|
||||
@@ -290,10 +261,14 @@ export default class CardStack extends React.Component<Props, State> {
|
||||
descriptor: {
|
||||
...descriptor,
|
||||
options: {
|
||||
...options,
|
||||
...transitionConfig,
|
||||
...descriptor.options,
|
||||
animationEnabled,
|
||||
cardOverlayEnabled,
|
||||
cardStyleInterpolator,
|
||||
gestureDirection,
|
||||
gestureEnabled,
|
||||
headerStyleInterpolator,
|
||||
transitionSpec,
|
||||
headerMode,
|
||||
},
|
||||
},
|
||||
@@ -455,9 +430,6 @@ export default class CardStack extends React.Component<Props, State> {
|
||||
isParentHeaderShown,
|
||||
onTransitionStart,
|
||||
onTransitionEnd,
|
||||
onPageChangeStart,
|
||||
onPageChangeConfirm,
|
||||
onPageChangeCancel,
|
||||
onGestureStart,
|
||||
onGestureEnd,
|
||||
onGestureCancel,
|
||||
@@ -492,7 +464,7 @@ export default class CardStack extends React.Component<Props, State> {
|
||||
const { options } = scenes[i].descriptor;
|
||||
const {
|
||||
// By default, we don't want to detach the previous screen of the active one for modals
|
||||
detachPreviousScreen = options.animationPresentation === 'modal' ||
|
||||
detachPreviousScreen = options.presentation === 'modal' ||
|
||||
options.cardStyleInterpolator === forModalPresentationIOS
|
||||
? i !== scenes.length - 1
|
||||
: true,
|
||||
@@ -628,9 +600,6 @@ export default class CardStack extends React.Component<Props, State> {
|
||||
safeAreaInsetRight={safeAreaInsetRight}
|
||||
safeAreaInsetBottom={safeAreaInsetBottom}
|
||||
safeAreaInsetLeft={safeAreaInsetLeft}
|
||||
onPageChangeStart={onPageChangeStart}
|
||||
onPageChangeConfirm={onPageChangeConfirm}
|
||||
onPageChangeCancel={onPageChangeCancel}
|
||||
onGestureStart={onGestureStart}
|
||||
onGestureCancel={onGestureCancel}
|
||||
onGestureEnd={onGestureEnd}
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
EdgeInsets,
|
||||
} from 'react-native-safe-area-context';
|
||||
import {
|
||||
NavigationHelpersContext,
|
||||
StackActions,
|
||||
StackNavigationState,
|
||||
Route,
|
||||
@@ -18,7 +17,6 @@ import {
|
||||
|
||||
import { GestureHandlerRootView } from '../GestureHandler';
|
||||
import CardStack from './CardStack';
|
||||
import KeyboardManager from '../KeyboardManager';
|
||||
import HeaderContainer, {
|
||||
Props as HeaderContainerProps,
|
||||
} from '../Header/HeaderContainer';
|
||||
@@ -418,8 +416,6 @@ export default class StackView extends React.Component<Props, State> {
|
||||
render() {
|
||||
const {
|
||||
state,
|
||||
navigation,
|
||||
keyboardHandlingEnabled,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
descriptors: _,
|
||||
...rest
|
||||
@@ -433,45 +429,38 @@ export default class StackView extends React.Component<Props, State> {
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
<NavigationHelpersContext.Provider value={navigation}>
|
||||
<GestureHandlerWrapper style={styles.container}>
|
||||
<SafeAreaProviderCompat>
|
||||
<SafeAreaInsetsContext.Consumer>
|
||||
{(insets) => (
|
||||
<KeyboardManager enabled={keyboardHandlingEnabled !== false}>
|
||||
{(props) => (
|
||||
<HeaderShownContext.Consumer>
|
||||
{(isParentHeaderShown) => (
|
||||
<CardStack
|
||||
insets={insets as EdgeInsets}
|
||||
isParentHeaderShown={isParentHeaderShown}
|
||||
getPreviousRoute={this.getPreviousRoute}
|
||||
routes={routes}
|
||||
openingRouteKeys={openingRouteKeys}
|
||||
closingRouteKeys={closingRouteKeys}
|
||||
onOpenRoute={this.handleOpenRoute}
|
||||
onCloseRoute={this.handleCloseRoute}
|
||||
onTransitionStart={this.handleTransitionStart}
|
||||
onTransitionEnd={this.handleTransitionEnd}
|
||||
renderHeader={this.renderHeader}
|
||||
renderScene={this.renderScene}
|
||||
state={state}
|
||||
descriptors={descriptors}
|
||||
onGestureStart={this.handleGestureStart}
|
||||
onGestureEnd={this.handleGestureEnd}
|
||||
onGestureCancel={this.handleGestureCancel}
|
||||
{...rest}
|
||||
{...props}
|
||||
/>
|
||||
)}
|
||||
</HeaderShownContext.Consumer>
|
||||
)}
|
||||
</KeyboardManager>
|
||||
)}
|
||||
</SafeAreaInsetsContext.Consumer>
|
||||
</SafeAreaProviderCompat>
|
||||
</GestureHandlerWrapper>
|
||||
</NavigationHelpersContext.Provider>
|
||||
<GestureHandlerWrapper style={styles.container}>
|
||||
<SafeAreaProviderCompat>
|
||||
<SafeAreaInsetsContext.Consumer>
|
||||
{(insets) => (
|
||||
<HeaderShownContext.Consumer>
|
||||
{(isParentHeaderShown) => (
|
||||
<CardStack
|
||||
insets={insets as EdgeInsets}
|
||||
isParentHeaderShown={isParentHeaderShown}
|
||||
getPreviousRoute={this.getPreviousRoute}
|
||||
routes={routes}
|
||||
openingRouteKeys={openingRouteKeys}
|
||||
closingRouteKeys={closingRouteKeys}
|
||||
onOpenRoute={this.handleOpenRoute}
|
||||
onCloseRoute={this.handleCloseRoute}
|
||||
onTransitionStart={this.handleTransitionStart}
|
||||
onTransitionEnd={this.handleTransitionEnd}
|
||||
renderHeader={this.renderHeader}
|
||||
renderScene={this.renderScene}
|
||||
state={state}
|
||||
descriptors={descriptors}
|
||||
onGestureStart={this.handleGestureStart}
|
||||
onGestureEnd={this.handleGestureEnd}
|
||||
onGestureCancel={this.handleGestureCancel}
|
||||
{...rest}
|
||||
/>
|
||||
)}
|
||||
</HeaderShownContext.Consumer>
|
||||
)}
|
||||
</SafeAreaInsetsContext.Consumer>
|
||||
</SafeAreaProviderCompat>
|
||||
</GestureHandlerWrapper>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
30
yarn.lock
30
yarn.lock
@@ -3717,6 +3717,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.1.tgz#283f669ff76d7b8260df8ab7a4262cc83d988256"
|
||||
integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==
|
||||
|
||||
"@types/mock-require@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/mock-require/-/mock-require-2.0.0.tgz#57a4f0db0b4b6274f610a2d2c20beb3c842181e1"
|
||||
integrity sha512-nOgjoE5bBiDeiA+z41i95makyHUSMWQMOPocP+J67Pqx/68HAXaeWN1NFtrAYYV6LrISIZZ8vKHm/a50k0f6Sg==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/node-fetch@^2.5.9":
|
||||
version "2.5.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.9.tgz#c04a12115aa436f189e39579272b305e477621b4"
|
||||
@@ -9069,6 +9076,11 @@ gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2:
|
||||
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
|
||||
|
||||
get-caller-file@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
|
||||
integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
|
||||
|
||||
get-caller-file@^2.0.1, get-caller-file@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
@@ -12847,6 +12859,14 @@ mock-require-assets@^0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/mock-require-assets/-/mock-require-assets-0.0.1.tgz#94136f70e5b009c52c2df3b45724d15ab4f0cb98"
|
||||
integrity sha1-lBNvcOWwCcUsLfO0VyTRWrTwy5g=
|
||||
|
||||
mock-require@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/mock-require/-/mock-require-3.0.3.tgz#ccd544d9eae81dd576b3f219f69ec867318a1946"
|
||||
integrity sha512-lLzfLHcyc10MKQnNUCv7dMcoY/2Qxd6wJfbqCcVk3LDb8An4hF6ohk5AztrvgKhJCqj36uyzi/p5se+tvyD+Wg==
|
||||
dependencies:
|
||||
get-caller-file "^1.0.2"
|
||||
normalize-path "^2.1.1"
|
||||
|
||||
mockdate@^3.0.2:
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/mockdate/-/mockdate-3.0.5.tgz#789be686deb3149e7df2b663d2bc4392bc3284fb"
|
||||
@@ -15280,7 +15300,7 @@ react-native-web@~0.15.0:
|
||||
prop-types "^15.6.0"
|
||||
react-timer-mixin "^0.13.4"
|
||||
|
||||
"react-native@https://github.com/expo/react-native/archive/sdk-41.0.0.tar.gz", react-native@~0.63.2, react-native@~0.63.4:
|
||||
"react-native@https://github.com/expo/react-native/archive/sdk-41.0.0.tar.gz", react-native@~0.63.4:
|
||||
version "0.63.4"
|
||||
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.63.4.tgz#2210fdd404c94a5fa6b423c6de86f8e48810ec36"
|
||||
integrity sha512-I4kM8kYO2mWEYUFITMcpRulcy4/jd+j9T6PbIzR0FuMcz/xwd+JwHoLPa1HmCesvR1RDOw9o4D+OFLwuXXfmGw==
|
||||
@@ -18225,10 +18245,10 @@ walker@^1.0.7, walker@~1.0.5:
|
||||
dependencies:
|
||||
makeerror "1.0.x"
|
||||
|
||||
warn-once@^0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/warn-once/-/warn-once-0.0.1.tgz#71eda54c88f240c4461e5c7a84cac2263caf3a4e"
|
||||
integrity sha512-Sh/kR0dQ9Tlr70E2zuR8mZ0yxmN9kGMNfvlwWWRi7frSox2uRC7U659Le8jBIqvjykSbvo9JX9ttsqw4vZPLmA==
|
||||
warn-once@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/warn-once/-/warn-once-0.1.0.tgz#4f58d89b84f968d0389176aa99e0cf0f14ffd4c8"
|
||||
integrity sha512-recZTSvuaH/On5ZU5ywq66y99lImWqzP93+AiUo9LUwG8gXHW+LJjhOd6REJHm7qb0niYqrEQJvbHSQfuJtTqA==
|
||||
|
||||
watchpack-chokidar2@^2.0.1:
|
||||
version "2.0.1"
|
||||
|
||||
Reference in New Issue
Block a user