Compare commits

...

20 Commits

Author SHA1 Message Date
Satyajit Sahoo
9556aa9eff chore: publish
- @react-navigation/bottom-tabs@5.2.5
 - @react-navigation/compat@5.1.7
 - @react-navigation/core@5.3.2
 - @react-navigation/drawer@5.4.0
 - @react-navigation/material-bottom-tabs@5.1.7
 - @react-navigation/material-top-tabs@5.1.7
 - @react-navigation/native@5.1.4
 - @react-navigation/routers@5.2.1
 - @react-navigation/stack@5.2.9
2020-03-30 22:22:25 +02:00
Satyajit Sahoo
9a8fea8f2c fix: when comparing changed routes, only check keys 2020-03-30 22:20:16 +02:00
Satyajit Sahoo
9973db86f0 chore: use non-secure nanoid to be able to run in RN 2020-03-30 22:04:53 +02:00
max
8432e5ab25 fix: dismiss keyboard on screen change for android 2020-03-30 21:50:52 +02:00
Satyajit Sahoo
9bb5cfded3 refactor: replace shortid with nanoid. closes #7858 2020-03-30 21:42:58 +02:00
Satyajit Sahoo
4ac40b5c5d chore: update typescript and babel 2020-03-30 21:42:58 +02:00
Wojciech Lewicki
cd47915861 fix: handle no path property and undefined query params (#7911) 2020-03-30 17:11:33 +02:00
Andrius Janauskas
d649fbc669 fix: finish stack animation on CANCELLED event (#7898)
fixes #7897
2020-03-30 14:36:04 +02:00
Satyajit Sahoo
105da6ab2f fix: disable only swipe gesture on safari 2020-03-30 13:56:30 +02:00
Rajendran Nadar
ac7f972e92 feat: add swipeEnabled option to disable swipe gesture in drawer (#7834) 2020-03-30 13:51:32 +02:00
Satyajit Sahoo
babb5027f9 chore: publish
- @react-navigation/stack@5.2.8
2020-03-27 15:01:32 +01:00
Satyajit Sahoo
78d7a66b2b chore: remove detox dep coz we don't use it 2020-03-27 14:54:54 +01:00
osdnk
a248c453ba chore: publish
- @react-navigation/stack@5.2.7
2020-03-26 17:07:40 +01:00
Wojciech Stanisz
e097df880a fix: add pointerEvents=box-none to overlay View (#7871) 2020-03-26 13:38:30 +01:00
Satyajit Sahoo
856449b200 chore: publish
- @react-navigation/bottom-tabs@5.2.4
 - @react-navigation/compat@5.1.6
 - @react-navigation/core@5.3.1
 - @react-navigation/drawer@5.3.4
 - @react-navigation/material-bottom-tabs@5.1.6
 - @react-navigation/material-top-tabs@5.1.6
 - @react-navigation/native@5.1.3
 - @react-navigation/stack@5.2.6
2020-03-23 17:07:43 +01:00
Steven Bell
d94e43c3c8 fix: add info about android launchMode in useLinking error 2020-03-23 16:39:18 +01:00
Satyajit Sahoo
3096de6286 fix: only call listeners for focused screen for global events 2020-03-23 13:43:43 +01:00
Satyajit Sahoo
1c001424b5 fix: don't emit events for screens that don't exist anymore 2020-03-23 13:03:33 +01:00
Satyajit Sahoo
0f2368965c chore: publish
- @react-navigation/stack@5.2.5
2020-03-23 11:42:01 +01:00
Satyajit Sahoo
61f16d3f25 fix: fix swipe gestures requiring a lot of velocity to dismiss 2020-03-23 11:40:37 +01:00
43 changed files with 4140 additions and 3141 deletions

View File

@@ -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;

View File

@@ -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"
}
}

View File

@@ -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",

View File

@@ -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

View File

@@ -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",

View File

@@ -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

View File

@@ -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",

View File

@@ -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)

View File

@@ -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": "*"

View File

@@ -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);
});

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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;
})
)

View File

@@ -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) {

View File

@@ -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

View File

@@ -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",

View File

@@ -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`.

View File

@@ -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

View File

@@ -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) => {

View File

@@ -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

View File

@@ -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",

View File

@@ -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

View File

@@ -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",

View File

@@ -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

View File

@@ -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": "*",

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)

View File

@@ -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",

View File

@@ -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()}` }
),
};
}

View File

@@ -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()}`,
};
},

View File

@@ -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:

View File

@@ -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],
}
);

View File

@@ -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,

View File

@@ -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' });

View File

@@ -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' });

View File

@@ -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' });

View File

@@ -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)

View File

@@ -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",

View File

@@ -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);
}

View File

@@ -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}

View File

@@ -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

6482
yarn.lock

File diff suppressed because it is too large Load Diff