mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-13 22:42:25 +08:00
Compare commits
20 Commits
@react-nav
...
@react-nav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9556aa9eff | ||
|
|
9a8fea8f2c | ||
|
|
9973db86f0 | ||
|
|
8432e5ab25 | ||
|
|
9bb5cfded3 | ||
|
|
4ac40b5c5d | ||
|
|
cd47915861 | ||
|
|
d649fbc669 | ||
|
|
105da6ab2f | ||
|
|
ac7f972e92 | ||
|
|
babb5027f9 | ||
|
|
78d7a66b2b | ||
|
|
a248c453ba | ||
|
|
e097df880a | ||
|
|
856449b200 | ||
|
|
d94e43c3c8 | ||
|
|
3096de6286 | ||
|
|
1c001424b5 | ||
|
|
0f2368965c | ||
|
|
61f16d3f25 |
@@ -1,4 +1,4 @@
|
||||
/* eslint-disable jest/no-jasmine-globals, import/no-commonjs */
|
||||
/* eslint-disable import/no-commonjs */
|
||||
|
||||
const detox = require('detox');
|
||||
const config = require('../../package.json').detox;
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
"@types/react-native-restart": "^0.0.0",
|
||||
"color": "^3.1.2",
|
||||
"expo": "^36.0.2",
|
||||
"expo-asset": "~8.0.0",
|
||||
"expo-blur": "^8.0.0",
|
||||
"expo-asset": "~8.1.1",
|
||||
"expo-blur": "~8.1.0",
|
||||
"react": "~16.9.0",
|
||||
"react-dom": "~16.9.0",
|
||||
"react-native": "~0.61.5",
|
||||
@@ -28,15 +28,15 @@
|
||||
"react-native-safe-area-context": "^0.7.3",
|
||||
"react-native-screens": "^2.3.0",
|
||||
"react-native-tab-view": "2.13.0",
|
||||
"react-native-unimodules": "^0.7.0",
|
||||
"react-native-unimodules": "^0.8.1",
|
||||
"react-native-web": "^0.11.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@expo/webpack-config": "^0.11.7",
|
||||
"@expo/webpack-config": "^0.11.9",
|
||||
"@types/react": "^16.9.23",
|
||||
"@types/react-native": "^0.61.22",
|
||||
"babel-preset-expo": "^8.0.0",
|
||||
"expo-cli": "^3.13.8",
|
||||
"typescript": "^3.7.5"
|
||||
"babel-preset-expo": "^8.1.0",
|
||||
"expo-cli": "^3.15.5",
|
||||
"typescript": "^3.8.3"
|
||||
}
|
||||
}
|
||||
|
||||
22
package.json
22
package.json
@@ -18,7 +18,7 @@
|
||||
"author": "Satyajit Sahoo <satyajit.happy@gmail.com> (https://github.com/satya164/), Michał Osadnik <micosa97@gmail.com> (https://github.com/osdnk/)",
|
||||
"scripts": {
|
||||
"lint": "eslint --ext '.js,.ts,.tsx' .",
|
||||
"typescript": "tsc --noEmit",
|
||||
"typescript": "tsc --noEmit --composite false",
|
||||
"test": "jest",
|
||||
"prerelease": "lerna run clean",
|
||||
"release": "lerna publish",
|
||||
@@ -26,25 +26,25 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.8.3",
|
||||
"@babel/preset-env": "^7.8.7",
|
||||
"@babel/preset-flow": "^7.8.3",
|
||||
"@babel/preset-react": "^7.8.3",
|
||||
"@babel/preset-typescript": "^7.8.3",
|
||||
"@babel/runtime": "^7.8.7",
|
||||
"@babel/plugin-proposal-optional-chaining": "^7.9.0",
|
||||
"@babel/preset-env": "^7.9.0",
|
||||
"@babel/preset-flow": "^7.9.0",
|
||||
"@babel/preset-react": "^7.9.4",
|
||||
"@babel/preset-typescript": "^7.9.0",
|
||||
"@babel/runtime": "^7.9.2",
|
||||
"@commitlint/config-conventional": "^8.3.4",
|
||||
"@types/jest": "^25.1.4",
|
||||
"babel-jest": "^25.2.1",
|
||||
"codecov": "^3.6.5",
|
||||
"commitlint": "^8.3.5",
|
||||
"core-js": "^3.6.4",
|
||||
"detox": "^16.0.0",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-satya164": "^3.1.5",
|
||||
"eslint-config-satya164": "^3.1.6",
|
||||
"husky": "^4.2.3",
|
||||
"jest": "^25.1.0",
|
||||
"lerna": "^3.20.2",
|
||||
"prettier": "^2.0.1",
|
||||
"typescript": "^3.7.5"
|
||||
"prettier": "^2.0.2",
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"resolutions": {
|
||||
"react": "~16.9.0",
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [5.2.5](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.4...@react-navigation/bottom-tabs@5.2.5) (2020-03-30)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.2.4](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.3...@react-navigation/bottom-tabs@5.2.4) (2020-03-23)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.2.3](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.2...@react-navigation/bottom-tabs@5.2.3) (2020-03-22)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/bottom-tabs",
|
||||
"description": "Bottom tab navigator following iOS design guidelines",
|
||||
"version": "5.2.3",
|
||||
"version": "5.2.5",
|
||||
"keywords": [
|
||||
"react-native-component",
|
||||
"react-component",
|
||||
@@ -35,7 +35,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
"@react-navigation/native": "^5.1.2",
|
||||
"@react-navigation/native": "^5.1.4",
|
||||
"@types/color": "^3.0.1",
|
||||
"@types/react": "^16.9.23",
|
||||
"@types/react-native": "^0.61.22",
|
||||
@@ -44,7 +44,7 @@
|
||||
"react-native": "~0.61.5",
|
||||
"react-native-safe-area-context": "^0.7.3",
|
||||
"react-native-screens": "^2.3.0",
|
||||
"typescript": "^3.7.5"
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-navigation/native": "^5.0.5",
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [5.1.7](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.6...@react-navigation/compat@5.1.7) (2020-03-30)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/compat
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.1.6](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.5...@react-navigation/compat@5.1.6) (2020-03-23)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/compat
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.1.5](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.4...@react-navigation/compat@5.1.5) (2020-03-22)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/compat
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/compat",
|
||||
"description": "Compatibility layer to write navigator definitions in static configuration format",
|
||||
"version": "5.1.5",
|
||||
"version": "5.1.7",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/react-navigation/tree/master/packages/compat",
|
||||
"bugs": {
|
||||
@@ -26,10 +26,10 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
"@react-navigation/native": "^5.1.2",
|
||||
"@react-navigation/native": "^5.1.4",
|
||||
"@types/react": "^16.9.23",
|
||||
"react": "~16.9.0",
|
||||
"typescript": "^3.7.5"
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-navigation/native": "^5.0.5",
|
||||
|
||||
@@ -3,6 +3,29 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [5.3.2](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.3.1...@react-navigation/core@5.3.2) (2020-03-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* handle no path property and undefined query params ([#7911](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/7911)) ([cd47915](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/cd47915861a56cd7eaa9ac79f5139cde56ca95a7))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.3.1](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.3.0...@react-navigation/core@5.3.1) (2020-03-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* don't emit events for screens that don't exist anymore ([1c00142](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/1c001424b595b40f9db9343096c833f75353b099))
|
||||
* only call listeners for focused screen for global events ([3096de6](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/3096de62868a7ed9ed65e529c8ddfa001b9be486))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.3.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.2.3...@react-navigation/core@5.3.0) (2020-03-22)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/core",
|
||||
"description": "Core utilities for building navigators",
|
||||
"version": "5.3.0",
|
||||
"version": "5.3.2",
|
||||
"keywords": [
|
||||
"react",
|
||||
"react-native",
|
||||
@@ -29,24 +29,23 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.2.0",
|
||||
"@react-navigation/routers": "^5.2.1",
|
||||
"escape-string-regexp": "^2.0.0",
|
||||
"nanoid": "^3.0.2",
|
||||
"query-string": "^6.11.1",
|
||||
"react-is": "^16.13.0",
|
||||
"shortid": "^2.2.15",
|
||||
"use-subscription": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
"@types/react": "^16.9.23",
|
||||
"@types/react-is": "^16.7.1",
|
||||
"@types/shortid": "^0.0.29",
|
||||
"@types/use-subscription": "^1.0.0",
|
||||
"del-cli": "^3.0.0",
|
||||
"react": "~16.9.0",
|
||||
"react-native-testing-library": "^1.12.0",
|
||||
"react-test-renderer": "~16.9.0",
|
||||
"typescript": "^3.7.5"
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*"
|
||||
|
||||
@@ -521,3 +521,209 @@ it('returns "/" for empty path', () => {
|
||||
|
||||
expect(getPathFromState(state, config)).toBe('/');
|
||||
});
|
||||
|
||||
it('parses no path specified', () => {
|
||||
const path = '/Foo/bar';
|
||||
const config = {
|
||||
Foo: {
|
||||
screens: {
|
||||
Foe: {},
|
||||
},
|
||||
},
|
||||
Bar: 'bar',
|
||||
};
|
||||
|
||||
const state = {
|
||||
routes: [
|
||||
{
|
||||
name: 'Foo',
|
||||
state: {
|
||||
routes: [{ name: 'Bar' }],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(getPathFromState(state, config)).toBe(path);
|
||||
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||
});
|
||||
|
||||
it('parses no path specified in nested config', () => {
|
||||
const path = '/Foo/Foe/bar';
|
||||
const config = {
|
||||
Foo: {
|
||||
path: 'foo',
|
||||
screens: {
|
||||
Foe: {},
|
||||
},
|
||||
},
|
||||
Bar: 'bar',
|
||||
};
|
||||
|
||||
const state = {
|
||||
routes: [
|
||||
{
|
||||
name: 'Foo',
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Foe',
|
||||
state: {
|
||||
routes: [{ name: 'Bar' }],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(getPathFromState(state, config)).toBe(path);
|
||||
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||
});
|
||||
|
||||
it('strips undefined query params', () => {
|
||||
const path = '/bar/sweet/apple/foo/bis/jane?count=10&valid=true';
|
||||
const config = {
|
||||
Foo: {
|
||||
path: 'foo',
|
||||
screens: {
|
||||
Foe: {
|
||||
path: 'foe',
|
||||
},
|
||||
},
|
||||
},
|
||||
Bar: 'bar/:type/:fruit',
|
||||
Baz: {
|
||||
path: 'baz',
|
||||
screens: {
|
||||
Bos: 'bos',
|
||||
Bis: {
|
||||
path: 'bis/:author',
|
||||
stringify: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||
},
|
||||
parse: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const state = {
|
||||
routes: [
|
||||
{
|
||||
name: 'Bar',
|
||||
params: { fruit: 'apple', type: 'sweet' },
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Foo',
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Baz',
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Bis',
|
||||
params: {
|
||||
author: 'Jane',
|
||||
count: 10,
|
||||
answer: undefined,
|
||||
valid: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(getPathFromState(state, config)).toBe(path);
|
||||
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||
});
|
||||
|
||||
it('handles stripping all query params', () => {
|
||||
const path = '/bar/sweet/apple/foo/bis/jane';
|
||||
const config = {
|
||||
Foo: {
|
||||
path: 'foo',
|
||||
screens: {
|
||||
Foe: {
|
||||
path: 'foe',
|
||||
},
|
||||
},
|
||||
},
|
||||
Bar: 'bar/:type/:fruit',
|
||||
Baz: {
|
||||
path: 'baz',
|
||||
screens: {
|
||||
Bos: 'bos',
|
||||
Bis: {
|
||||
path: 'bis/:author',
|
||||
stringify: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, (c) => c.toLowerCase()),
|
||||
},
|
||||
parse: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, (c) => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const state = {
|
||||
routes: [
|
||||
{
|
||||
name: 'Bar',
|
||||
params: { fruit: 'apple', type: 'sweet' },
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Foo',
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Baz',
|
||||
state: {
|
||||
routes: [
|
||||
{
|
||||
name: 'Bis',
|
||||
params: {
|
||||
author: 'Jane',
|
||||
count: undefined,
|
||||
answer: undefined,
|
||||
valid: undefined,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
expect(getPathFromState(state, config)).toBe(path);
|
||||
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||
});
|
||||
|
||||
@@ -565,12 +565,10 @@ it('fires custom events added with listeners prop', () => {
|
||||
});
|
||||
|
||||
expect(firstCallback.mock.calls[0][0].target).toBe(undefined);
|
||||
expect(secondCallback.mock.calls[0][0].target).toBe(undefined);
|
||||
expect(thirdCallback.mock.calls[1][0].target).toBe(undefined);
|
||||
|
||||
expect(firstCallback).toBeCalledTimes(1);
|
||||
expect(secondCallback).toBeCalledTimes(1);
|
||||
expect(thirdCallback).toBeCalledTimes(2);
|
||||
expect(secondCallback).toBeCalledTimes(0);
|
||||
expect(thirdCallback).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it("doesn't call same listener multiple times with listeners", () => {
|
||||
@@ -624,6 +622,91 @@ it("doesn't call same listener multiple times with listeners", () => {
|
||||
expect(callback).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it('fires listeners when callback is provided for listeners prop', () => {
|
||||
const eventName = 'someSuperCoolEvent';
|
||||
|
||||
const TestNavigator = React.forwardRef((props: any, ref: any): any => {
|
||||
const { state, navigation } = useNavigationBuilder(MockRouter, props);
|
||||
|
||||
React.useImperativeHandle(ref, () => ({ navigation, state }), [
|
||||
navigation,
|
||||
state,
|
||||
]);
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
const firstCallback = jest.fn();
|
||||
const secondCallback = jest.fn();
|
||||
const thirdCallback = jest.fn();
|
||||
|
||||
const ref = React.createRef<any>();
|
||||
|
||||
const element = (
|
||||
<BaseNavigationContainer>
|
||||
<TestNavigator ref={ref}>
|
||||
<Screen
|
||||
name="first"
|
||||
listeners={({ route, navigation }) => ({
|
||||
someSuperCoolEvent: (e) => firstCallback(e, route, navigation),
|
||||
})}
|
||||
component={jest.fn()}
|
||||
/>
|
||||
<Screen
|
||||
name="second"
|
||||
listeners={({ route, navigation }) => ({
|
||||
someSuperCoolEvent: (e) => secondCallback(e, route, navigation),
|
||||
})}
|
||||
component={jest.fn()}
|
||||
/>
|
||||
<Screen
|
||||
name="third"
|
||||
listeners={({ route, navigation }) => ({
|
||||
someSuperCoolEvent: (e) => thirdCallback(e, route, navigation),
|
||||
})}
|
||||
component={jest.fn()}
|
||||
/>
|
||||
</TestNavigator>
|
||||
</BaseNavigationContainer>
|
||||
);
|
||||
|
||||
render(element);
|
||||
|
||||
expect(firstCallback).toBeCalledTimes(0);
|
||||
expect(secondCallback).toBeCalledTimes(0);
|
||||
expect(thirdCallback).toBeCalledTimes(0);
|
||||
|
||||
const target =
|
||||
ref.current.state.routes[ref.current.state.routes.length - 1].key;
|
||||
|
||||
act(() => {
|
||||
ref.current.navigation.emit({
|
||||
type: eventName,
|
||||
target,
|
||||
data: 42,
|
||||
});
|
||||
});
|
||||
|
||||
expect(firstCallback).toBeCalledTimes(0);
|
||||
expect(secondCallback).toBeCalledTimes(0);
|
||||
expect(thirdCallback).toBeCalledTimes(1);
|
||||
expect(thirdCallback.mock.calls[0][0].type).toBe('someSuperCoolEvent');
|
||||
expect(thirdCallback.mock.calls[0][0].data).toBe(42);
|
||||
expect(thirdCallback.mock.calls[0][0].target).toBe(target);
|
||||
expect(thirdCallback.mock.calls[0][0].defaultPrevented).toBe(undefined);
|
||||
expect(thirdCallback.mock.calls[0][0].preventDefault).toBe(undefined);
|
||||
|
||||
act(() => {
|
||||
ref.current.navigation.emit({ type: eventName });
|
||||
});
|
||||
|
||||
expect(firstCallback.mock.calls[0][0].target).toBe(undefined);
|
||||
|
||||
expect(firstCallback).toBeCalledTimes(1);
|
||||
expect(secondCallback).toBeCalledTimes(0);
|
||||
expect(thirdCallback).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it('has option to prevent default', () => {
|
||||
expect.assertions(5);
|
||||
|
||||
|
||||
@@ -64,6 +64,8 @@ export default function getPathFromState(
|
||||
};
|
||||
let currentOptions = options;
|
||||
let pattern = route.name;
|
||||
// we keep all the route names that appeared during going deeper in config in case the pattern is resolved to undefined
|
||||
let nestedRouteNames = '';
|
||||
|
||||
while (route.name in currentOptions) {
|
||||
if (typeof currentOptions[route.name] === 'string') {
|
||||
@@ -77,11 +79,13 @@ export default function getPathFromState(
|
||||
}).screens
|
||||
) {
|
||||
pattern = (currentOptions[route.name] as { path: string }).path;
|
||||
nestedRouteNames = `${nestedRouteNames}/${route.name}`;
|
||||
break;
|
||||
} else {
|
||||
// if it is the end of state, we return pattern
|
||||
if (route.state === undefined) {
|
||||
pattern = (currentOptions[route.name] as { path: string }).path;
|
||||
nestedRouteNames = `${nestedRouteNames}/${route.name}`;
|
||||
break;
|
||||
} else {
|
||||
index =
|
||||
@@ -92,11 +96,13 @@ export default function getPathFromState(
|
||||
}).screens;
|
||||
// if there is config for next route name, we go deeper
|
||||
if (nextRoute.name in deeperConfig) {
|
||||
nestedRouteNames = `${nestedRouteNames}/${route.name}`;
|
||||
route = nextRoute as Route<string> & { state?: State };
|
||||
currentOptions = deeperConfig;
|
||||
} else {
|
||||
// if not, there is no sense in going deeper in config
|
||||
pattern = (currentOptions[route.name] as { path: string }).path;
|
||||
nestedRouteNames = `${nestedRouteNames}/${route.name}`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -104,6 +110,11 @@ export default function getPathFromState(
|
||||
}
|
||||
}
|
||||
|
||||
if (pattern === undefined) {
|
||||
// cut the first `/`
|
||||
pattern = nestedRouteNames.substring(1);
|
||||
}
|
||||
|
||||
// we don't add empty path strings to path
|
||||
if (pattern !== '') {
|
||||
const config =
|
||||
@@ -147,6 +158,12 @@ export default function getPathFromState(
|
||||
if (route.state) {
|
||||
path += '/';
|
||||
} else if (params) {
|
||||
for (let param in params) {
|
||||
if (params[param] === 'undefined') {
|
||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||
delete params[param];
|
||||
}
|
||||
}
|
||||
const query = queryString.stringify(params);
|
||||
|
||||
if (query) {
|
||||
|
||||
@@ -371,36 +371,40 @@ export default function useNavigationBuilder<
|
||||
const emitter = useEventEmitter((e) => {
|
||||
let routeNames = [];
|
||||
|
||||
let target: Route<string> | undefined;
|
||||
let route: Route<string> | undefined;
|
||||
|
||||
if (e.target) {
|
||||
target = state.routes.find((route) => route.key === e.target);
|
||||
route = state.routes.find((route) => route.key === e.target);
|
||||
|
||||
if (target?.name) {
|
||||
routeNames.push(target.name);
|
||||
if (route?.name) {
|
||||
routeNames.push(route.name);
|
||||
}
|
||||
} else {
|
||||
routeNames.push(...Object.keys(screens));
|
||||
route = state.routes[state.index];
|
||||
routeNames.push(
|
||||
...Object.keys(screens).filter((name) => route?.name === name)
|
||||
);
|
||||
}
|
||||
|
||||
if (route == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const navigation = descriptors[route.key].navigation;
|
||||
|
||||
const listeners = ([] as (((e: any) => void) | undefined)[])
|
||||
.concat(
|
||||
...routeNames.map((name) => {
|
||||
const { listeners } = screens[name];
|
||||
const map =
|
||||
typeof listeners === 'function'
|
||||
? listeners({ route: route as any, navigation })
|
||||
: listeners;
|
||||
|
||||
return listeners
|
||||
? Object.keys(listeners)
|
||||
return map
|
||||
? Object.keys(map)
|
||||
.filter((type) => type === e.type)
|
||||
.map((type) => {
|
||||
if (typeof listeners === 'function') {
|
||||
const route = target ?? state.routes[state.index];
|
||||
const navigation = descriptors[route.key].navigation;
|
||||
|
||||
return listeners({ route: route as any, navigation })[type];
|
||||
}
|
||||
|
||||
return listeners[type];
|
||||
})
|
||||
.map((type) => map?.[type])
|
||||
: undefined;
|
||||
})
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import shortid from 'shortid';
|
||||
import { nanoid } from 'nanoid/non-secure';
|
||||
import { SingleNavigatorContext } from './EnsureSingleNavigator';
|
||||
|
||||
/**
|
||||
@@ -7,7 +7,7 @@ import { SingleNavigatorContext } from './EnsureSingleNavigator';
|
||||
* This is used to prevent multiple navigators under a single container or screen.
|
||||
*/
|
||||
export default function useRegisterNavigator() {
|
||||
const [key] = React.useState(() => shortid());
|
||||
const [key] = React.useState(() => nanoid());
|
||||
const container = React.useContext(SingleNavigatorContext);
|
||||
|
||||
if (container === undefined) {
|
||||
|
||||
@@ -3,6 +3,30 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.4.0](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.3.4...@react-navigation/drawer@5.4.0) (2020-03-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* disable only swipe gesture on safari ([105da6a](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/105da6ab2fe69847b676c4d4117638212cda1f9a))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add swipeEnabled option to disable swipe gesture in drawer ([#7834](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/7834)) ([ac7f972](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/ac7f972e922a82cd32d943356941d100b68bd8b0))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.3.4](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.3.3...@react-navigation/drawer@5.3.4) (2020-03-23)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/drawer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.3.3](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.3.2...@react-navigation/drawer@5.3.3) (2020-03-22)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/drawer
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/drawer",
|
||||
"description": "Drawer navigator component with animated transitions and gesturess",
|
||||
"version": "5.3.3",
|
||||
"version": "5.4.0",
|
||||
"keywords": [
|
||||
"react-native-component",
|
||||
"react-component",
|
||||
@@ -40,7 +40,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
"@react-navigation/native": "^5.1.2",
|
||||
"@react-navigation/native": "^5.1.4",
|
||||
"@types/react": "^16.9.23",
|
||||
"@types/react-native": "^0.61.22",
|
||||
"del-cli": "^3.0.0",
|
||||
@@ -50,7 +50,7 @@
|
||||
"react-native-reanimated": "^1.7.0",
|
||||
"react-native-safe-area-context": "^0.7.3",
|
||||
"react-native-screens": "^2.3.0",
|
||||
"typescript": "^3.7.5"
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-navigation/native": "^5.0.5",
|
||||
|
||||
@@ -111,9 +111,18 @@ export type DrawerNavigationOptions = {
|
||||
|
||||
/**
|
||||
* Whether you can use gestures to open or close the drawer.
|
||||
* Setting this to `false` disables swipe gestures as well as tap on overlay to close.
|
||||
* See `swipeEnabled` to disable only the swipe gesture.
|
||||
* Defaults to `true`
|
||||
*/
|
||||
gestureEnabled?: boolean;
|
||||
|
||||
/**
|
||||
* Whether you can use swipe gestures to open or close the drawer.
|
||||
* Defaults to `true`
|
||||
*/
|
||||
swipeEnabled?: boolean;
|
||||
|
||||
/**
|
||||
* Whether this screen should be unmounted when navigating away from it.
|
||||
* Defaults to `false`.
|
||||
|
||||
@@ -80,6 +80,7 @@ type Props = {
|
||||
onClose: () => void;
|
||||
onGestureRef?: (ref: PanGestureHandler | null) => void;
|
||||
gestureEnabled: boolean;
|
||||
swipeEnabled: boolean;
|
||||
drawerPosition: 'left' | 'right';
|
||||
drawerType: 'front' | 'back' | 'slide' | 'permanent';
|
||||
keyboardDismissMode: 'none' | 'on-drag';
|
||||
@@ -100,7 +101,7 @@ type Props = {
|
||||
* Disables the pan gesture by default on Apple devices in the browser.
|
||||
* https://stackoverflow.com/a/9039885
|
||||
*/
|
||||
function shouldEnableGesture(): boolean {
|
||||
function shouldEnableSwipeGesture(): boolean {
|
||||
if (
|
||||
Platform.OS === 'web' &&
|
||||
typeof navigator !== 'undefined' &&
|
||||
@@ -115,11 +116,12 @@ function shouldEnableGesture(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
export default class DrawerView extends React.PureComponent<Props> {
|
||||
export default class DrawerView extends React.Component<Props> {
|
||||
static defaultProps = {
|
||||
drawerPostion: I18nManager.isRTL ? 'left' : 'right',
|
||||
drawerType: 'front',
|
||||
gestureEnabled: shouldEnableGesture(),
|
||||
gestureEnabled: true,
|
||||
swipeEnabled: shouldEnableSwipeGesture(),
|
||||
swipeEdgeWidth: 32,
|
||||
swipeVelocityThreshold: 500,
|
||||
keyboardDismissMode: 'on-drag',
|
||||
@@ -138,16 +140,11 @@ export default class DrawerView extends React.PureComponent<Props> {
|
||||
open,
|
||||
drawerPosition,
|
||||
drawerType,
|
||||
gestureEnabled,
|
||||
swipeDistanceThreshold,
|
||||
swipeVelocityThreshold,
|
||||
hideStatusBar,
|
||||
} = this.props;
|
||||
|
||||
if (prevProps.gestureEnabled !== gestureEnabled) {
|
||||
this.isGestureEnabled.setValue(gestureEnabled ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
if (
|
||||
// If we're not in the middle of a transition, sync the drawer's open state
|
||||
typeof this.pendingOpenValue !== 'boolean' ||
|
||||
@@ -223,9 +220,6 @@ export default class DrawerView extends React.PureComponent<Props> {
|
||||
private isDrawerTypeFront = new Value<Binary>(
|
||||
this.props.drawerType === 'front' ? TRUE : FALSE
|
||||
);
|
||||
private isGestureEnabled = new Value(
|
||||
this.props.gestureEnabled ? TRUE : FALSE
|
||||
);
|
||||
|
||||
private isOpen = new Value<Binary>(this.props.open ? TRUE : FALSE);
|
||||
private nextIsOpen = new Value<Binary | -1>(UNSET);
|
||||
@@ -554,6 +548,7 @@ export default class DrawerView extends React.PureComponent<Props> {
|
||||
const {
|
||||
open,
|
||||
gestureEnabled,
|
||||
swipeEnabled,
|
||||
drawerPosition,
|
||||
drawerType,
|
||||
swipeEdgeWidth,
|
||||
@@ -605,7 +600,7 @@ export default class DrawerView extends React.PureComponent<Props> {
|
||||
onGestureEvent={this.handleGestureEvent}
|
||||
onHandlerStateChange={this.handleGestureStateChange}
|
||||
hitSlop={hitSlop}
|
||||
enabled={drawerType !== 'permanent' && gestureEnabled}
|
||||
enabled={drawerType !== 'permanent' && gestureEnabled && swipeEnabled}
|
||||
{...gestureHandlerProps}
|
||||
>
|
||||
<Animated.View
|
||||
|
||||
@@ -200,7 +200,7 @@ export default function DrawerView({
|
||||
};
|
||||
|
||||
const activeKey = state.routes[state.index].key;
|
||||
const { gestureEnabled } = descriptors[activeKey].options;
|
||||
const { gestureEnabled, swipeEnabled } = descriptors[activeKey].options;
|
||||
|
||||
return (
|
||||
<GestureHandlerWrapper style={styles.content}>
|
||||
@@ -210,6 +210,7 @@ export default function DrawerView({
|
||||
<Drawer
|
||||
open={isDrawerOpen}
|
||||
gestureEnabled={gestureEnabled}
|
||||
swipeEnabled={swipeEnabled}
|
||||
onOpen={handleDrawerOpen}
|
||||
onClose={handleDrawerClose}
|
||||
onGestureRef={(ref) => {
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [5.1.7](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.6...@react-navigation/material-bottom-tabs@5.1.7) (2020-03-30)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.1.6](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.5...@react-navigation/material-bottom-tabs@5.1.6) (2020-03-23)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.1.5](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.4...@react-navigation/material-bottom-tabs@5.1.5) (2020-03-22)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/material-bottom-tabs",
|
||||
"description": "Integration for bottom navigation component from react-native-paper",
|
||||
"version": "5.1.5",
|
||||
"version": "5.1.7",
|
||||
"keywords": [
|
||||
"react-native-component",
|
||||
"react-component",
|
||||
@@ -36,7 +36,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
"@react-navigation/native": "^5.1.2",
|
||||
"@react-navigation/native": "^5.1.4",
|
||||
"@types/react": "^16.9.23",
|
||||
"@types/react-native": "^0.61.22",
|
||||
"@types/react-native-vector-icons": "^6.4.5",
|
||||
@@ -45,7 +45,7 @@
|
||||
"react-native": "~0.61.5",
|
||||
"react-native-paper": "^3.6.0",
|
||||
"react-native-vector-icons": "^6.6.0",
|
||||
"typescript": "^3.7.5"
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-navigation/native": "^5.0.5",
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [5.1.7](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.6...@react-navigation/material-top-tabs@5.1.7) (2020-03-30)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.1.6](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.5...@react-navigation/material-top-tabs@5.1.6) (2020-03-23)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.1.5](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.4...@react-navigation/material-top-tabs@5.1.5) (2020-03-22)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/material-top-tabs",
|
||||
"description": "Integration for the animated tab view component from react-native-tab-view",
|
||||
"version": "5.1.5",
|
||||
"version": "5.1.7",
|
||||
"keywords": [
|
||||
"react-native-component",
|
||||
"react-component",
|
||||
@@ -39,7 +39,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
"@react-navigation/native": "^5.1.2",
|
||||
"@react-navigation/native": "^5.1.4",
|
||||
"@types/react": "^16.9.23",
|
||||
"@types/react-native": "^0.61.22",
|
||||
"del-cli": "^3.0.0",
|
||||
@@ -48,7 +48,7 @@
|
||||
"react-native-gesture-handler": "^1.6.0",
|
||||
"react-native-reanimated": "^1.7.0",
|
||||
"react-native-tab-view": "^2.13.0",
|
||||
"typescript": "^3.7.5"
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-navigation/native": "^5.0.5",
|
||||
|
||||
@@ -3,6 +3,25 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [5.1.4](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.1.3...@react-navigation/native@5.1.4) (2020-03-30)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/native
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.1.3](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.1.2...@react-navigation/native@5.1.3) (2020-03-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add info about android launchMode in useLinking error ([d94e43c](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/d94e43c3c8625b209a5c883b8cb560496d07fda7))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.1.2](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.1.1...@react-navigation/native@5.1.2) (2020-03-22)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/native
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/native",
|
||||
"description": "React Native integration for React Navigation",
|
||||
"version": "5.1.2",
|
||||
"version": "5.1.4",
|
||||
"keywords": [
|
||||
"react-native",
|
||||
"react-navigation",
|
||||
@@ -31,7 +31,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/core": "^5.3.0"
|
||||
"@react-navigation/core": "^5.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
@@ -41,7 +41,7 @@
|
||||
"react": "~16.9.0",
|
||||
"react-native": "~0.61.5",
|
||||
"react-native-testing-library": "^1.12.0",
|
||||
"typescript": "^3.7.5"
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { Linking } from 'react-native';
|
||||
import { Linking, Platform } from 'react-native';
|
||||
import {
|
||||
getActionFromState,
|
||||
getStateFromPath as getStateFromPathDefault,
|
||||
@@ -20,7 +20,10 @@ export default function useLinking(
|
||||
React.useEffect(() => {
|
||||
if (isUsingLinking) {
|
||||
throw new Error(
|
||||
"Looks like you are using 'useLinking' in multiple components. This is likely an error since deep links should only be handled in one place to avoid conflicts."
|
||||
"Looks like you are using 'useLinking' in multiple components. This is likely an error since deep links should only be handled in one place to avoid conflicts." +
|
||||
(Platform.OS === 'android'
|
||||
? "\n\nIf you're not using it in multiple components, ensure that you have set 'android:launchMode=singleTask' in the '<activity />' section of the 'AndroidManifest.xml' file to avoid launching multiple activities which run multiple instances of the root component."
|
||||
: '')
|
||||
);
|
||||
} else {
|
||||
isUsingLinking = true;
|
||||
|
||||
@@ -40,7 +40,7 @@ export default function useLinking(
|
||||
React.useEffect(() => {
|
||||
if (isUsingLinking) {
|
||||
throw new Error(
|
||||
"Looks like you are using 'useLinking' in multiple components. This is likely an error since URL integration should only be handled in one place to avoid conflicts."
|
||||
"Looks like you are using 'useLinking' in multiple components. This is likely an error since URL integration should only be handled in one place to avoid conflicts. Also ensure that you set your android activity launchMode to single task in your AndroiManifest.xml file."
|
||||
);
|
||||
} else {
|
||||
isUsingLinking = true;
|
||||
|
||||
@@ -3,6 +3,14 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.2.0...@react-navigation/routers@5.2.1) (2020-03-30)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/routers
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.2.0](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.1.1...@react-navigation/routers@5.2.0) (2020-03-22)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/routers",
|
||||
"description": "Routers to help build custom navigators",
|
||||
"version": "5.2.0",
|
||||
"version": "5.2.1",
|
||||
"keywords": [
|
||||
"react",
|
||||
"react-native",
|
||||
@@ -30,12 +30,12 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"shortid": "^2.2.15"
|
||||
"nanoid": "^3.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
"del-cli": "^3.0.0",
|
||||
"typescript": "^3.7.5"
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"@react-native-community/bob": {
|
||||
"source": "src",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import shortid from 'shortid';
|
||||
import { nanoid } from 'nanoid/non-secure';
|
||||
import { CommonNavigationAction, NavigationState, PartialState } from './types';
|
||||
|
||||
/**
|
||||
@@ -55,9 +55,7 @@ const BaseRouter = {
|
||||
return {
|
||||
...nextState,
|
||||
routes: nextState.routes.map((route) =>
|
||||
route.key
|
||||
? route
|
||||
: { ...route, key: `${route.name}-${shortid()}` }
|
||||
route.key ? route : { ...route, key: `${route.name}-${nanoid()}` }
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import shortid from 'shortid';
|
||||
import { nanoid } from 'nanoid/non-secure';
|
||||
import {
|
||||
PartialState,
|
||||
CommonNavigationAction,
|
||||
@@ -115,7 +115,7 @@ export default function DrawerRouter(
|
||||
...state,
|
||||
stale: false,
|
||||
type: 'drawer',
|
||||
key: `drawer-${shortid()}`,
|
||||
key: `drawer-${nanoid()}`,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -136,7 +136,7 @@ export default function DrawerRouter(
|
||||
return {
|
||||
...state,
|
||||
type: 'drawer',
|
||||
key: `drawer-${shortid()}`,
|
||||
key: `drawer-${nanoid()}`,
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import shortid from 'shortid';
|
||||
import { nanoid } from 'nanoid/non-secure';
|
||||
import BaseRouter from './BaseRouter';
|
||||
import {
|
||||
NavigationState,
|
||||
@@ -113,12 +113,12 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
return {
|
||||
stale: false,
|
||||
type: 'stack',
|
||||
key: `stack-${shortid()}`,
|
||||
key: `stack-${nanoid()}`,
|
||||
index: 0,
|
||||
routeNames,
|
||||
routes: [
|
||||
{
|
||||
key: `${initialRouteName}-${shortid()}`,
|
||||
key: `${initialRouteName}-${nanoid()}`,
|
||||
name: initialRouteName,
|
||||
params: routeParamList[initialRouteName],
|
||||
},
|
||||
@@ -139,7 +139,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
(route) =>
|
||||
({
|
||||
...route,
|
||||
key: route.key || `${route.name}-${shortid()}`,
|
||||
key: route.key || `${route.name}-${nanoid()}`,
|
||||
params:
|
||||
routeParamList[route.name] !== undefined
|
||||
? {
|
||||
@@ -157,7 +157,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
: routeNames[0];
|
||||
|
||||
routes.push({
|
||||
key: `${initialRouteName}-${shortid()}`,
|
||||
key: `${initialRouteName}-${nanoid()}`,
|
||||
name: initialRouteName,
|
||||
params: routeParamList[initialRouteName],
|
||||
});
|
||||
@@ -166,7 +166,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
return {
|
||||
stale: false,
|
||||
type: 'stack',
|
||||
key: `stack-${shortid()}`,
|
||||
key: `stack-${nanoid()}`,
|
||||
index: routes.length - 1,
|
||||
routeNames,
|
||||
routes,
|
||||
@@ -186,7 +186,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
: routeNames[0];
|
||||
|
||||
routes.push({
|
||||
key: `${initialRouteName}-${shortid()}`,
|
||||
key: `${initialRouteName}-${nanoid()}`,
|
||||
name: initialRouteName,
|
||||
params: routeParamList[initialRouteName],
|
||||
});
|
||||
@@ -238,7 +238,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
routes: state.routes.map((route, i) =>
|
||||
i === index
|
||||
? {
|
||||
key: key !== undefined ? key : `${name}-${shortid()}`,
|
||||
key: key !== undefined ? key : `${name}-${nanoid()}`,
|
||||
name,
|
||||
params:
|
||||
routeParamList[name] !== undefined
|
||||
@@ -263,7 +263,7 @@ export default function StackRouter(options: StackRouterOptions) {
|
||||
{
|
||||
key:
|
||||
action.payload.key === undefined
|
||||
? `${action.payload.name}-${shortid()}`
|
||||
? `${action.payload.name}-${nanoid()}`
|
||||
: action.payload.key,
|
||||
name: action.payload.name,
|
||||
params:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import shortid from 'shortid';
|
||||
import { nanoid } from 'nanoid/non-secure';
|
||||
import BaseRouter from './BaseRouter';
|
||||
import {
|
||||
NavigationState,
|
||||
@@ -126,7 +126,7 @@ export default function TabRouter({
|
||||
|
||||
const routes = routeNames.map((name) => ({
|
||||
name,
|
||||
key: `${name}-${shortid()}`,
|
||||
key: `${name}-${nanoid()}`,
|
||||
params: routeParamList[name],
|
||||
}));
|
||||
|
||||
@@ -135,7 +135,7 @@ export default function TabRouter({
|
||||
return {
|
||||
stale: false,
|
||||
type: 'tab',
|
||||
key: `tab-${shortid()}`,
|
||||
key: `tab-${nanoid()}`,
|
||||
index,
|
||||
routeNames,
|
||||
history,
|
||||
@@ -161,7 +161,7 @@ export default function TabRouter({
|
||||
key:
|
||||
route && route.name === name && route.key
|
||||
? route.key
|
||||
: `${name}-${shortid()}`,
|
||||
: `${name}-${nanoid()}`,
|
||||
params:
|
||||
routeParamList[name] !== undefined
|
||||
? {
|
||||
@@ -195,7 +195,7 @@ export default function TabRouter({
|
||||
return {
|
||||
stale: false,
|
||||
type: 'tab',
|
||||
key: `tab-${shortid()}`,
|
||||
key: `tab-${nanoid()}`,
|
||||
index,
|
||||
routeNames,
|
||||
history,
|
||||
@@ -208,7 +208,7 @@ export default function TabRouter({
|
||||
(name) =>
|
||||
state.routes.find((r) => r.name === name) || {
|
||||
name,
|
||||
key: `${name}-${shortid()}`,
|
||||
key: `${name}-${nanoid()}`,
|
||||
params: routeParamList[name],
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import BaseRouter from '../BaseRouter';
|
||||
import * as CommonActions from '../CommonActions';
|
||||
|
||||
jest.mock('shortid', () => () => 'test');
|
||||
jest.mock('nanoid/non-secure', () => ({ nanoid: () => 'test' }));
|
||||
|
||||
const STATE = {
|
||||
stale: false as const,
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
DrawerNavigationState,
|
||||
} from '..';
|
||||
|
||||
jest.mock('shortid', () => () => 'test');
|
||||
jest.mock('nanoid/non-secure', () => ({ nanoid: () => 'test' }));
|
||||
|
||||
it('gets initial state from route names and params with initialRouteName', () => {
|
||||
const router = DrawerRouter({ initialRouteName: 'baz' });
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CommonActions, StackRouter, StackActions } from '..';
|
||||
|
||||
jest.mock('shortid', () => () => 'test');
|
||||
jest.mock('nanoid/non-secure', () => ({ nanoid: () => 'test' }));
|
||||
|
||||
it('gets initial state from route names and params with initialRouteName', () => {
|
||||
const router = StackRouter({ initialRouteName: 'baz' });
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CommonActions, TabRouter, TabActions, TabNavigationState } from '..';
|
||||
|
||||
jest.mock('shortid', () => () => 'test');
|
||||
jest.mock('nanoid/non-secure', () => ({ nanoid: () => 'test' }));
|
||||
|
||||
it('gets initial state from route names and params with initialRouteName', () => {
|
||||
const router = TabRouter({ initialRouteName: 'baz' });
|
||||
|
||||
@@ -3,6 +3,49 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [5.2.9](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.8...@react-navigation/stack@5.2.9) (2020-03-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* dismiss keyboard on screen change for android ([8432e5a](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/8432e5ab25f041af8538ea7fb35e97cfcf1f983e))
|
||||
* finish stack animation on CANCELLED event ([#7898](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/7898)) ([d649fbc](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/d649fbc6691871f0348076bce185d11a183c02cf)), closes [#7897](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/7897)
|
||||
* when comparing changed routes, only check keys ([9a8fea8](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/9a8fea8f2c1bdabfc5dd87e5c3ff4e7b97aef47d))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.2.7](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.6...@react-navigation/stack@5.2.7) (2020-03-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add pointerEvents=box-none to overlay View ([#7871](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/7871)) ([e097df8](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/e097df880adab984aae29f847003d2548cfbdce5))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.2.6](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.5...@react-navigation/stack@5.2.6) (2020-03-23)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/stack
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.2.5](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.4...@react-navigation/stack@5.2.5) (2020-03-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix swipe gestures requiring a lot of velocity to dismiss ([61f16d3](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/61f16d3f25cbbcc00d699dd09c5f4abde9b17d5a))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.2.4](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.3...@react-navigation/stack@5.2.4) (2020-03-22)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/stack",
|
||||
"description": "Stack navigator component for iOS and Android with animated transitions and gestures",
|
||||
"version": "5.2.4",
|
||||
"version": "5.2.9",
|
||||
"keywords": [
|
||||
"react-native-component",
|
||||
"react-component",
|
||||
@@ -40,7 +40,7 @@
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.10.0",
|
||||
"@react-native-community/masked-view": "^0.1.7",
|
||||
"@react-navigation/native": "^5.1.2",
|
||||
"@react-navigation/native": "^5.1.4",
|
||||
"@types/color": "^3.0.1",
|
||||
"@types/react": "^16.9.23",
|
||||
"@types/react-native": "^0.61.22",
|
||||
@@ -50,7 +50,7 @@
|
||||
"react-native-gesture-handler": "^1.6.0",
|
||||
"react-native-safe-area-context": "^0.7.3",
|
||||
"react-native-screens": "^2.3.0",
|
||||
"typescript": "^3.7.5"
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@react-native-community/masked-view": ">= 0.1.0",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { TextInput } from 'react-native';
|
||||
import { TextInput, Platform, Keyboard } from 'react-native';
|
||||
|
||||
type Props = {
|
||||
enabled: boolean;
|
||||
@@ -56,7 +56,9 @@ export default class KeyboardManager extends React.Component<Props> {
|
||||
|
||||
const input = this.previouslyFocusedTextInput;
|
||||
|
||||
if (input) {
|
||||
if (Platform.OS === 'android') {
|
||||
Keyboard.dismiss();
|
||||
} else if (input) {
|
||||
TextInput.State.blurTextInput(input);
|
||||
}
|
||||
|
||||
|
||||
@@ -246,11 +246,21 @@ export default class Card extends React.Component<Props> {
|
||||
this.handleStartInteraction();
|
||||
onGestureBegin?.();
|
||||
break;
|
||||
case GestureState.CANCELLED:
|
||||
case GestureState.CANCELLED: {
|
||||
this.isSwiping.setValue(FALSE);
|
||||
this.handleEndInteraction();
|
||||
|
||||
const velocity =
|
||||
gestureDirection === 'vertical' ||
|
||||
gestureDirection === 'vertical-inverted'
|
||||
? nativeEvent.velocityY
|
||||
: nativeEvent.velocityX;
|
||||
|
||||
this.animate({ closing: this.props.closing, velocity });
|
||||
|
||||
onGestureCanceled?.();
|
||||
break;
|
||||
}
|
||||
case GestureState.END: {
|
||||
this.isSwiping.setValue(FALSE);
|
||||
|
||||
@@ -272,8 +282,7 @@ export default class Card extends React.Component<Props> {
|
||||
}
|
||||
|
||||
const closing =
|
||||
(translation + velocity) *
|
||||
gestureVelocityImpact *
|
||||
(translation + velocity * gestureVelocityImpact) *
|
||||
getInvertedMultiplier(gestureDirection) >
|
||||
distance / 2
|
||||
? velocity !== 0 || translation !== 0
|
||||
@@ -481,7 +490,7 @@ export default class Card extends React.Component<Props> {
|
||||
<CardAnimationContext.Provider value={animationContext}>
|
||||
<View pointerEvents="box-none" {...rest}>
|
||||
{overlayEnabled ? (
|
||||
<View style={StyleSheet.absoluteFill}>
|
||||
<View pointerEvents="box-none" style={StyleSheet.absoluteFill}>
|
||||
{overlay({ style: overlayStyle })}
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
@@ -46,31 +46,63 @@ type State = {
|
||||
|
||||
const GestureHandlerWrapper = GestureHandlerRootView ?? View;
|
||||
|
||||
/**
|
||||
* Compare two arrays with primitive values as the content.
|
||||
* We need to make sure that both values and order match.
|
||||
*/
|
||||
const isArrayEqual = (a: any[], b: any[]) =>
|
||||
a.length === b.length && a.every((it, index) => it === b[index]);
|
||||
|
||||
export default class StackView extends React.Component<Props, State> {
|
||||
static getDerivedStateFromProps(
|
||||
props: Readonly<Props>,
|
||||
state: Readonly<State>
|
||||
) {
|
||||
// If there was no change in routes, we don't need to compute anything
|
||||
if (props.state.routes === state.previousRoutes && state.routes.length) {
|
||||
if (props.descriptors !== state.previousDescriptors) {
|
||||
const descriptors = state.routes.reduce<StackDescriptorMap>(
|
||||
(acc, route) => {
|
||||
acc[route.key] =
|
||||
props.descriptors[route.key] || state.descriptors[route.key];
|
||||
if (
|
||||
(props.state.routes === state.previousRoutes ||
|
||||
isArrayEqual(
|
||||
props.state.routes.map((r) => r.key),
|
||||
state.previousRoutes.map((r) => r.key)
|
||||
)) &&
|
||||
state.routes.length
|
||||
) {
|
||||
let routes = state.routes;
|
||||
let previousRoutes = state.previousRoutes;
|
||||
let descriptors = props.descriptors;
|
||||
let previousDescriptors = state.previousDescriptors;
|
||||
|
||||
if (props.descriptors !== state.previousDescriptors) {
|
||||
descriptors = state.routes.reduce<StackDescriptorMap>((acc, route) => {
|
||||
acc[route.key] =
|
||||
props.descriptors[route.key] || state.descriptors[route.key];
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
previousDescriptors = props.descriptors;
|
||||
}
|
||||
|
||||
if (props.state.routes !== state.previousRoutes) {
|
||||
// if any route objects have changed, we should update them
|
||||
const map = props.state.routes.reduce<Record<string, Route<string>>>(
|
||||
(acc, route) => {
|
||||
acc[route.key] = route;
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
|
||||
return {
|
||||
previousDescriptors: props.descriptors,
|
||||
descriptors,
|
||||
};
|
||||
routes = state.routes.map((route) => map[route.key] || route);
|
||||
previousRoutes = props.state.routes;
|
||||
}
|
||||
|
||||
return null;
|
||||
return {
|
||||
routes,
|
||||
previousRoutes,
|
||||
descriptors,
|
||||
previousDescriptors,
|
||||
};
|
||||
}
|
||||
|
||||
// Here we determine which routes were added or removed to animate them
|
||||
|
||||
Reference in New Issue
Block a user