Compare commits

...

32 Commits

Author SHA1 Message Date
Satyajit Sahoo
bc9b044fb3 chore: publish
- @react-navigation/bottom-tabs@5.2.2
 - @react-navigation/compat@5.1.4
 - @react-navigation/core@5.2.3
 - @react-navigation/drawer@5.3.2
 - @react-navigation/material-bottom-tabs@5.1.4
 - @react-navigation/material-top-tabs@5.1.4
 - @react-navigation/native@5.1.1
 - @react-navigation/stack@5.2.2
2020-03-19 19:48:37 +01:00
Alexey Vlasenko
f24d3a3461 fix: fix closing stack using inverted gesture. (#7824)
Co-authored-by: Satyajit Sahoo <satyajit.happy@gmail.com>
2020-03-19 19:32:29 +01:00
Satyajit Sahoo
3df65e2819 fix: initialize height and width to zero if undefined
closes #6789
2020-03-19 19:03:23 +01:00
Satyajit Sahoo
5c4afc5cb4 fix: close drawer on pressing Esc on web
closes #6745
2020-03-19 18:51:16 +01:00
Satyajit Sahoo
d5bb357053 chore: temporarily disables devtools until we add a public API
closes #7726
2020-03-19 18:39:04 +01:00
Satyajit Sahoo
b1fe73097f fix: only dismiss previously focused input on page change. closes #6918 2020-03-19 18:30:54 +01:00
Satyajit Sahoo
49f6fed6d3 fix: fix blank page if stack was inside display: none before 2020-03-19 18:11:55 +01:00
Satyajit Sahoo
b1a65fc73e fix: don't use react-native-screens on web
seems `react-native-screens` doesn't handle active screens properly and shows a blank page instead on web when a number is specified in the `active` prop.

closes #7485
2020-03-19 17:28:35 +01:00
Noemi Rozpara
3ea8eec432 fix: fix permanent sidebar position (#7830) 2020-03-19 11:44:13 +01:00
Satyajit Sahoo
00e0f05190 chore: publish
- @react-navigation/drawer@5.3.1
2020-03-17 20:13:03 +01:00
Satyajit Sahoo
193c344ba5 refactor: fix useIsDrawerOpen hook 2020-03-17 19:22:12 +01:00
Satyajit Sahoo
358d9e9feb chore: publish
- @react-navigation/bottom-tabs@5.2.1
 - @react-navigation/compat@5.1.3
 - @react-navigation/drawer@5.3.0
 - @react-navigation/material-bottom-tabs@5.1.3
 - @react-navigation/material-top-tabs@5.1.3
 - @react-navigation/native@5.1.0
 - @react-navigation/stack@5.2.1
2020-03-17 14:37:21 +01:00
Satyajit Sahoo
6a5d0a035a feat: add permanent drawer type (#7818)
Co-authored-by: NoemiRozpara <nrozpara@gmail.com>
2020-03-17 14:11:00 +01:00
Satyajit Sahoo
b75744abd5 chore: publish
- @react-navigation/bottom-tabs@5.2.0
 - @react-navigation/compat@5.1.2
 - @react-navigation/core@5.2.2
 - @react-navigation/drawer@5.2.0
 - @react-navigation/material-bottom-tabs@5.1.2
 - @react-navigation/material-top-tabs@5.1.2
 - @react-navigation/native@5.0.10
 - @react-navigation/routers@5.1.1
 - @react-navigation/stack@5.2.0
2020-03-16 14:29:25 +01:00
Satyajit Sahoo
6dbda1a0c2 chore: upgrade depenendecies 2020-03-16 14:28:10 +01:00
Michał Osadnik
70029d6c13 feat: add an option to change use a custom card overlay (#7809)
I find it sometimes useful to define overlay renderer on my own. Eg. I needed to replace the background with BlurView and with this API I find it quite easy

Co-authored-by: Satyajit Sahoo <satyajit.happy@gmail.com>
2020-03-16 14:28:10 +01:00
Tien Pham
469d0542c7 fix: fix back gesture cancellation (#7700)
The problem here is that when we scroll back really fast, even though velocity is negative, `Math.abs(translation + velocity * gestureVelocityImpact)` will end up bigger than `distance / 2`.

I removed the `Math.abs`, I think it's not necessary. When `translation + velocity * gestureVelocityImpact` is negative, it's also < `distance / 2` and we should just close the screen.

Closes #6782
2020-03-16 12:03:16 +01:00
Vojtech Novak
0dcaea3242 fix: fix android header title font weight (#7720)
the previously used fort weight of 500 would effectively be converted to `fontWeight: bold` because of https://github.com/facebook/react-native/pull/25341

this fixes the title appearance to look as customary
2020-03-16 11:05:02 +01:00
Satyajit Sahoo
646cbfb28e refactor: move action helper types to routers 2020-03-13 12:34:37 +01:00
Satyajit Sahoo
660cac3557 fix: don't handle action if no routes are present 2020-03-11 18:17:19 +01:00
Satyajit Sahoo
e637250a7e chore: add a triage action for feature requests 2020-03-11 03:19:49 +01:00
Satyajit Sahoo
82af7bed71 feat: add safeAreaInsets to bottom tabs 2020-03-09 22:21:04 +01:00
Michał Osadnik
cb46d0bca4 feat: make useIsDrawerOpen workable inside drawer content (#7746) 2020-03-06 15:46:13 +01:00
Mike Rogers
b3665a325d Correcting spelling 'Supress' > 'Suppress' (#7731) 2020-03-06 07:24:43 -03:00
Satyajit Sahoo
0cc7a12b9c chore: remove stale action coz it's not keeping issues open after reply 2020-03-04 13:53:42 +01:00
Satyajit Sahoo
90e417248d chore: fix typo in expo preview url 2020-03-03 18:38:20 +01:00
Satyajit Sahoo
e071a978e6 chore: publish
- @react-navigation/bottom-tabs@5.1.1
 - @react-navigation/compat@5.1.1
 - @react-navigation/core@5.2.1
 - @react-navigation/drawer@5.1.1
 - @react-navigation/material-bottom-tabs@5.1.1
 - @react-navigation/material-top-tabs@5.1.1
 - @react-navigation/native@5.0.9
 - @react-navigation/routers@5.1.0
 - @react-navigation/stack@5.1.1
2020-03-03 11:58:45 +01:00
Satyajit Sahoo
296c836064 fix: ignore back button press if screen isn't focused. closes #7673 2020-03-03 11:34:38 +01:00
Satyajit Sahoo
09f6808d7d feat: make reset bubble up 2020-03-01 02:45:08 +01:00
Satyajit Sahoo
5bb0f405ce fix: fix links for documentation 2020-02-28 17:12:18 +01:00
Satyajit Sahoo
2dfa4f3629 fix: move updating state to useEffect 2020-02-28 17:01:58 +01:00
Satyajit Sahoo
cf41288760 chore: run clean before release 2020-02-26 15:03:57 +01:00
63 changed files with 1893 additions and 1028 deletions

View File

@@ -44,7 +44,7 @@ jobs:
- name: Get expo link - name: Get expo link
id: expo id: expo
run: echo "::set-output name=path::@react-navigation/react-react-navigationample?release-channel=pr-${{ github.event.number }}" run: echo "::set-output name=path::@react-navigation/react-navigation-example?release-channel=pr-${{ github.event.number }}"
- name: Comment on PR - name: Comment on PR
uses: unsplash/comment-on-pr@master uses: unsplash/comment-on-pr@master

View File

@@ -1,20 +0,0 @@
name: "Close stale issues and pull requests"
on:
schedule:
- cron: "0 0 * * *"
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'Hello 👋, this issue has been open for more than 3 months with no activity on it. If the issue is still present in the latest version, please leave a comment within 7 days to keep it open, otherwise it will be closed automatically. If you found a solution on workaround for the issue, please comment here for others to find. If this issue is critical for you, please consider sending a pull request to fix the issue.'
stale-pr-message: 'Hello 👋, this pull request has been open for more than 3 months with no activity on it. If you think this is still necessary with the latest version, please comment and ping a maintainer to get this reviewed, otherwise it will be closed automatically in 7 days.'
days-before-stale: 90
days-before-close: 7
stale-issue-label: 'stale'
stale-pr-label: 'stale'
exempt-issue-label: 'keep open'
exempt-pr-label: 'keep open'

View File

@@ -36,3 +36,14 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
args: comment "Hey! Thanks for opening the issue. The issue tracker is intended for only tracking bug reports. This helps us prioritize fixing bugs in the library. Seems you have a usage question. Please ask the question on [StackOverflow](https://stackoverflow.com/questions/tagged/react-navigation) instead using the `react-navigation` label. You can also chat with other community members on [Reactiflux Discord server](https://www.reactiflux.com/) in the `#react-navigation` channel." args: comment "Hey! Thanks for opening the issue. The issue tracker is intended for only tracking bug reports. This helps us prioritize fixing bugs in the library. Seems you have a usage question. Please ask the question on [StackOverflow](https://stackoverflow.com/questions/tagged/react-navigation) instead using the `react-navigation` label. You can also chat with other community members on [Reactiflux Discord server](https://www.reactiflux.com/) in the `#react-navigation` channel."
feature-request:
runs-on: ubuntu-latest
if: github.event.label.name == 'feature-request'
steps:
- uses: actions/checkout@master
- uses: actions/github@v1.0.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
args: comment "Hey! Thanks for opening the issue. The issue tracker is intended for only tracking bug reports. Seems you have a feature request. Please post the feature request on [Canny](https://react-navigation.canny.io/feature-requests). This lets other users upvote your feature request and helps us prioritize the most requested features."

1
.gitignore vendored
View File

@@ -6,6 +6,7 @@
.gradle .gradle
.project .project
.settings .settings
.history
local.properties local.properties

View File

@@ -12,7 +12,7 @@
}, },
"dependencies": { "dependencies": {
"@expo/vector-icons": "^10.0.0", "@expo/vector-icons": "^10.0.0",
"@react-native-community/masked-view": "0.1.6", "@react-native-community/masked-view": "0.1.7",
"@types/react-native-restart": "^0.0.0", "@types/react-native-restart": "^0.0.0",
"color": "^3.1.2", "color": "^3.1.2",
"expo": "^36.0.2", "expo": "^36.0.2",
@@ -21,22 +21,22 @@
"react": "~16.9.0", "react": "~16.9.0",
"react-dom": "~16.9.0", "react-dom": "~16.9.0",
"react-native": "~0.61.5", "react-native": "~0.61.5",
"react-native-gesture-handler": "^1.5.6", "react-native-gesture-handler": "^1.6.0",
"react-native-paper": "^3.6.0", "react-native-paper": "^3.6.0",
"react-native-reanimated": "^1.7.0", "react-native-reanimated": "^1.7.0",
"react-native-restart": "^0.0.13", "react-native-restart": "^0.0.14",
"react-native-safe-area-context": "^0.7.2", "react-native-safe-area-context": "^0.7.3",
"react-native-screens": "^2.0.0-beta.2", "react-native-screens": "^2.3.0",
"react-native-tab-view": "2.13.0", "react-native-tab-view": "2.13.0",
"react-native-unimodules": "^0.7.0", "react-native-unimodules": "^0.7.0",
"react-native-web": "^0.11.7" "react-native-web": "^0.11.7"
}, },
"devDependencies": { "devDependencies": {
"@expo/webpack-config": "^0.10.12", "@expo/webpack-config": "^0.11.7",
"@types/react": "^16.9.19", "@types/react": "^16.9.23",
"@types/react-native": "^0.60.30", "@types/react-native": "^0.61.22",
"babel-preset-expo": "^8.0.0", "babel-preset-expo": "^8.0.0",
"expo-cli": "^3.11.9", "expo-cli": "^3.13.8",
"typescript": "^3.7.5" "typescript": "^3.7.5"
} }
} }

View File

@@ -6,6 +6,8 @@ import {
Platform, Platform,
StatusBar, StatusBar,
I18nManager, I18nManager,
Dimensions,
ScaledSize,
} from 'react-native'; } from 'react-native';
// eslint-disable-next-line import/no-unresolved // eslint-disable-next-line import/no-unresolved
import { enableScreens } from 'react-native-screens'; import { enableScreens } from 'react-native-screens';
@@ -196,10 +198,24 @@ export default function App() {
}; };
}, [theme.colors, theme.dark]); }, [theme.colors, theme.dark]);
const [dimensions, setDimensions] = React.useState(Dimensions.get('window'));
React.useEffect(() => {
const onDimensionsChange = ({ window }: { window: ScaledSize }) => {
setDimensions(window);
};
Dimensions.addEventListener('change', onDimensionsChange);
return () => Dimensions.removeEventListener('change', onDimensionsChange);
}, []);
if (!isReady) { if (!isReady) {
return null; return null;
} }
const isLargeScreen = dimensions.width > 900;
return ( return (
<PaperProvider theme={paperTheme}> <PaperProvider theme={paperTheme}>
{Platform.OS === 'ios' && ( {Platform.OS === 'ios' && (
@@ -216,7 +232,7 @@ export default function App() {
} }
theme={theme} theme={theme}
> >
<Drawer.Navigator> <Drawer.Navigator drawerType={isLargeScreen ? 'permanent' : undefined}>
<Drawer.Screen <Drawer.Screen
name="Root" name="Root"
options={{ options={{
@@ -240,13 +256,15 @@ export default function App() {
name="Home" name="Home"
options={{ options={{
title: 'Examples', title: 'Examples',
headerLeft: () => ( headerLeft: isLargeScreen
<Appbar.Action ? undefined
color={theme.colors.text} : () => (
icon="menu" <Appbar.Action
onPress={() => navigation.toggleDrawer()} color={theme.colors.text}
/> icon="menu"
), onPress={() => navigation.toggleDrawer()}
/>
),
}} }}
> >
{({ {({

View File

@@ -1,7 +1,7 @@
const error = console.error; const error = console.error;
console.error = (...args) => console.error = (...args) =>
// Supress error messages regarding error boundary in tests // Suppress error messages regarding error boundary in tests
/(Consider adding an error boundary to your tree to customize error handling behavior|React will try to recreate this component tree from scratch using the error boundary you provided|Error boundaries should implement getDerivedStateFromError)/m.test( /(Consider adding an error boundary to your tree to customize error handling behavior|React will try to recreate this component tree from scratch using the error boundary you provided|Error boundaries should implement getDerivedStateFromError)/m.test(
args[0] args[0]
) )

View File

@@ -20,26 +20,27 @@
"lint": "eslint --ext '.js,.ts,.tsx' .", "lint": "eslint --ext '.js,.ts,.tsx' .",
"typescript": "tsc --noEmit", "typescript": "tsc --noEmit",
"test": "jest", "test": "jest",
"prerelease": "lerna run clean",
"release": "lerna publish", "release": "lerna publish",
"example": "yarn --cwd example" "example": "yarn --cwd example"
}, },
"devDependencies": { "devDependencies": {
"@babel/plugin-proposal-class-properties": "^7.8.3", "@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-proposal-optional-chaining": "^7.8.3", "@babel/plugin-proposal-optional-chaining": "^7.8.3",
"@babel/preset-env": "^7.8.4", "@babel/preset-env": "^7.8.7",
"@babel/preset-flow": "^7.8.3", "@babel/preset-flow": "^7.8.3",
"@babel/preset-react": "^7.8.3", "@babel/preset-react": "^7.8.3",
"@babel/preset-typescript": "^7.8.3", "@babel/preset-typescript": "^7.8.3",
"@babel/runtime": "^7.8.4", "@babel/runtime": "^7.8.7",
"@commitlint/config-conventional": "^8.3.4", "@commitlint/config-conventional": "^8.3.4",
"@types/jest": "^25.1.2", "@types/jest": "^25.1.4",
"codecov": "^3.6.5", "codecov": "^3.6.5",
"commitlint": "^8.3.5", "commitlint": "^8.3.5",
"core-js": "^3.6.4", "core-js": "^3.6.4",
"detox": "^15.1.4", "detox": "^16.0.0",
"eslint": "^6.8.0", "eslint": "^6.8.0",
"eslint-config-satya164": "^3.1.5", "eslint-config-satya164": "^3.1.5",
"husky": "^4.2.1", "husky": "^4.2.3",
"jest": "^25.1.0", "jest": "^25.1.0",
"lerna": "^3.20.2", "lerna": "^3.20.2",
"prettier": "^1.19.1", "prettier": "^1.19.1",

View File

@@ -3,6 +3,45 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [5.2.2](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.1...@react-navigation/bottom-tabs@5.2.2) (2020-03-19)
### Bug Fixes
* don't use react-native-screens on web ([b1a65fc](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/b1a65fc73e8603ae2c06ef101a74df31e80bb9b2)), closes [#7485](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/issues/7485)
* initialize height and width to zero if undefined ([3df65e2](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/3df65e28197db3bb8371059146546d57661c5ba3)), closes [#6789](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/issues/6789)
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.0...@react-navigation/bottom-tabs@5.2.1) (2020-03-17)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.2.0](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.1.1...@react-navigation/bottom-tabs@5.2.0) (2020-03-16)
### Features
* add safeAreaInsets to bottom tabs ([82af7be](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/82af7bed7135e42e24693b48cf7f1c6f9f5a6981))
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.1.0...@react-navigation/bottom-tabs@5.1.1) (2020-03-03)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.7...@react-navigation/bottom-tabs@5.1.0) (2020-02-26) # [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.7...@react-navigation/bottom-tabs@5.1.0) (2020-02-26)

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/bottom-tabs", "name": "@react-navigation/bottom-tabs",
"description": "Bottom tab navigator following iOS design guidelines", "description": "Bottom tab navigator following iOS design guidelines",
"version": "5.1.0", "version": "5.2.2",
"keywords": [ "keywords": [
"react-native-component", "react-native-component",
"react-component", "react-component",
@@ -34,22 +34,24 @@
"react-native-iphone-x-helper": "^1.2.1" "react-native-iphone-x-helper": "^1.2.1"
}, },
"devDependencies": { "devDependencies": {
"@react-native-community/bob": "^0.9.3", "@react-native-community/bob": "^0.10.0",
"@react-navigation/native": "^5.0.8", "@react-navigation/native": "^5.1.1",
"@types/color": "^3.0.1", "@types/color": "^3.0.1",
"@types/react": "^16.9.19", "@types/react": "^16.9.23",
"@types/react-native": "^0.60.30", "@types/react-native": "^0.61.22",
"del-cli": "^3.0.0", "del-cli": "^3.0.0",
"react": "~16.9.0", "react": "~16.9.0",
"react-native": "~0.61.5", "react-native": "~0.61.5",
"react-native-safe-area-context": "^0.7.2", "react-native-safe-area-context": "^0.7.3",
"react-native-screens": "^2.3.0",
"typescript": "^3.7.5" "typescript": "^3.7.5"
}, },
"peerDependencies": { "peerDependencies": {
"@react-navigation/native": "^5.0.5", "@react-navigation/native": "^5.0.5",
"react": "*", "react": "*",
"react-native": "*", "react-native": "*",
"react-native-safe-area-context": ">= 0.6.0" "react-native-safe-area-context": ">= 0.6.0",
"react-native-screens": ">= 2.0.0-alpha.0 || >= 2.0.0-beta.0 || >= 2.0.0"
}, },
"@react-native-community/bob": { "@react-native-community/bob": {
"source": "src", "source": "src",

View File

@@ -11,6 +11,7 @@ import {
ParamListBase, ParamListBase,
Descriptor, Descriptor,
TabNavigationState, TabNavigationState,
TabActionHelpers,
} from '@react-navigation/native'; } from '@react-navigation/native';
export type BottomTabNavigationEventMap = { export type BottomTabNavigationEventMap = {
@@ -40,19 +41,8 @@ export type BottomTabNavigationProp<
TabNavigationState, TabNavigationState,
BottomTabNavigationOptions, BottomTabNavigationOptions,
BottomTabNavigationEventMap BottomTabNavigationEventMap
> & { > &
/** TabActionHelpers<ParamList>;
* Jump to an existing tab.
*
* @param name Name of the route for the tab.
* @param [params] Params object for the route.
*/
jumpTo<RouteName extends Extract<keyof ParamList, string>>(
...args: ParamList[RouteName] extends undefined | any
? [RouteName] | [RouteName, ParamList[RouteName]]
: [RouteName, ParamList[RouteName]]
): void;
};
export type BottomTabNavigationOptions = { export type BottomTabNavigationOptions = {
/** /**
@@ -184,6 +174,16 @@ export type BottomTabBarOptions = {
* Whether the label position should adapt to the orientation. * Whether the label position should adapt to the orientation.
*/ */
adaptive?: boolean; adaptive?: boolean;
/**
* Safe area insets for the tab bar. This is used to avoid elements like the navigation bar on Android and bottom safe area on iOS.
* By default, the device's safe area insets are automatically detected. You can override the behavior with this option.
*/
safeAreaInsets?: {
top?: number;
right?: number;
bottom?: number;
left?: number;
};
/** /**
* Style object for the tab bar container. * Style object for the tab bar container.
*/ */

View File

@@ -15,7 +15,7 @@ import {
CommonActions, CommonActions,
useTheme, useTheme,
} from '@react-navigation/native'; } from '@react-navigation/native';
import { SafeAreaConsumer } from 'react-native-safe-area-context'; import { useSafeArea } from 'react-native-safe-area-context';
import BottomTabItem from './BottomTabItem'; import BottomTabItem from './BottomTabItem';
import { BottomTabBarProps } from '../types'; import { BottomTabBarProps } from '../types';
@@ -43,6 +43,7 @@ export default function BottomTabBar({
keyboardHidesTabBar = false, keyboardHidesTabBar = false,
labelPosition, labelPosition,
labelStyle, labelStyle,
safeAreaInsets,
showIcon, showIcon,
showLabel, showLabel,
style, style,
@@ -50,7 +51,12 @@ export default function BottomTabBar({
}: Props) { }: Props) {
const { colors } = useTheme(); const { colors } = useTheme();
const [dimensions, setDimensions] = React.useState(Dimensions.get('window')); const [dimensions, setDimensions] = React.useState(() => {
const { height = 0, width = 0 } = Dimensions.get('window');
return { height, width };
});
const [layout, setLayout] = React.useState({ const [layout, setLayout] = React.useState({
height: 0, height: 0,
width: dimensions.width, width: dimensions.width,
@@ -158,116 +164,122 @@ export default function BottomTabBar({
} }
}; };
const defaultInsets = useSafeArea();
const insets = {
top: safeAreaInsets?.top ?? defaultInsets.top,
right: safeAreaInsets?.right ?? defaultInsets.right,
bottom: safeAreaInsets?.bottom ?? defaultInsets.bottom,
left: safeAreaInsets?.left ?? defaultInsets.left,
};
return ( return (
<SafeAreaConsumer> <Animated.View
{insets => ( style={[
<Animated.View styles.tabBar,
style={[ {
styles.tabBar, backgroundColor: colors.card,
{ borderTopColor: colors.border,
backgroundColor: colors.card, },
borderTopColor: colors.border, keyboardHidesTabBar
}, ? {
keyboardHidesTabBar // When the keyboard is shown, slide down the tab bar
? { transform: [
// When the keyboard is shown, slide down the tab bar {
transform: [ translateY: visible.interpolate({
{ inputRange: [0, 1],
translateY: visible.interpolate({ outputRange: [layout.height, 0],
inputRange: [0, 1], }),
outputRange: [layout.height, 0], },
}), ],
}, // Absolutely position the tab bar so that the content is below it
], // This is needed to avoid gap at bottom when the tab bar is hidden
// Absolutely position the tab bar so that the content is below it position: keyboardShown ? 'absolute' : null,
// This is needed to avoid gap at bottom when the tab bar is hidden }
position: keyboardShown ? 'absolute' : null, : null,
} {
: null, height: DEFAULT_TABBAR_HEIGHT + insets.bottom,
{ paddingBottom: insets.bottom,
height: DEFAULT_TABBAR_HEIGHT + (insets ? insets.bottom : 0), paddingHorizontal: Math.max(insets.left, insets.right),
paddingBottom: insets ? insets.bottom : 0, },
}, style,
style, ]}
]} pointerEvents={keyboardHidesTabBar && keyboardShown ? 'none' : 'auto'}
pointerEvents={keyboardHidesTabBar && keyboardShown ? 'none' : 'auto'} >
> <View style={styles.content} onLayout={handleLayout}>
<View style={styles.content} onLayout={handleLayout}> {routes.map((route, index) => {
{routes.map((route, index) => { const focused = index === state.index;
const focused = index === state.index; const { options } = descriptors[route.key];
const { options } = descriptors[route.key];
const onPress = () => { const onPress = () => {
const event = navigation.emit({ const event = navigation.emit({
type: 'tabPress', type: 'tabPress',
target: route.key, target: route.key,
canPreventDefault: true, canPreventDefault: true,
}); });
if (!focused && !event.defaultPrevented) { if (!focused && !event.defaultPrevented) {
navigation.dispatch({ navigation.dispatch({
...CommonActions.navigate(route.name), ...CommonActions.navigate(route.name),
target: state.key, target: state.key,
}); });
} }
}; };
const onLongPress = () => { const onLongPress = () => {
navigation.emit({ navigation.emit({
type: 'tabLongPress', type: 'tabLongPress',
target: route.key, target: route.key,
}); });
}; };
const label = const label =
options.tabBarLabel !== undefined options.tabBarLabel !== undefined
? options.tabBarLabel ? options.tabBarLabel
: options.title !== undefined : options.title !== undefined
? options.title ? options.title
: route.name; : route.name;
const accessibilityLabel = const accessibilityLabel =
options.tabBarAccessibilityLabel !== undefined options.tabBarAccessibilityLabel !== undefined
? options.tabBarAccessibilityLabel ? options.tabBarAccessibilityLabel
: typeof label === 'string' : typeof label === 'string'
? `${label}, tab, ${index + 1} of ${routes.length}` ? `${label}, tab, ${index + 1} of ${routes.length}`
: undefined; : undefined;
return ( return (
<NavigationContext.Provider <NavigationContext.Provider
key={route.key} key={route.key}
value={descriptors[route.key].navigation} value={descriptors[route.key].navigation}
> >
<NavigationRouteContext.Provider value={route}> <NavigationRouteContext.Provider value={route}>
<BottomTabItem <BottomTabItem
route={route} route={route}
focused={focused} focused={focused}
horizontal={shouldUseHorizontalLabels()} horizontal={shouldUseHorizontalLabels()}
onPress={onPress} onPress={onPress}
onLongPress={onLongPress} onLongPress={onLongPress}
accessibilityLabel={accessibilityLabel} accessibilityLabel={accessibilityLabel}
testID={options.tabBarTestID} testID={options.tabBarTestID}
allowFontScaling={allowFontScaling} allowFontScaling={allowFontScaling}
activeTintColor={activeTintColor} activeTintColor={activeTintColor}
inactiveTintColor={inactiveTintColor} inactiveTintColor={inactiveTintColor}
activeBackgroundColor={activeBackgroundColor} activeBackgroundColor={activeBackgroundColor}
inactiveBackgroundColor={inactiveBackgroundColor} inactiveBackgroundColor={inactiveBackgroundColor}
button={options.tabBarButton} button={options.tabBarButton}
icon={options.tabBarIcon} icon={options.tabBarIcon}
label={label} label={label}
showIcon={showIcon} showIcon={showIcon}
showLabel={showLabel} showLabel={showLabel}
labelStyle={labelStyle} labelStyle={labelStyle}
style={tabStyle} style={tabStyle}
/> />
</NavigationRouteContext.Provider> </NavigationRouteContext.Provider>
</NavigationContext.Provider> </NavigationContext.Provider>
); );
})} })}
</View> </View>
</Animated.View> </Animated.View>
)}
</SafeAreaConsumer>
); );
} }

View File

@@ -1,6 +1,5 @@
import * as React from 'react'; import * as React from 'react';
import { Platform, StyleSheet, View } from 'react-native'; import { Platform, StyleSheet, View } from 'react-native';
// eslint-disable-next-line import/no-unresolved // eslint-disable-next-line import/no-unresolved
import { Screen, screensEnabled } from 'react-native-screens'; import { Screen, screensEnabled } from 'react-native-screens';
@@ -10,12 +9,14 @@ type Props = {
style?: any; style?: any;
}; };
const FAR_FAR_AWAY = 3000; // this should be big enough to move the whole view out of its container const FAR_FAR_AWAY = 30000; // this should be big enough to move the whole view out of its container
export default class ResourceSavingScene extends React.Component<Props> { export default class ResourceSavingScene extends React.Component<Props> {
render() { render() {
if (screensEnabled?.()) { // react-native-screens is buggy on web
if (screensEnabled?.() && Platform.OS !== 'web') {
const { isVisible, ...rest } = this.props; const { isVisible, ...rest } = this.props;
// @ts-ignore // @ts-ignore
return <Screen active={isVisible ? 1 : 0} {...rest} />; return <Screen active={isVisible ? 1 : 0} {...rest} />;
} }
@@ -24,7 +25,13 @@ export default class ResourceSavingScene extends React.Component<Props> {
return ( return (
<View <View
style={[styles.container, style, { opacity: isVisible ? 1 : 0 }]} style={[
styles.container,
Platform.OS === 'web'
? { display: isVisible ? 'flex' : 'none' }
: null,
style,
]}
collapsable={false} collapsable={false}
removeClippedSubviews={ removeClippedSubviews={
// On iOS, set removeClippedSubviews to true only when not focused // On iOS, set removeClippedSubviews to true only when not focused

View File

@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [5.1.4](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.3...@react-navigation/compat@5.1.4) (2020-03-19)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.3](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.2...@react-navigation/compat@5.1.3) (2020-03-17)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.2](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.1...@react-navigation/compat@5.1.2) (2020-03-16)
**Note:** Version bump only for package @react-navigation/compat
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.0...@react-navigation/compat@5.1.1) (2020-03-03)
**Note:** Version bump only for package @react-navigation/compat
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.0.7...@react-navigation/compat@5.1.0) (2020-02-26) # [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.0.7...@react-navigation/compat@5.1.0) (2020-02-26)

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/compat", "name": "@react-navigation/compat",
"description": "Compatibility layer to write navigator definitions in static configuration format", "description": "Compatibility layer to write navigator definitions in static configuration format",
"version": "5.1.0", "version": "5.1.4",
"license": "MIT", "license": "MIT",
"repository": "https://github.com/react-navigation/react-navigation/tree/master/packages/compat", "repository": "https://github.com/react-navigation/react-navigation/tree/master/packages/compat",
"bugs": { "bugs": {
@@ -25,9 +25,9 @@
"clean": "del lib" "clean": "del lib"
}, },
"devDependencies": { "devDependencies": {
"@react-native-community/bob": "^0.9.3", "@react-native-community/bob": "^0.10.0",
"@react-navigation/native": "^5.0.8", "@react-navigation/native": "^5.1.1",
"@types/react": "^16.9.19", "@types/react": "^16.9.23",
"react": "~16.9.0", "react": "~16.9.0",
"typescript": "^3.7.5" "typescript": "^3.7.5"
}, },

View File

@@ -3,6 +3,34 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [5.2.3](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.2.2...@react-navigation/core@5.2.3) (2020-03-19)
**Note:** Version bump only for package @react-navigation/core
## [5.2.2](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.2.1...@react-navigation/core@5.2.2) (2020-03-16)
**Note:** Version bump only for package @react-navigation/core
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.2.0...@react-navigation/core@5.2.1) (2020-03-03)
### Bug Fixes
* fix links for documentation ([5bb0f40](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/5bb0f405ceb5755d39a0b5b1f2e4ecee0da051bc))
* move updating state to useEffect ([2dfa4f3](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/2dfa4f36293a2acb718814f6b2fa79d7c7ddf09c))
# [5.2.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.1.6...@react-navigation/core@5.2.0) (2020-02-26) # [5.2.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.1.6...@react-navigation/core@5.2.0) (2020-02-26)

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/core", "name": "@react-navigation/core",
"description": "Core utilities for building navigators", "description": "Core utilities for building navigators",
"version": "5.2.0", "version": "5.2.3",
"keywords": [ "keywords": [
"react", "react",
"react-native", "react-native",
@@ -29,23 +29,23 @@
"clean": "del lib" "clean": "del lib"
}, },
"dependencies": { "dependencies": {
"@react-navigation/routers": "^5.0.3", "@react-navigation/routers": "^5.1.1",
"escape-string-regexp": "^2.0.0", "escape-string-regexp": "^2.0.0",
"query-string": "^6.10.1", "query-string": "^6.11.1",
"react-is": "^16.12.0", "react-is": "^16.13.0",
"shortid": "^2.2.15", "shortid": "^2.2.15",
"use-subscription": "^1.3.0" "use-subscription": "^1.4.0"
}, },
"devDependencies": { "devDependencies": {
"@react-native-community/bob": "^0.9.3", "@react-native-community/bob": "^0.10.0",
"@types/react": "^16.9.19", "@types/react": "^16.9.23",
"@types/react-is": "^16.7.1", "@types/react-is": "^16.7.1",
"@types/shortid": "^0.0.29", "@types/shortid": "^0.0.29",
"@types/use-subscription": "^1.0.0", "@types/use-subscription": "^1.0.0",
"del-cli": "^3.0.0", "del-cli": "^3.0.0",
"react": "~16.9.0", "react": "~16.9.0",
"react-native-testing-library": "^1.12.0", "react-native-testing-library": "^1.12.0",
"react-test-renderer": "~16.12.0", "react-test-renderer": "~16.9.0",
"typescript": "^3.7.5" "typescript": "^3.7.5"
}, },
"peerDependencies": { "peerDependencies": {

View File

@@ -21,10 +21,10 @@ import useSyncState from './useSyncState';
type State = NavigationState | PartialState<NavigationState> | undefined; type State = NavigationState | PartialState<NavigationState> | undefined;
const MISSING_CONTEXT_ERROR = const MISSING_CONTEXT_ERROR =
"Couldn't find a navigation context. Have you wrapped your app with 'NavigationContainer'? See https://reactnavigation.org/docs/getting-started.html for setup instructions."; "Couldn't find a navigation context. Have you wrapped your app with 'NavigationContainer'? See https://reactnavigation.org/docs/getting-started for setup instructions.";
const NOT_INITIALIZED_ERROR = const NOT_INITIALIZED_ERROR =
"The 'navigation' object hasn't been initialized yet. This might happen if you don't have a navigator mounted, or if the navigator hasn't finished mounting. See https://reactnavigation.org/docs/navigating-without-navigation-prop.html#handling-initialization for more details."; "The 'navigation' object hasn't been initialized yet. This might happen if you don't have a navigator mounted, or if the navigator hasn't finished mounting. See https://reactnavigation.org/docs/navigating-without-navigation-prop#handling-initialization for more details.";
export const NavigationStateContext = React.createContext<{ export const NavigationStateContext = React.createContext<{
isDefault?: true; isDefault?: true;
@@ -136,6 +136,7 @@ const BaseNavigationContainer = React.forwardRef(
); );
const { trackState, trackAction } = useDevTools({ const { trackState, trackAction } = useDevTools({
enabled: false,
name: '@react-navigation', name: '@react-navigation',
reset, reset,
state, state,
@@ -238,7 +239,7 @@ const BaseNavigationContainer = React.forwardRef(
hasWarnedForSerialization = true; hasWarnedForSerialization = true;
console.warn( console.warn(
"Non-serializable values were found in the navigation state, which can break usage such as persisting and restoring state. This might happen if you passed non-serializable values such as function, class instances etc. in params. If you need to use components with callbacks in your options, you can use 'navigation.setOptions' instead. See https://reactnavigation.org/docs/troubleshooting.html#i-get-the-warning-we-found-non-serializable-values-in-the-navigation-state for more details." "Non-serializable values were found in the navigation state, which can break usage such as persisting and restoring state. This might happen if you passed non-serializable values such as function, class instances etc. in params. If you need to use components with callbacks in your options, you can use 'navigation.setOptions' instead. See https://reactnavigation.org/docs/troubleshooting#i-get-the-warning-non-serializable-values-were-found-in-the-navigation-state for more details."
); );
} }
} }

View File

@@ -4,7 +4,7 @@ type Props = {
children: React.ReactNode; children: React.ReactNode;
}; };
const MULTIPLE_NAVIGATOR_ERROR = `Another navigator is already registered for this container. You likely have multiple navigators under a single "NavigationContainer" or "Screen". Make sure each navigator is under a separate "Screen" container. See https://reactnavigation.org/docs/nesting-navigators.html for a guide on nesting.`; const MULTIPLE_NAVIGATOR_ERROR = `Another navigator is already registered for this container. You likely have multiple navigators under a single "NavigationContainer" or "Screen". Make sure each navigator is under a separate "Screen" container. See https://reactnavigation.org/docs/nesting-navigators for a guide on nesting.`;
export const SingleNavigatorContext = React.createContext< export const SingleNavigatorContext = React.createContext<
| { | {

View File

@@ -25,7 +25,7 @@ export default function createNavigatorFactory<
> { > {
if (arguments[0] !== undefined) { if (arguments[0] !== undefined) {
throw new Error( throw new Error(
"Creating a navigator doesn't take an argument. Maybe you are trying to use React Navigation 4 API with React Navigation 5? See https://reactnavigation.org/docs/upgrading-from-4.x.html for migration guide." "Creating a navigator doesn't take an argument. Maybe you are trying to use React Navigation 4 API with React Navigation 5? See https://reactnavigation.org/docs/upgrading-from-4.x for migration guide."
); );
} }

View File

@@ -168,18 +168,6 @@ type NavigationHelpersCommon<
| { name: RouteName; key?: string; params: ParamList[RouteName] } | { name: RouteName; key?: string; params: ParamList[RouteName] }
): void; ): void;
/**
* Replace the current route with a new one.
*
* @param name Route name of the new route.
* @param [params] Params object for the new route.
*/
replace<RouteName extends keyof ParamList>(
...args: ParamList[RouteName] extends undefined
? [RouteName] | [RouteName, ParamList[RouteName]]
: [RouteName, ParamList[RouteName]]
): void;
/** /**
* Reset the navigation state to the provided state. * Reset the navigation state to the provided state.
* *

View File

@@ -8,6 +8,7 @@ import {
type State = NavigationState | PartialState<NavigationState> | undefined; type State = NavigationState | PartialState<NavigationState> | undefined;
type Options = { type Options = {
enabled: boolean;
name: string; name: string;
reset: (state: NavigationState) => void; reset: (state: NavigationState) => void;
state: State; state: State;
@@ -35,10 +36,11 @@ declare global {
} }
} }
export default function useDevTools({ name, reset, state }: Options) { export default function useDevTools({ name, reset, state, enabled }: Options) {
const devToolsRef = React.useRef<DevTools>(); const devToolsRef = React.useRef<DevTools>();
if ( if (
enabled &&
process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'production' &&
global.__REDUX_DEVTOOLS_EXTENSION__ && global.__REDUX_DEVTOOLS_EXTENSION__ &&
devToolsRef.current === undefined devToolsRef.current === undefined

View File

@@ -46,7 +46,7 @@ export default function useFocusEffect(effect: EffectCallback) {
' fetchData();\n' + ' fetchData();\n' +
' }, [someId])\n' + ' }, [someId])\n' +
'};\n\n' + '};\n\n' +
'See usage guide: https://reactnavigation.org/docs/use-focus-effect.html'; 'See usage guide: https://reactnavigation.org/docs/use-focus-effect';
} else { } else {
message += ` You returned: '${JSON.stringify(destroy)}'`; message += ` You returned: '${JSON.stringify(destroy)}'`;
} }

View File

@@ -333,12 +333,14 @@ export default function useNavigationBuilder<
: state; : state;
} }
if (state !== nextState) { const shouldUpdate = state !== nextState;
// If the state needs to be updated, we'll schedule an update with React
// setState in render seems hacky, but that's how React docs implement getDerivedPropsFromState React.useEffect(() => {
// https://reactjs.org/docs/hooks-faq.html#how-do-i-implement-getderivedstatefromprops if (shouldUpdate) {
setState(nextState); // If the state needs to be updated, we'll schedule an update with React
} setState(nextState);
}
}, [nextState, setState, shouldUpdate]);
// The up-to-date state will come in next render, but we don't need to wait for it // The up-to-date state will come in next render, but we don't need to wait for it
// We can't use the outdated state since the screens have changed, which will cause error due to mismatched config // We can't use the outdated state since the screens have changed, which will cause error due to mismatched config

View File

@@ -54,9 +54,9 @@ export default function useNavigationHelpers<
case 'REPLACE': case 'REPLACE':
case 'JUMP_TO': case 'JUMP_TO':
if (payload?.name) { if (payload?.name) {
message += `\n\nDo you have a screen named '${payload.name}'?\n\nIf you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators.html#navigating-to-a-screen-in-a-nested-navigator.`; message += `\n\nDo you have a screen named '${payload.name}'?\n\nIf you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator.`;
} else { } else {
message += `\n\nYou need to pass the name of the screen to navigate to.\n\nSee https://reactnavigation.org/docs/navigation-actions.html for usage.`; message += `\n\nYou need to pass the name of the screen to navigate to.\n\nSee https://reactnavigation.org/docs/navigation-actions for usage.`;
} }
break; break;

View File

@@ -3,6 +3,58 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [5.3.2](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.3.1...@react-navigation/drawer@5.3.2) (2020-03-19)
### Bug Fixes
* close drawer on pressing Esc on web ([5c4afc5](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/5c4afc5cb40c1206a9d8c40efe3cf947030da48e)), closes [#6745](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/6745)
* don't use react-native-screens on web ([b1a65fc](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/b1a65fc73e8603ae2c06ef101a74df31e80bb9b2)), closes [#7485](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/7485)
* fix permanent sidebar position ([#7830](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/7830)) ([3ea8eec](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/3ea8eec4324ea82f0ed427f4662e68e1115e60ab))
* initialize height and width to zero if undefined ([3df65e2](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/3df65e28197db3bb8371059146546d57661c5ba3)), closes [#6789](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/6789)
## [5.3.1](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.3.0...@react-navigation/drawer@5.3.1) (2020-03-17)
**Note:** Version bump only for package @react-navigation/drawer
# [5.3.0](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.2.0...@react-navigation/drawer@5.3.0) (2020-03-17)
### Features
* add permanent drawer type ([#7818](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/7818)) ([6a5d0a0](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/6a5d0a035afae60d91aef78401ec8826295746fe))
# [5.2.0](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.1.1...@react-navigation/drawer@5.2.0) (2020-03-16)
### Features
* make useIsDrawerOpen workable inside drawer content ([#7746](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/7746)) ([cb46d0b](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/cb46d0bca4e17e847fff46ac94276213ac9697bf))
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.1.0...@react-navigation/drawer@5.1.1) (2020-03-03)
**Note:** Version bump only for package @react-navigation/drawer
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.0.7...@react-navigation/drawer@5.1.0) (2020-02-26) # [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.0.7...@react-navigation/drawer@5.1.0) (2020-02-26)

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/drawer", "name": "@react-navigation/drawer",
"description": "Drawer navigator component with animated transitions and gesturess", "description": "Drawer navigator component with animated transitions and gesturess",
"version": "5.1.0", "version": "5.3.2",
"keywords": [ "keywords": [
"react-native-component", "react-native-component",
"react-component", "react-component",
@@ -39,17 +39,17 @@
"react-native-iphone-x-helper": "^1.2.1" "react-native-iphone-x-helper": "^1.2.1"
}, },
"devDependencies": { "devDependencies": {
"@react-native-community/bob": "^0.9.3", "@react-native-community/bob": "^0.10.0",
"@react-navigation/native": "^5.0.8", "@react-navigation/native": "^5.1.1",
"@types/react": "^16.9.19", "@types/react": "^16.9.23",
"@types/react-native": "^0.60.30", "@types/react-native": "^0.61.22",
"del-cli": "^3.0.0", "del-cli": "^3.0.0",
"react": "~16.9.0", "react": "~16.9.0",
"react-native": "~0.61.5", "react-native": "~0.61.5",
"react-native-gesture-handler": "^1.5.6", "react-native-gesture-handler": "^1.6.0",
"react-native-reanimated": "^1.7.0", "react-native-reanimated": "^1.7.0",
"react-native-safe-area-context": "^0.7.2", "react-native-safe-area-context": "^0.7.3",
"react-native-screens": "^2.0.0-beta.2", "react-native-screens": "^2.3.0",
"typescript": "^3.7.5" "typescript": "^3.7.5"
}, },
"peerDependencies": { "peerDependencies": {
@@ -59,7 +59,7 @@
"react-native-gesture-handler": ">= 1.0.0", "react-native-gesture-handler": ">= 1.0.0",
"react-native-reanimated": ">= 1.0.0", "react-native-reanimated": ">= 1.0.0",
"react-native-safe-area-context": ">= 0.6.0", "react-native-safe-area-context": ">= 0.6.0",
"react-native-screens": ">= 2.0.0-alpha.0 || >= 2.0.0-beta.0" "react-native-screens": ">= 2.0.0-alpha.0 || >= 2.0.0-beta.0 || >= 2.0.0"
}, },
"@react-native-community/bob": { "@react-native-community/bob": {
"source": "src", "source": "src",

View File

@@ -7,6 +7,7 @@ import {
Descriptor, Descriptor,
NavigationHelpers, NavigationHelpers,
DrawerNavigationState, DrawerNavigationState,
DrawerActionHelpers,
} from '@react-navigation/native'; } from '@react-navigation/native';
import { PanGestureHandler } from 'react-native-gesture-handler'; import { PanGestureHandler } from 'react-native-gesture-handler';
@@ -26,8 +27,9 @@ export type DrawerNavigationConfig<T = DrawerContentOptions> = {
* - `front`: Traditional drawer which covers the screen with a overlay behind it. * - `front`: Traditional drawer which covers the screen with a overlay behind it.
* - `back`: The drawer is revealed behind the screen on swipe. * - `back`: The drawer is revealed behind the screen on swipe.
* - `slide`: Both the screen and the drawer slide on swipe to reveal the drawer. * - `slide`: Both the screen and the drawer slide on swipe to reveal the drawer.
* - `permanent`: A permanent drawer is shown as a sidebar.
*/ */
drawerType?: 'front' | 'back' | 'slide'; drawerType?: 'front' | 'back' | 'slide' | 'permanent';
/** /**
* How far from the edge of the screen the swipe gesture should activate. * How far from the edge of the screen the swipe gesture should activate.
*/ */
@@ -190,22 +192,8 @@ export type DrawerNavigationProp<
DrawerNavigationState, DrawerNavigationState,
DrawerNavigationOptions, DrawerNavigationOptions,
DrawerNavigationEventMap DrawerNavigationEventMap
> & { > &
/** DrawerActionHelpers<ParamList>;
* Open the drawer sidebar.
*/
openDrawer(): void;
/**
* Close the drawer sidebar.
*/
closeDrawer(): void;
/**
* Open the drawer sidebar if closed, or close if opened.
*/
toggleDrawer(): void;
};
export type DrawerDescriptor = Descriptor< export type DrawerDescriptor = Descriptor<
ParamListBase, ParamListBase,

View File

@@ -0,0 +1,5 @@
import * as React from 'react';
const DrawerOpenContext = React.createContext<boolean | null>(null);
export default DrawerOpenContext;

View File

@@ -1,38 +1,17 @@
import * as React from 'react'; import * as React from 'react';
import { useNavigation, ParamListBase } from '@react-navigation/native'; import DrawerOpenContext from './DrawerOpenContext';
import { DrawerNavigationProp } from '../types';
/** /**
* Hook to detect if the drawer is open in a parent navigator. * Hook to detect if the drawer is open in a parent navigator.
*/ */
export default function useIsDrawerOpen() { export default function useIsDrawerOpen() {
const navigation = useNavigation(); const isDrawerOpen = React.useContext(DrawerOpenContext);
let drawer = navigation as DrawerNavigationProp<ParamListBase>; if (typeof isDrawerOpen !== 'boolean') {
throw new Error(
// The screen might be inside another navigator such as stack nested in drawer "Couldn't find a drawer. Is your component inside a drawer navigator?"
// We need to find the closest drawer navigator and add the listener there );
while (drawer && drawer.dangerouslyGetState().type !== 'drawer') {
drawer = drawer.dangerouslyGetParent();
} }
const [isDrawerOpen, setIsDrawerOpen] = React.useState(() =>
drawer
? Boolean(
drawer.dangerouslyGetState().history.find(it => it.type === 'drawer')
)
: false
);
React.useEffect(() => {
const unsubscribe = drawer.addListener('state', e => {
setIsDrawerOpen(
Boolean(e.data.state.history.find(it => it.type === 'drawer'))
);
});
return unsubscribe;
}, [drawer, isDrawerOpen]);
return isDrawerOpen; return isDrawerOpen;
} }

View File

@@ -68,6 +68,8 @@ const SPRING_CONFIG = {
restSpeedThreshold: 0.01, restSpeedThreshold: 0.01,
}; };
const ANIMATED_ONE = new Animated.Value(1);
type Binary = 0 | 1; type Binary = 0 | 1;
type Renderer = (props: { progress: Animated.Node<number> }) => React.ReactNode; type Renderer = (props: { progress: Animated.Node<number> }) => React.ReactNode;
@@ -79,7 +81,7 @@ type Props = {
onGestureRef?: (ref: PanGestureHandler | null) => void; onGestureRef?: (ref: PanGestureHandler | null) => void;
gestureEnabled: boolean; gestureEnabled: boolean;
drawerPosition: 'left' | 'right'; drawerPosition: 'left' | 'right';
drawerType: 'front' | 'back' | 'slide'; drawerType: 'front' | 'back' | 'slide' | 'permanent';
keyboardDismissMode: 'none' | 'on-drag'; keyboardDismissMode: 'none' | 'on-drag';
swipeEdgeWidth: number; swipeEdgeWidth: number;
swipeDistanceThreshold?: number; swipeDistanceThreshold?: number;
@@ -125,6 +127,12 @@ export default class DrawerView extends React.PureComponent<Props> {
statusBarAnimation: 'slide', statusBarAnimation: 'slide',
}; };
componentDidMount() {
if (Platform.OS === 'web') {
document?.body?.addEventListener?.('keyup', this.handleEscape);
}
}
componentDidUpdate(prevProps: Props) { componentDidUpdate(prevProps: Props) {
const { const {
open, open,
@@ -180,8 +188,22 @@ export default class DrawerView extends React.PureComponent<Props> {
componentWillUnmount() { componentWillUnmount() {
this.toggleStatusBar(false); this.toggleStatusBar(false);
this.handleEndInteraction(); this.handleEndInteraction();
if (Platform.OS === 'web') {
document?.body?.removeEventListener?.('keyup', this.handleEscape);
}
} }
private handleEscape = (e: KeyboardEvent) => {
const { open, onClose } = this.props;
if (e.key === 'Escape') {
if (open) {
onClose();
}
}
};
private handleEndInteraction = () => { private handleEndInteraction = () => {
if (this.interactionHandle !== undefined) { if (this.interactionHandle !== undefined) {
InteractionManager.clearInteractionHandle(this.interactionHandle); InteractionManager.clearInteractionHandle(this.interactionHandle);
@@ -544,6 +566,7 @@ export default class DrawerView extends React.PureComponent<Props> {
gestureHandlerProps, gestureHandlerProps,
} = this.props; } = this.props;
const isOpen = drawerType === 'permanent' ? true : open;
const isRight = drawerPosition === 'right'; const isRight = drawerPosition === 'right';
const contentTranslateX = drawerType === 'front' ? 0 : this.translateX; const contentTranslateX = drawerType === 'front' ? 0 : this.translateX;
@@ -569,8 +592,10 @@ export default class DrawerView extends React.PureComponent<Props> {
const hitSlop = isRight const hitSlop = isRight
? // Extend hitSlop to the side of the screen when drawer is closed ? // Extend hitSlop to the side of the screen when drawer is closed
// This lets the user drag the drawer from the side of the screen // This lets the user drag the drawer from the side of the screen
{ right: 0, width: open ? undefined : swipeEdgeWidth } { right: 0, width: isOpen ? undefined : swipeEdgeWidth }
: { left: 0, width: open ? undefined : swipeEdgeWidth }; : { left: 0, width: isOpen ? undefined : swipeEdgeWidth };
const progress = drawerType === 'permanent' ? ANIMATED_ONE : this.progress;
return ( return (
<PanGestureHandler <PanGestureHandler
@@ -580,62 +605,83 @@ export default class DrawerView extends React.PureComponent<Props> {
onGestureEvent={this.handleGestureEvent} onGestureEvent={this.handleGestureEvent}
onHandlerStateChange={this.handleGestureStateChange} onHandlerStateChange={this.handleGestureStateChange}
hitSlop={hitSlop} hitSlop={hitSlop}
enabled={gestureEnabled} enabled={drawerType !== 'permanent' && gestureEnabled}
{...gestureHandlerProps} {...gestureHandlerProps}
> >
<Animated.View <Animated.View
onLayout={this.handleContainerLayout} onLayout={this.handleContainerLayout}
style={styles.main} style={[
styles.main,
{
flexDirection:
drawerType === 'permanent' && !isRight ? 'row-reverse' : 'row',
},
]}
> >
<Animated.View <Animated.View
style={[ style={[
styles.content, styles.content,
{ drawerType !== 'permanent' && {
transform: [{ translateX: contentTranslateX }], transform: [{ translateX: contentTranslateX }],
}, },
sceneContainerStyle as any, sceneContainerStyle as any,
]} ]}
> >
<View <View
accessibilityElementsHidden={open} accessibilityElementsHidden={isOpen}
importantForAccessibility={open ? 'no-hide-descendants' : 'auto'} importantForAccessibility={
isOpen ? 'no-hide-descendants' : 'auto'
}
style={styles.content} style={styles.content}
> >
{renderSceneContent({ progress: this.progress })} {renderSceneContent({ progress })}
</View> </View>
<TapGestureHandler {// Disable overlay if sidebar is permanent
enabled={gestureEnabled} drawerType === 'permanent' ? null : (
onHandlerStateChange={this.handleTapStateChange} <TapGestureHandler
> enabled={gestureEnabled}
<Overlay progress={this.progress} style={overlayStyle} /> onHandlerStateChange={this.handleTapStateChange}
</TapGestureHandler> >
<Overlay progress={progress} style={overlayStyle} />
</TapGestureHandler>
)}
</Animated.View> </Animated.View>
<Animated.Code {drawerType === 'permanent' ? null : (
exec={block([ <Animated.Code
onChange(this.manuallyTriggerSpring, [ exec={block([
cond(eq(this.manuallyTriggerSpring, TRUE), [ onChange(this.manuallyTriggerSpring, [
set(this.nextIsOpen, FALSE), cond(eq(this.manuallyTriggerSpring, TRUE), [
call([], () => (this.currentOpenValue = false)), set(this.nextIsOpen, FALSE),
call([], () => (this.currentOpenValue = false)),
]),
]), ]),
]), ])}
])} />
/> )}
<Animated.View <Animated.View
accessibilityViewIsModal={open} accessibilityViewIsModal={isOpen}
removeClippedSubviews={Platform.OS !== 'ios'} removeClippedSubviews={Platform.OS !== 'ios'}
onLayout={this.handleDrawerLayout} onLayout={this.handleDrawerLayout}
style={[ style={[
styles.container, styles.container,
isRight ? { right: offset } : { left: offset }, drawerType === 'permanent'
{ ? // Without this, the `left`/`right` values don't get reset
transform: [{ translateX: drawerTranslateX }], isRight
opacity: this.drawerOpacity, ? { right: 0 }
zIndex: drawerType === 'back' ? -1 : 0, : { left: 0 }
}, : [
styles.nonPermanent,
{
transform: [{ translateX: drawerTranslateX }],
opacity: this.drawerOpacity,
},
isRight ? { right: offset } : { left: offset },
{ zIndex: drawerType === 'back' ? -1 : 0 },
],
drawerStyle as any, drawerStyle as any,
]} ]}
> >
{renderDrawerContent({ progress: this.progress })} {renderDrawerContent({ progress })}
</Animated.View> </Animated.View>
</Animated.View> </Animated.View>
</PanGestureHandler> </PanGestureHandler>
@@ -646,11 +692,13 @@ export default class DrawerView extends React.PureComponent<Props> {
const styles = StyleSheet.create({ const styles = StyleSheet.create({
container: { container: {
backgroundColor: 'white', backgroundColor: 'white',
maxWidth: '100%',
},
nonPermanent: {
position: 'absolute', position: 'absolute',
top: 0, top: 0,
bottom: 0, bottom: 0,
width: '80%', width: '80%',
maxWidth: '100%',
}, },
content: { content: {
flex: 1, flex: 1,

View File

@@ -32,6 +32,7 @@ import {
DrawerNavigationHelpers, DrawerNavigationHelpers,
DrawerContentComponentProps, DrawerContentComponentProps,
} from '../types'; } from '../types';
import DrawerOpenContext from '../utils/DrawerOpenContext';
import DrawerPositionContext from '../utils/DrawerPositionContext'; import DrawerPositionContext from '../utils/DrawerPositionContext';
type Props = DrawerNavigationConfig & { type Props = DrawerNavigationConfig & {
@@ -88,15 +89,17 @@ export default function DrawerView({
sceneContainerStyle, sceneContainerStyle,
}: Props) { }: Props) {
const [loaded, setLoaded] = React.useState([state.index]); const [loaded, setLoaded] = React.useState([state.index]);
const [drawerWidth, setDrawerWidth] = React.useState(() => const [drawerWidth, setDrawerWidth] = React.useState(() => {
getDefaultDrawerWidth(Dimensions.get('window')) const { height = 0, width = 0 } = Dimensions.get('window');
);
return getDefaultDrawerWidth({ height, width });
});
const drawerGestureRef = React.useRef<PanGestureHandler>(null); const drawerGestureRef = React.useRef<PanGestureHandler>(null);
const { colors } = useTheme(); const { colors } = useTheme();
const isDrawerOpen = Boolean(state.history.find(it => it.type === 'drawer')); const isDrawerOpen = state.history.some(it => it.type === 'drawer');
const handleDrawerOpen = React.useCallback(() => { const handleDrawerOpen = React.useCallback(() => {
navigation.dispatch({ navigation.dispatch({
@@ -203,36 +206,48 @@ export default function DrawerView({
<GestureHandlerWrapper style={styles.content}> <GestureHandlerWrapper style={styles.content}>
<SafeAreaProviderCompat> <SafeAreaProviderCompat>
<DrawerGestureContext.Provider value={drawerGestureRef}> <DrawerGestureContext.Provider value={drawerGestureRef}>
<Drawer <DrawerOpenContext.Provider value={isDrawerOpen}>
open={isDrawerOpen} <Drawer
gestureEnabled={gestureEnabled} open={isDrawerOpen}
onOpen={handleDrawerOpen} gestureEnabled={gestureEnabled}
onClose={handleDrawerClose} onOpen={handleDrawerOpen}
onGestureRef={ref => { onClose={handleDrawerClose}
// @ts-ignore onGestureRef={ref => {
drawerGestureRef.current = ref; // @ts-ignore
}} drawerGestureRef.current = ref;
gestureHandlerProps={gestureHandlerProps} }}
drawerType={drawerType} gestureHandlerProps={gestureHandlerProps}
drawerPosition={drawerPosition} drawerType={drawerType}
sceneContainerStyle={[ drawerPosition={drawerPosition}
{ backgroundColor: colors.background }, sceneContainerStyle={[
sceneContainerStyle, { backgroundColor: colors.background },
]} sceneContainerStyle,
drawerStyle={[ ]}
{ width: drawerWidth, backgroundColor: colors.card }, drawerStyle={[
drawerStyle, { width: drawerWidth, backgroundColor: colors.card },
]} drawerType === 'permanent' &&
overlayStyle={{ backgroundColor: overlayColor }} (drawerPosition === 'left'
swipeEdgeWidth={edgeWidth} ? {
swipeDistanceThreshold={minSwipeDistance} borderRightColor: colors.border,
hideStatusBar={hideStatusBar} borderRightWidth: StyleSheet.hairlineWidth,
statusBarAnimation={statusBarAnimation} }
renderDrawerContent={renderNavigationView} : {
renderSceneContent={renderContent} borderLeftColor: colors.border,
keyboardDismissMode={keyboardDismissMode} borderLeftWidth: StyleSheet.hairlineWidth,
drawerPostion={drawerPosition} }),
/> drawerStyle,
]}
overlayStyle={{ backgroundColor: overlayColor }}
swipeEdgeWidth={edgeWidth}
swipeDistanceThreshold={minSwipeDistance}
hideStatusBar={hideStatusBar}
statusBarAnimation={statusBarAnimation}
renderDrawerContent={renderNavigationView}
renderSceneContent={renderContent}
keyboardDismissMode={keyboardDismissMode}
drawerPostion={drawerPosition}
/>
</DrawerOpenContext.Provider>
</DrawerGestureContext.Provider> </DrawerGestureContext.Provider>
</SafeAreaProviderCompat> </SafeAreaProviderCompat>
</GestureHandlerWrapper> </GestureHandlerWrapper>

View File

@@ -9,21 +9,29 @@ type Props = {
style?: any; style?: any;
}; };
const FAR_FAR_AWAY = 3000; // this should be big enough to move the whole view out of its container const FAR_FAR_AWAY = 30000; // this should be big enough to move the whole view out of its container
export default class ResourceSavingScene extends React.Component<Props> { export default class ResourceSavingScene extends React.Component<Props> {
render() { render() {
if (screensEnabled?.()) { // react-native-screens is buggy on web
if (screensEnabled?.() && Platform.OS !== 'web') {
const { isVisible, ...rest } = this.props; const { isVisible, ...rest } = this.props;
// @ts-ignore // @ts-ignore
return <Screen active={isVisible ? 1 : 0} {...rest} />; return <Screen active={isVisible ? 1 : 0} {...rest} />;
} }
const { isVisible, children, style, ...rest } = this.props; const { isVisible, children, style, ...rest } = this.props;
return ( return (
<View <View
style={[styles.container, style]} style={[
styles.container,
Platform.OS === 'web'
? { display: isVisible ? 'flex' : 'none' }
: null,
style,
]}
collapsable={false} collapsable={false}
removeClippedSubviews={ removeClippedSubviews={
// On iOS, set removeClippedSubviews to true only when not focused // On iOS, set removeClippedSubviews to true only when not focused

View File

@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [5.1.4](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.3...@react-navigation/material-bottom-tabs@5.1.4) (2020-03-19)
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
## [5.1.3](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.2...@react-navigation/material-bottom-tabs@5.1.3) (2020-03-17)
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
## [5.1.2](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.1...@react-navigation/material-bottom-tabs@5.1.2) (2020-03-16)
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.0...@react-navigation/material-bottom-tabs@5.1.1) (2020-03-03)
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.0.7...@react-navigation/material-bottom-tabs@5.1.0) (2020-02-26) # [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.0.7...@react-navigation/material-bottom-tabs@5.1.0) (2020-02-26)

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/material-bottom-tabs", "name": "@react-navigation/material-bottom-tabs",
"description": "Integration for bottom navigation component from react-native-paper", "description": "Integration for bottom navigation component from react-native-paper",
"version": "5.1.0", "version": "5.1.4",
"keywords": [ "keywords": [
"react-native-component", "react-native-component",
"react-component", "react-component",
@@ -35,10 +35,10 @@
"clean": "del lib" "clean": "del lib"
}, },
"devDependencies": { "devDependencies": {
"@react-native-community/bob": "^0.9.3", "@react-native-community/bob": "^0.10.0",
"@react-navigation/native": "^5.0.8", "@react-navigation/native": "^5.1.1",
"@types/react": "^16.9.19", "@types/react": "^16.9.23",
"@types/react-native": "^0.60.30", "@types/react-native": "^0.61.22",
"@types/react-native-vector-icons": "^6.4.5", "@types/react-native-vector-icons": "^6.4.5",
"del-cli": "^3.0.0", "del-cli": "^3.0.0",
"react": "~16.9.0", "react": "~16.9.0",

View File

@@ -5,6 +5,7 @@ import {
NavigationProp, NavigationProp,
NavigationHelpers, NavigationHelpers,
TabNavigationState, TabNavigationState,
TabActionHelpers,
} from '@react-navigation/native'; } from '@react-navigation/native';
export type MaterialBottomTabNavigationEventMap = { export type MaterialBottomTabNavigationEventMap = {
@@ -28,19 +29,8 @@ export type MaterialBottomTabNavigationProp<
TabNavigationState, TabNavigationState,
MaterialBottomTabNavigationOptions, MaterialBottomTabNavigationOptions,
MaterialBottomTabNavigationEventMap MaterialBottomTabNavigationEventMap
> & { > &
/** TabActionHelpers<ParamList>;
* Jump to an existing tab.
*
* @param name Name of the route for the tab.
* @param [params] Params object for the route.
*/
jumpTo<RouteName extends Extract<keyof ParamList, string>>(
...args: ParamList[RouteName] extends undefined | any
? [RouteName] | [RouteName, ParamList[RouteName]]
: [RouteName, ParamList[RouteName]]
): void;
};
export type MaterialBottomTabNavigationOptions = { export type MaterialBottomTabNavigationOptions = {
/** /**

View File

@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [5.1.4](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.3...@react-navigation/material-top-tabs@5.1.4) (2020-03-19)
**Note:** Version bump only for package @react-navigation/material-top-tabs
## [5.1.3](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.2...@react-navigation/material-top-tabs@5.1.3) (2020-03-17)
**Note:** Version bump only for package @react-navigation/material-top-tabs
## [5.1.2](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.1...@react-navigation/material-top-tabs@5.1.2) (2020-03-16)
**Note:** Version bump only for package @react-navigation/material-top-tabs
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.0...@react-navigation/material-top-tabs@5.1.1) (2020-03-03)
**Note:** Version bump only for package @react-navigation/material-top-tabs
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.0.7...@react-navigation/material-top-tabs@5.1.0) (2020-02-26) # [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.0.7...@react-navigation/material-top-tabs@5.1.0) (2020-02-26)

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/material-top-tabs", "name": "@react-navigation/material-top-tabs",
"description": "Integration for the animated tab view component from react-native-tab-view", "description": "Integration for the animated tab view component from react-native-tab-view",
"version": "5.1.0", "version": "5.1.4",
"keywords": [ "keywords": [
"react-native-component", "react-native-component",
"react-component", "react-component",
@@ -38,14 +38,14 @@
"color": "^3.1.2" "color": "^3.1.2"
}, },
"devDependencies": { "devDependencies": {
"@react-native-community/bob": "^0.9.3", "@react-native-community/bob": "^0.10.0",
"@react-navigation/native": "^5.0.8", "@react-navigation/native": "^5.1.1",
"@types/react": "^16.9.19", "@types/react": "^16.9.23",
"@types/react-native": "^0.60.30", "@types/react-native": "^0.61.22",
"del-cli": "^3.0.0", "del-cli": "^3.0.0",
"react": "~16.9.0", "react": "~16.9.0",
"react-native": "~0.61.5", "react-native": "~0.61.5",
"react-native-gesture-handler": "^1.5.6", "react-native-gesture-handler": "^1.6.0",
"react-native-reanimated": "^1.7.0", "react-native-reanimated": "^1.7.0",
"react-native-tab-view": "^2.13.0", "react-native-tab-view": "^2.13.0",
"typescript": "^3.7.5" "typescript": "^3.7.5"

View File

@@ -7,6 +7,7 @@ import {
Route, Route,
NavigationProp, NavigationProp,
TabNavigationState, TabNavigationState,
TabActionHelpers,
} from '@react-navigation/native'; } from '@react-navigation/native';
export type MaterialTopTabNavigationEventMap = { export type MaterialTopTabNavigationEventMap = {
@@ -42,19 +43,8 @@ export type MaterialTopTabNavigationProp<
TabNavigationState, TabNavigationState,
MaterialTopTabNavigationOptions, MaterialTopTabNavigationOptions,
MaterialTopTabNavigationEventMap MaterialTopTabNavigationEventMap
> & { > &
/** TabActionHelpers<ParamList>;
* Jump to an existing tab.
*
* @param name Name of the route for the tab.
* @param [params] Params object for the route.
*/
jumpTo<RouteName extends Extract<keyof ParamList, string>>(
...args: ParamList[RouteName] extends undefined | any
? [RouteName] | [RouteName, ParamList[RouteName]]
: [RouteName, ParamList[RouteName]]
): void;
};
export type MaterialTopTabNavigationOptions = { export type MaterialTopTabNavigationOptions = {
/** /**

View File

@@ -3,6 +3,41 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.1.0...@react-navigation/native@5.1.1) (2020-03-19)
**Note:** Version bump only for package @react-navigation/native
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.0.10...@react-navigation/native@5.1.0) (2020-03-17)
### Features
* add permanent drawer type ([#7818](https://github.com/react-navigation/react-navigation/tree/master/packages/native/issues/7818)) ([6a5d0a0](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/6a5d0a035afae60d91aef78401ec8826295746fe))
## [5.0.10](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.0.9...@react-navigation/native@5.0.10) (2020-03-16)
**Note:** Version bump only for package @react-navigation/native
## [5.0.9](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.0.8...@react-navigation/native@5.0.9) (2020-03-03)
**Note:** Version bump only for package @react-navigation/native
## [5.0.8](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.0.7...@react-navigation/native@5.0.8) (2020-02-26) ## [5.0.8](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.0.7...@react-navigation/native@5.0.8) (2020-02-26)
**Note:** Version bump only for package @react-navigation/native **Note:** Version bump only for package @react-navigation/native

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/native", "name": "@react-navigation/native",
"description": "React Native integration for React Navigation", "description": "React Native integration for React Navigation",
"version": "5.0.8", "version": "5.1.1",
"keywords": [ "keywords": [
"react-native", "react-native",
"react-navigation", "react-navigation",
@@ -31,12 +31,12 @@
"clean": "del lib" "clean": "del lib"
}, },
"dependencies": { "dependencies": {
"@react-navigation/core": "^5.2.0" "@react-navigation/core": "^5.2.3"
}, },
"devDependencies": { "devDependencies": {
"@react-native-community/bob": "^0.9.3", "@react-native-community/bob": "^0.10.0",
"@types/react": "^16.9.19", "@types/react": "^16.9.23",
"@types/react-native": "^0.60.30", "@types/react-native": "^0.61.22",
"del-cli": "^3.0.0", "del-cli": "^3.0.0",
"react": "~16.9.0", "react": "~16.9.0",
"react-native": "~0.61.5", "react-native": "~0.61.5",

View File

@@ -7,7 +7,7 @@ const DefaultTheme: Theme = {
background: 'rgb(242, 242, 242)', background: 'rgb(242, 242, 242)',
card: 'rgb(255, 255, 255)', card: 'rgb(255, 255, 255)',
text: 'rgb(28, 28, 30)', text: 'rgb(28, 28, 30)',
border: 'rgb(199, 199, 204)', border: 'rgb(224, 224, 224)',
}, },
}; };

View File

@@ -6,11 +6,11 @@ type ScrollOptions = { y?: number; animated?: boolean };
type ScrollableView = type ScrollableView =
| { scrollToTop(): void } | { scrollToTop(): void }
| { scrollTo(options: ScrollOptions): void } | { scrollTo(options: ScrollOptions): void }
| { scrollToOffset(options: ScrollOptions): void } | { scrollToOffset(options: { offset?: number; animated?: boolean }): void }
| { scrollResponderScrollTo(options: ScrollOptions): void }; | { scrollResponderScrollTo(options: ScrollOptions): void };
type ScrollableWrapper = type ScrollableWrapper =
| { getScrollResponder(): ScrollableView } | { getScrollResponder(): React.ReactNode }
| { getNode(): ScrollableView } | { getNode(): ScrollableView }
| ScrollableView; | ScrollableView;
@@ -79,7 +79,7 @@ export default function useScrollToTop(
// Run the operation in the next frame so we're sure all listeners have been run // Run the operation in the next frame so we're sure all listeners have been run
// This is necessary to know if preventDefault() has been called // This is necessary to know if preventDefault() has been called
requestAnimationFrame(() => { requestAnimationFrame(() => {
const scrollable = getScrollableNode(ref); const scrollable = getScrollableNode(ref) as ScrollableWrapper;
if (isFocused && isFirst && scrollable && !e.defaultPrevented) { if (isFocused && isFirst && scrollable && !e.defaultPrevented) {
if ('scrollToTop' in scrollable) { if ('scrollToTop' in scrollable) {
@@ -87,7 +87,7 @@ export default function useScrollToTop(
} else if ('scrollTo' in scrollable) { } else if ('scrollTo' in scrollable) {
scrollable.scrollTo({ y: 0, animated: true }); scrollable.scrollTo({ y: 0, animated: true });
} else if ('scrollToOffset' in scrollable) { } else if ('scrollToOffset' in scrollable) {
scrollable.scrollToOffset({ y: 0, animated: true }); scrollable.scrollToOffset({ offset: 0, animated: true });
} else if ('scrollResponderScrollTo' in scrollable) { } else if ('scrollResponderScrollTo' in scrollable) {
scrollable.scrollResponderScrollTo({ y: 0, animated: true }); scrollable.scrollResponderScrollTo({ y: 0, animated: true });
} }

View File

@@ -3,6 +3,33 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.1.0...@react-navigation/routers@5.1.1) (2020-03-16)
### Bug Fixes
* don't handle action if no routes are present ([660cac3](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/commit/660cac3557bce8978812ce2750e961e7ada92d13))
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.0.3...@react-navigation/routers@5.1.0) (2020-03-03)
### Bug Fixes
* fix links for documentation ([5bb0f40](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/commit/5bb0f405ceb5755d39a0b5b1f2e4ecee0da051bc))
### Features
* make reset bubble up ([09f6808](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/commit/09f6808d7d43c70b2c502151f9f20fad03972886))
## [5.0.3](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.0.2...@react-navigation/routers@5.0.3) (2020-02-26) ## [5.0.3](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.0.2...@react-navigation/routers@5.0.3) (2020-02-26)
**Note:** Version bump only for package @react-navigation/routers **Note:** Version bump only for package @react-navigation/routers

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/routers", "name": "@react-navigation/routers",
"description": "Routers to help build custom navigators", "description": "Routers to help build custom navigators",
"version": "5.0.3", "version": "5.1.1",
"keywords": [ "keywords": [
"react", "react",
"react-native", "react-native",
@@ -33,7 +33,7 @@
"shortid": "^2.2.15" "shortid": "^2.2.15"
}, },
"devDependencies": { "devDependencies": {
"@react-native-community/bob": "^0.9.3", "@react-native-community/bob": "^0.10.0",
"del-cli": "^3.0.0", "del-cli": "^3.0.0",
"typescript": "^3.7.5" "typescript": "^3.7.5"
}, },

View File

@@ -29,8 +29,29 @@ const BaseRouter = {
}; };
} }
case 'RESET': case 'RESET': {
return action.payload as PartialState<State>; const nextState = action.payload as State | PartialState<State>;
if (nextState.stale === false) {
if (
state.routeNames.length !== nextState.routeNames.length ||
nextState.routeNames.some(name => !state.routeNames.includes(name))
) {
return null;
}
}
if (
nextState.routes.length === 0 ||
nextState.routes.some(
(route: { name: string }) => !state.routeNames.includes(route.name)
)
) {
return null;
}
return nextState;
}
default: default:
return null; return null;

View File

@@ -45,7 +45,7 @@ export function navigate(...args: any): Action {
if (!payload.hasOwnProperty('key') && !payload.hasOwnProperty('name')) { if (!payload.hasOwnProperty('key') && !payload.hasOwnProperty('name')) {
throw new Error( throw new Error(
'You need to specify name or key when calling navigate with an object as the argument. See https://reactnavigation.org/docs/navigation-actions.html#navigate for usage.' 'You need to specify name or key when calling navigate with an object as the argument. See https://reactnavigation.org/docs/navigation-actions#navigate for usage.'
); );
} }

View File

@@ -1,10 +1,16 @@
import shortid from 'shortid'; import shortid from 'shortid';
import { PartialState, CommonNavigationAction, Router } from './types'; import {
PartialState,
CommonNavigationAction,
Router,
ParamListBase,
} from './types';
import TabRouter, { import TabRouter, {
TabActions, TabActions,
TabActionType, TabActionType,
TabRouterOptions, TabRouterOptions,
TabNavigationState, TabNavigationState,
TabActionHelpers,
} from './TabRouter'; } from './TabRouter';
export type DrawerActionType = export type DrawerActionType =
@@ -31,6 +37,25 @@ export type DrawerNavigationState = Omit<
history: ({ type: 'route'; key: string } | { type: 'drawer' })[]; history: ({ type: 'route'; key: string } | { type: 'drawer' })[];
}; };
export type DrawerActionHelpers<
ParamList extends ParamListBase
> = TabActionHelpers<ParamList> & {
/**
* Open the drawer sidebar.
*/
openDrawer(): void;
/**
* Close the drawer sidebar.
*/
closeDrawer(): void;
/**
* Open the drawer sidebar if closed, or close if opened.
*/
toggleDrawer(): void;
};
export const DrawerActions = { export const DrawerActions = {
...TabActions, ...TabActions,
openDrawer(): DrawerActionType { openDrawer(): DrawerActionType {

View File

@@ -6,6 +6,7 @@ import {
Router, Router,
DefaultRouterOptions, DefaultRouterOptions,
Route, Route,
ParamListBase,
} from './types'; } from './types';
export type StackActionType = export type StackActionType =
@@ -42,6 +43,42 @@ export type StackNavigationState = NavigationState & {
type: 'stack'; type: 'stack';
}; };
export type StackActionHelpers<ParamList extends ParamListBase> = {
/**
* Replace the current route with a new one.
*
* @param name Route name of the new route.
* @param [params] Params object for the new route.
*/
replace<RouteName extends keyof ParamList>(
...args: ParamList[RouteName] extends undefined
? [RouteName] | [RouteName, ParamList[RouteName]]
: [RouteName, ParamList[RouteName]]
): void;
/**
* Push a new screen onto the stack.
*
* @param name Name of the route for the tab.
* @param [params] Params object for the route.
*/
push<RouteName extends keyof ParamList>(
...args: ParamList[RouteName] extends undefined | any
? [RouteName] | [RouteName, ParamList[RouteName]]
: [RouteName, ParamList[RouteName]]
): void;
/**
* Pop a screen from the stack.
*/
pop(count?: number): void;
/**
* Pop to the first route in the stack, dismissing all other screens.
*/
popToTop(): void;
};
export const StackActions = { export const StackActions = {
replace(name: string, params?: object): StackActionType { replace(name: string, params?: object): StackActionType {
return { type: 'REPLACE', payload: { name, params } }; return { type: 'REPLACE', payload: { name, params } };

View File

@@ -7,6 +7,7 @@ import {
Router, Router,
DefaultRouterOptions, DefaultRouterOptions,
Route, Route,
ParamListBase,
} from './types'; } from './types';
export type TabActionType = { export type TabActionType = {
@@ -33,6 +34,20 @@ export type TabNavigationState = Omit<NavigationState, 'history'> & {
history: { type: 'route'; key: string }[]; history: { type: 'route'; key: string }[];
}; };
export type TabActionHelpers<ParamList extends ParamListBase> = {
/**
* Jump to an existing tab.
*
* @param name Name of the route for the tab.
* @param [params] Params object for the route.
*/
jumpTo<RouteName extends Extract<keyof ParamList, string>>(
...args: ParamList[RouteName] extends undefined | any
? [RouteName] | [RouteName, ParamList[RouteName]]
: [RouteName, ParamList[RouteName]]
): void;
};
const TYPE_ROUTE = 'route' as const; const TYPE_ROUTE = 'route' as const;
export const TabActions = { export const TabActions = {

View File

@@ -83,3 +83,46 @@ it('resets state to new state with RESET', () => {
expect(result).toEqual({ index: 0, routes }); expect(result).toEqual({ index: 0, routes });
}); });
it("doesn't handle RESET if routes don't match routeNames", () => {
const routes = [
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
{ key: 'baz', name: 'baz' },
{ key: 'qux', name: 'quz' },
];
const result = BaseRouter.getStateForAction(
STATE,
CommonActions.reset({
index: 0,
routes,
})
);
expect(result).toEqual(null);
});
it("doesn't handle RESET if routeNames don't match", () => {
const result = BaseRouter.getStateForAction(
STATE,
CommonActions.reset({
...STATE,
// @ts-ignore
routeNames: ['ten'],
})
);
expect(result).toEqual(null);
});
it("doesn't handle RESET if there are no routes", () => {
const result = BaseRouter.getStateForAction(
STATE,
CommonActions.reset({
index: 0,
routes: [],
})
);
expect(result).toEqual(null);
});

View File

@@ -7,6 +7,7 @@ export { default as BaseRouter } from './BaseRouter';
export { export {
default as StackRouter, default as StackRouter,
StackActions, StackActions,
StackActionHelpers,
StackActionType, StackActionType,
StackRouterOptions, StackRouterOptions,
StackNavigationState, StackNavigationState,
@@ -15,6 +16,7 @@ export {
export { export {
default as TabRouter, default as TabRouter,
TabActions, TabActions,
TabActionHelpers,
TabActionType, TabActionType,
TabRouterOptions, TabRouterOptions,
TabNavigationState, TabNavigationState,
@@ -23,6 +25,7 @@ export {
export { export {
default as DrawerRouter, default as DrawerRouter,
DrawerActions, DrawerActions,
DrawerActionHelpers,
DrawerActionType, DrawerActionType,
DrawerRouterOptions, DrawerRouterOptions,
DrawerNavigationState, DrawerNavigationState,

View File

@@ -3,6 +3,57 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [5.2.2](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.1...@react-navigation/stack@5.2.2) (2020-03-19)
### Bug Fixes
* don't use react-native-screens on web ([b1a65fc](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/b1a65fc73e8603ae2c06ef101a74df31e80bb9b2)), closes [#7485](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/7485)
* fix blank page if stack was inside display: none before ([49f6fed](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/49f6fed6d3da878e02a9fe9115c05bcf84e332bf))
* fix closing stack using inverted gesture. ([#7824](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/7824)) ([f24d3a3](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/f24d3a3461ee8a566c25ce7d13f31035b4be2691))
* initialize height and width to zero if undefined ([3df65e2](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/3df65e28197db3bb8371059146546d57661c5ba3)), closes [#6789](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/6789)
* only dismiss previously focused input on page change. closes [#6918](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/6918) ([b1fe730](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/b1fe73097f3ad58d3ba4a8a9b875276d1d8d220c))
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.0...@react-navigation/stack@5.2.1) (2020-03-17)
**Note:** Version bump only for package @react-navigation/stack
# [5.2.0](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.1.1...@react-navigation/stack@5.2.0) (2020-03-16)
### Bug Fixes
* fix android header title font weight ([#7720](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/7720)) ([0dcaea3](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/0dcaea32428484cdc9b4d56f7bf38f9f1bdf1dee))
* fix back gesture cancellation ([#7700](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/7700)) ([469d054](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/469d0542c7341dc524a597d70216ba743602a51e)), closes [#6782](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/6782)
### Features
* add an option to change use a custom card overlay ([#7809](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/7809)) ([70029d6](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/70029d6c130f0f47de94b6a6c4cbee6afa12b405))
## [5.1.1](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.1.0...@react-navigation/stack@5.1.1) (2020-03-03)
### Bug Fixes
* ignore back button press if screen isn't focused. closes [#7673](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/7673) ([296c836](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/296c836064447e055a88e43cfbbf5f9de93838f0))
# [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.0.9...@react-navigation/stack@5.1.0) (2020-02-26) # [5.1.0](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.0.9...@react-navigation/stack@5.1.0) (2020-02-26)

View File

@@ -1,7 +1,7 @@
{ {
"name": "@react-navigation/stack", "name": "@react-navigation/stack",
"description": "Stack navigator component for iOS and Android with animated transitions and gestures", "description": "Stack navigator component for iOS and Android with animated transitions and gestures",
"version": "5.1.0", "version": "5.2.2",
"keywords": [ "keywords": [
"react-native-component", "react-native-component",
"react-component", "react-component",
@@ -38,18 +38,18 @@
"react-native-iphone-x-helper": "^1.2.1" "react-native-iphone-x-helper": "^1.2.1"
}, },
"devDependencies": { "devDependencies": {
"@react-native-community/bob": "^0.9.3", "@react-native-community/bob": "^0.10.0",
"@react-native-community/masked-view": "^0.1.6", "@react-native-community/masked-view": "^0.1.7",
"@react-navigation/native": "^5.0.8", "@react-navigation/native": "^5.1.1",
"@types/color": "^3.0.1", "@types/color": "^3.0.1",
"@types/react": "^16.9.19", "@types/react": "^16.9.23",
"@types/react-native": "^0.60.30", "@types/react-native": "^0.61.22",
"del-cli": "^3.0.0", "del-cli": "^3.0.0",
"react": "~16.9.0", "react": "~16.9.0",
"react-native": "~0.61.5", "react-native": "~0.61.5",
"react-native-gesture-handler": "^1.5.6", "react-native-gesture-handler": "^1.6.0",
"react-native-safe-area-context": "^0.7.2", "react-native-safe-area-context": "^0.7.3",
"react-native-screens": "^2.0.0-beta.2", "react-native-screens": "^2.3.0",
"typescript": "^3.7.5" "typescript": "^3.7.5"
}, },
"peerDependencies": { "peerDependencies": {
@@ -59,7 +59,7 @@
"react-native": "*", "react-native": "*",
"react-native-gesture-handler": ">= 1.0.0", "react-native-gesture-handler": ">= 1.0.0",
"react-native-safe-area-context": ">= 0.6.0", "react-native-safe-area-context": ">= 0.6.0",
"react-native-screens": ">= 2.0.0-alpha.0 || >= 2.0.0-beta.0" "react-native-screens": ">= 2.0.0-alpha.0 || >= 2.0.0-beta.0 || >= 2.0.0"
}, },
"@react-native-community/bob": { "@react-native-community/bob": {
"source": "src", "source": "src",

View File

@@ -1,3 +1,4 @@
import * as React from 'react';
import { import {
Animated, Animated,
StyleProp, StyleProp,
@@ -13,6 +14,7 @@ import {
Route, Route,
NavigationHelpers, NavigationHelpers,
StackNavigationState, StackNavigationState,
StackActionHelpers,
} from '@react-navigation/native'; } from '@react-navigation/native';
export type StackNavigationEventMap = { export type StackNavigationEventMap = {
@@ -40,29 +42,8 @@ export type StackNavigationProp<
StackNavigationState, StackNavigationState,
StackNavigationOptions, StackNavigationOptions,
StackNavigationEventMap StackNavigationEventMap
> & { > &
/** StackActionHelpers<ParamList>;
* Push a new screen onto the stack.
*
* @param name Name of the route for the tab.
* @param [params] Params object for the route.
*/
push<RouteName extends keyof ParamList>(
...args: ParamList[RouteName] extends undefined | any
? [RouteName] | [RouteName, ParamList[RouteName]]
: [RouteName, ParamList[RouteName]]
): void;
/**
* Pop a screen from the stack.
*/
pop(count?: number): void;
/**
* Pop to the first route in the stack, dismissing all other screens.
*/
popToTop(): void;
};
export type Layout = { width: number; height: number }; export type Layout = { width: number; height: number };
@@ -122,7 +103,7 @@ export type StackHeaderOptions = {
/** /**
* Style object for the title component. * Style object for the title component.
*/ */
headerTitleStyle?: StyleProp<TextStyle>; headerTitleStyle?: React.ComponentProps<typeof Animated.Text>['style'];
/** /**
* Style object for the container of the `headerTitle` component, for example to add padding. * Style object for the container of the `headerTitle` component, for example to add padding.
* By default, `headerTitleContainerStyle` is with an absolute position style and offsets both `left` and `right`. * By default, `headerTitleContainerStyle` is with an absolute position style and offsets both `left` and `right`.
@@ -279,6 +260,10 @@ export type StackNavigationOptions = StackHeaderOptions &
* Defaults to `true` on Android and `false` on iOS. * Defaults to `true` on Android and `false` on iOS.
*/ */
cardOverlayEnabled?: boolean; cardOverlayEnabled?: boolean;
/**
* Function that returns a React Element to display as a overlay for the card.
*/
cardOverlay?: (props: { style: StyleProp<ViewStyle> }) => React.ReactNode;
/** /**
* Style object for the card in stack. * Style object for the card in stack.
* You can provide a custom background color to use instead of the default background here. * You can provide a custom background color to use instead of the default background here.
@@ -430,7 +415,7 @@ export type StackHeaderTitleProps = {
/** /**
* Style object for the title element. * Style object for the title element.
*/ */
style?: StyleProp<TextStyle>; style?: React.ComponentProps<typeof Animated.Text>['style'];
}; };
export type TransitionSpec = export type TransitionSpec =

View File

@@ -32,13 +32,14 @@ export default class BorderlessButton extends React.Component<Props> {
}).start(); }).start();
} }
this.props.onActiveStateChange && this.props.onActiveStateChange(active); this.props.onActiveStateChange?.(active);
}; };
render() { render() {
const { children, style, enabled, ...rest } = this.props; const { children, style, enabled, ...rest } = this.props;
return ( return (
// @ts-ignore
<AnimatedBaseButton <AnimatedBaseButton
{...rest} {...rest}
onActiveStateChange={this.handleActiveStateChange} onActiveStateChange={this.handleActiveStateChange}

View File

@@ -43,7 +43,7 @@ export default React.memo(function Header(props: StackHeaderProps) {
const goBack = React.useCallback( const goBack = React.useCallback(
debounce(() => { debounce(() => {
if (navigation.canGoBack()) { if (navigation.isFocused() && navigation.canGoBack()) {
navigation.dispatch({ navigation.dispatch({
...StackActions.pop(), ...StackActions.pop(),
source: scene.route.key, source: scene.route.key,

View File

@@ -1,8 +1,8 @@
import * as React from 'react'; import * as React from 'react';
import { Animated, StyleSheet, Platform, TextProps } from 'react-native'; import { Animated, StyleSheet, Platform } from 'react-native';
import { useTheme } from '@react-navigation/native'; import { useTheme } from '@react-navigation/native';
type Props = TextProps & { type Props = React.ComponentProps<typeof Animated.Text> & {
tintColor?: string; tintColor?: string;
children?: string; children?: string;
}; };
@@ -32,7 +32,8 @@ const styles = StyleSheet.create({
}, },
android: { android: {
fontSize: 20, fontSize: 20,
fontWeight: '500', fontFamily: 'sans-serif-medium',
fontWeight: 'normal',
}, },
default: { default: {
fontSize: 18, fontSize: 18,

View File

@@ -1,5 +1,5 @@
import * as React from 'react'; import * as React from 'react';
import { TextInput, Keyboard } from 'react-native'; import { TextInput } from 'react-native';
type Props = { type Props = {
enabled: boolean; enabled: boolean;
@@ -54,7 +54,11 @@ export default class KeyboardManager extends React.Component<Props> {
this.clearKeyboardTimeout(); this.clearKeyboardTimeout();
Keyboard.dismiss(); const input = this.previouslyFocusedTextInput;
if (input) {
TextInput.State.blurTextInput(input);
}
// Cleanup the ID on successful page change // Cleanup the ID on successful page change
this.previouslyFocusedTextInput = null; this.previouslyFocusedTextInput = null;

View File

@@ -44,6 +44,7 @@ type Props = ViewProps & {
onGestureCanceled?: () => void; onGestureCanceled?: () => void;
onGestureEnd?: () => void; onGestureEnd?: () => void;
children: React.ReactNode; children: React.ReactNode;
overlay: (props: { style: StyleProp<ViewStyle> }) => React.ReactNode;
overlayEnabled: boolean; overlayEnabled: boolean;
shadowEnabled: boolean; shadowEnabled: boolean;
gestureEnabled: boolean; gestureEnabled: boolean;
@@ -80,6 +81,10 @@ export default class Card extends React.Component<Props> {
shadowEnabled: true, shadowEnabled: true,
gestureEnabled: true, gestureEnabled: true,
gestureVelocityImpact: GESTURE_VELOCITY_IMPACT, gestureVelocityImpact: GESTURE_VELOCITY_IMPACT,
overlay: ({ style }: { style: StyleProp<ViewStyle> }) =>
style ? (
<Animated.View pointerEvents="none" style={[styles.overlay, style]} />
) : null,
}; };
componentDidMount() { componentDidMount() {
@@ -266,9 +271,16 @@ export default class Card extends React.Component<Props> {
velocity = nativeEvent.velocityX; velocity = nativeEvent.velocityX;
} }
if (
gestureDirection === 'horizontal-inverted' ||
gestureDirection === 'vertical-inverted'
) {
translation *= -1;
velocity *= -1;
}
const closing = const closing =
Math.abs(translation + velocity * gestureVelocityImpact) > translation + velocity * gestureVelocityImpact > distance / 2
distance / 2
? velocity !== 0 || translation !== 0 ? velocity !== 0 || translation !== 0
: false; : false;
@@ -409,6 +421,7 @@ export default class Card extends React.Component<Props> {
next, next,
layout, layout,
insets, insets,
overlay,
overlayEnabled, overlayEnabled,
shadowEnabled, shadowEnabled,
gestureEnabled, gestureEnabled,
@@ -470,55 +483,54 @@ export default class Card extends React.Component<Props> {
: false; : false;
return ( return (
<View pointerEvents="box-none" {...rest}> <CardAnimationContext.Provider value={animationContext}>
{overlayEnabled && overlayStyle ? ( <View pointerEvents="box-none" {...rest}>
{overlayEnabled ? (
<View style={StyleSheet.absoluteFill}>
{overlay({ style: overlayStyle })}
</View>
) : null}
<Animated.View <Animated.View
pointerEvents="none" style={[styles.container, containerStyle, customContainerStyle]}
style={[styles.overlay, overlayStyle]} pointerEvents="box-none"
/>
) : null}
<Animated.View
style={[styles.container, containerStyle, customContainerStyle]}
pointerEvents="box-none"
>
<PanGestureHandler
ref={this.gestureRef}
enabled={layout.width !== 0 && gestureEnabled}
onGestureEvent={handleGestureEvent}
onHandlerStateChange={this.handleGestureStateChange}
{...this.gestureActivationCriteria()}
> >
<Animated.View style={[styles.container, cardStyle]}> <PanGestureHandler
{shadowEnabled && shadowStyle && !isTransparent ? ( ref={this.gestureRef}
<Animated.View enabled={layout.width !== 0 && gestureEnabled}
style={[ onGestureEvent={handleGestureEvent}
styles.shadow, onHandlerStateChange={this.handleGestureStateChange}
gestureDirection === 'horizontal' {...this.gestureActivationCriteria()}
? [styles.shadowHorizontal, styles.shadowLeft] >
: gestureDirection === 'horizontal-inverted' <Animated.View style={[styles.container, cardStyle]}>
? [styles.shadowHorizontal, styles.shadowRight] {shadowEnabled && shadowStyle && !isTransparent ? (
: gestureDirection === 'vertical' <Animated.View
? [styles.shadowVertical, styles.shadowTop] style={[
: [styles.shadowVertical, styles.shadowBottom], styles.shadow,
shadowStyle, gestureDirection === 'horizontal'
]} ? [styles.shadowHorizontal, styles.shadowLeft]
pointerEvents="none" : gestureDirection === 'horizontal-inverted'
/> ? [styles.shadowHorizontal, styles.shadowRight]
) : null} : gestureDirection === 'vertical'
<View ? [styles.shadowVertical, styles.shadowTop]
ref={this.contentRef} : [styles.shadowVertical, styles.shadowBottom],
style={[styles.content, contentStyle]} shadowStyle,
> ]}
<StackGestureRefContext.Provider value={this.gestureRef}> pointerEvents="none"
<CardAnimationContext.Provider value={animationContext}> />
) : null}
<View
ref={this.contentRef}
style={[styles.content, contentStyle]}
>
<StackGestureRefContext.Provider value={this.gestureRef}>
{children} {children}
</CardAnimationContext.Provider> </StackGestureRefContext.Provider>
</StackGestureRefContext.Provider> </View>
</View> </Animated.View>
</Animated.View> </PanGestureHandler>
</PanGestureHandler> </Animated.View>
</Animated.View> </View>
</View> </CardAnimationContext.Provider>
); );
} }
} }
@@ -532,7 +544,7 @@ const styles = StyleSheet.create({
overflow: 'hidden', overflow: 'hidden',
}, },
overlay: { overlay: {
...StyleSheet.absoluteFillObject, flex: 1,
backgroundColor: '#000', backgroundColor: '#000',
}, },
shadow: { shadow: {

View File

@@ -19,6 +19,7 @@ type Props = TransitionPreset & {
safeAreaInsetRight: number; safeAreaInsetRight: number;
safeAreaInsetBottom: number; safeAreaInsetBottom: number;
safeAreaInsetLeft: number; safeAreaInsetLeft: number;
cardOverlay?: (props: { style: StyleProp<ViewStyle> }) => React.ReactNode;
cardOverlayEnabled?: boolean; cardOverlayEnabled?: boolean;
cardShadowEnabled?: boolean; cardShadowEnabled?: boolean;
cardStyle?: StyleProp<ViewStyle>; cardStyle?: StyleProp<ViewStyle>;
@@ -58,6 +59,7 @@ const EPSILON = 0.1;
function CardContainer({ function CardContainer({
active, active,
cardOverlay,
cardOverlayEnabled, cardOverlayEnabled,
cardShadowEnabled, cardShadowEnabled,
cardStyle, cardStyle,
@@ -162,6 +164,7 @@ function CardContainer({
closing={closing} closing={closing}
onOpen={handleOpen} onOpen={handleOpen}
onClose={handleClose} onClose={handleClose}
overlay={cardOverlay}
overlayEnabled={cardOverlayEnabled} overlayEnabled={cardOverlayEnabled}
shadowEnabled={cardShadowEnabled} shadowEnabled={cardShadowEnabled}
onTransitionStart={handleTransitionStart} onTransitionStart={handleTransitionStart}

View File

@@ -75,9 +75,6 @@ type State = {
const EPSILON = 0.01; const EPSILON = 0.01;
const dimensions = Dimensions.get('window');
const layout = { width: dimensions.width, height: dimensions.height };
const MaybeScreenContainer = ({ const MaybeScreenContainer = ({
enabled, enabled,
...rest ...rest
@@ -160,7 +157,16 @@ const getProgressFromGesture = (
layout: Layout, layout: Layout,
descriptor?: StackDescriptor descriptor?: StackDescriptor
) => { ) => {
const distance = getDistanceFromOptions(mode, layout, descriptor); const distance = getDistanceFromOptions(
mode,
{
// Make sure that we have a non-zero distance, otherwise there will be incorrect progress
// This causes blank screen on web if it was previously inside container with display: none
width: Math.max(1, layout.width),
height: Math.max(1, layout.height),
},
descriptor
);
if (distance > 0) { if (distance > 0) {
return gesture.interpolate({ return gesture.interpolate({
@@ -290,19 +296,25 @@ export default class CardStack extends React.Component<Props, State> {
}; };
} }
state: State = { constructor(props: Props) {
routes: [], super(props);
scenes: [],
gestures: {}, const { height = 0, width = 0 } = Dimensions.get('window');
layout,
descriptors: this.props.descriptors, this.state = {
// Used when card's header is null and mode is float to make transition routes: [],
// between screens with headers and those without headers smooth. scenes: [],
// This is not a great heuristic here. We don't know synchronously gestures: {},
// on mount what the header height is so we have just used the most layout: { height, width },
// common cases here. descriptors: this.props.descriptors,
headerHeights: {}, // Used when card's header is null and mode is float to make transition
}; // between screens with headers and those without headers smooth.
// This is not a great heuristic here. We don't know synchronously
// on mount what the header height is so we have just used the most
// common cases here.
headerHeights: {},
};
}
private handleLayout = (e: LayoutChangeEvent) => { private handleLayout = (e: LayoutChangeEvent) => {
const { height, width } = e.nativeEvent.layout; const { height, width } = e.nativeEvent.layout;
@@ -401,9 +413,9 @@ export default class CardStack extends React.Component<Props, State> {
left = insets.left, left = insets.left,
} = focusedOptions.safeAreaInsets || {}; } = focusedOptions.safeAreaInsets || {};
// Screens is buggy on iOS, so we don't enable it there // Screens is buggy on iOS and web, so we only enable it on Android
// For modals, usually we want the screen underneath to be visible, so also disable it there // For modals, usually we want the screen underneath to be visible, so also disable it there
const isScreensEnabled = Platform.OS !== 'ios' && mode !== 'modal'; const isScreensEnabled = Platform.OS === 'android' && mode !== 'modal';
return ( return (
<React.Fragment> <React.Fragment>
@@ -431,6 +443,7 @@ export default class CardStack extends React.Component<Props, State> {
headerTransparent, headerTransparent,
cardShadowEnabled, cardShadowEnabled,
cardOverlayEnabled, cardOverlayEnabled,
cardOverlay,
cardStyle, cardStyle,
animationEnabled, animationEnabled,
gestureResponseDistance, gestureResponseDistance,
@@ -528,6 +541,7 @@ export default class CardStack extends React.Component<Props, State> {
safeAreaInsetRight={safeAreaInsetRight} safeAreaInsetRight={safeAreaInsetRight}
safeAreaInsetBottom={safeAreaInsetBottom} safeAreaInsetBottom={safeAreaInsetBottom}
safeAreaInsetLeft={safeAreaInsetLeft} safeAreaInsetLeft={safeAreaInsetLeft}
cardOverlay={cardOverlay}
cardOverlayEnabled={cardOverlayEnabled} cardOverlayEnabled={cardOverlayEnabled}
cardShadowEnabled={cardShadowEnabled} cardShadowEnabled={cardShadowEnabled}
cardStyle={cardStyle} cardStyle={cardStyle}

1385
yarn.lock

File diff suppressed because it is too large Load Diff