Compare commits

...

6 Commits

Author SHA1 Message Date
Satyajit Sahoo
68a334cc93 chore: publish
- @react-navigation/bottom-tabs@5.0.0-alpha.27
 - @react-navigation/compat@5.0.0-alpha.18
 - @react-navigation/core@5.0.0-alpha.28
 - @react-navigation/drawer@5.0.0-alpha.29
 - @react-navigation/material-bottom-tabs@5.0.0-alpha.26
 - @react-navigation/material-top-tabs@5.0.0-alpha.24
 - @react-navigation/native-stack@5.0.0-alpha.18
 - @react-navigation/native@5.0.0-alpha.20
 - @react-navigation/routers@5.0.0-alpha.17
 - @react-navigation/stack@5.0.0-alpha.45
2019-12-16 15:27:11 +01:00
Satyajit Sahoo
c110570d4c fix: disable style interpolation for card when animation is disabled 2019-12-16 15:25:19 +01:00
Satyajit Sahoo
d57226fd8b refactor: remove cardTransparent in favor of cardStyle 2019-12-16 15:09:10 +01:00
Oliver Winter
c3d3748143 fix: use Partial type for initialParam (#206) 2019-12-16 13:58:37 +01:00
Wojciech Lewicki
8002d51795 feat: add nested config in deep linking (#210)
Fixes #154
2019-12-16 13:30:28 +01:00
Erivelton Elias
31cf19912b chore: update README expo and native-stack (#212) 2019-12-16 12:29:31 +01:00
30 changed files with 558 additions and 100 deletions

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.0.0-alpha.27](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/bottom-tabs@5.0.0-alpha.26...@react-navigation/bottom-tabs@5.0.0-alpha.27) (2019-12-16)
**Note:** Version bump only for package @react-navigation/bottom-tabs
# [5.0.0-alpha.26](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/bottom-tabs@5.0.0-alpha.25...@react-navigation/bottom-tabs@5.0.0-alpha.26) (2019-12-14)

View File

@@ -10,7 +10,7 @@
"android",
"tab"
],
"version": "5.0.0-alpha.26",
"version": "5.0.0-alpha.27",
"license": "MIT",
"repository": {
"type": "git",
@@ -33,7 +33,7 @@
"clean": "del lib"
},
"dependencies": {
"@react-navigation/routers": "^5.0.0-alpha.16",
"@react-navigation/routers": "^5.0.0-alpha.17",
"color": "^3.1.2"
},
"devDependencies": {

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.0.0-alpha.18](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/compat@5.0.0-alpha.17...@react-navigation/compat@5.0.0-alpha.18) (2019-12-16)
**Note:** Version bump only for package @react-navigation/compat
# [5.0.0-alpha.17](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/compat@5.0.0-alpha.16...@react-navigation/compat@5.0.0-alpha.17) (2019-12-11)
**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.0.0-alpha.17",
"version": "5.0.0-alpha.18",
"license": "MIT",
"repository": {
"type": "git",
@@ -24,7 +24,7 @@
"clean": "del lib"
},
"dependencies": {
"@react-navigation/routers": "^5.0.0-alpha.16"
"@react-navigation/routers": "^5.0.0-alpha.17"
},
"devDependencies": {
"@types/react": "^16.9.11",

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.0.0-alpha.28](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/core@5.0.0-alpha.27...@react-navigation/core@5.0.0-alpha.28) (2019-12-16)
### Bug Fixes
* use Partial type for initialParam ([#206](https://github.com/react-navigation/navigation-ex/issues/206)) ([c3d3748](https://github.com/react-navigation/navigation-ex/commit/c3d374814308b0bd6d259099444f0f24593f4d7e))
### Features
* add nested config in deep linking ([#210](https://github.com/react-navigation/navigation-ex/issues/210)) ([8002d51](https://github.com/react-navigation/navigation-ex/commit/8002d5179524a7211c37760a4ed45e8c12af4358)), closes [#154](https://github.com/react-navigation/navigation-ex/issues/154)
# [5.0.0-alpha.27](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/core@5.0.0-alpha.26...@react-navigation/core@5.0.0-alpha.27) (2019-12-10)
**Note:** Version bump only for package @react-navigation/core

View File

@@ -6,7 +6,7 @@
"react-native",
"react-navigation"
],
"version": "5.0.0-alpha.27",
"version": "5.0.0-alpha.28",
"license": "MIT",
"repository": {
"type": "git",

View File

@@ -127,3 +127,238 @@ it('handles route without param', () => {
it('returns undefined for invalid path', () => {
expect(getStateFromPath('//')).toBe(undefined);
});
it('converts path string to initial state with config with nested screens', () => {
expect(
getStateFromPath(
'/few/bar/sweet/apple/baz/jane?count=10&answer=42&valid=true',
{
Foo: {
Foe: 'few',
},
Bar: 'bar/:type/:fruit',
Baz: {
path: 'baz/:author',
parse: {
author: (author: string) =>
author.replace(/^\w/, c => c.toUpperCase()),
count: Number,
valid: Boolean,
},
},
}
)
).toEqual({
routes: [
{
name: 'Foo',
state: {
routes: [
{
name: 'Foe',
state: {
routes: [
{
name: 'Bar',
params: { fruit: 'apple', type: 'sweet' },
state: {
routes: [
{
name: 'Baz',
params: {
author: 'Jane',
count: 10,
answer: '42',
valid: true,
},
},
],
},
},
],
},
},
],
},
},
],
});
});
it('converts path string to initial state with config with nested screens and unused configs', () => {
expect(
getStateFromPath('/few/baz/jane?count=10&answer=42&valid=true', {
Foo: {
Foe: 'few',
},
Baz: {
path: 'baz/:author',
parse: {
author: (author: string) =>
author.replace(/^\w/, c => c.toUpperCase()),
count: Number,
valid: Boolean,
},
},
})
).toEqual({
routes: [
{
name: 'Foo',
state: {
routes: [
{
name: 'Foe',
state: {
routes: [
{
name: 'Baz',
params: {
author: 'Jane',
count: 10,
answer: '42',
valid: true,
},
},
],
},
},
],
},
},
],
});
});
it('handles parse in nested object with parse in it', () => {
expect(
getStateFromPath(
'/bar/sweet/apple/few/bis/jane?count=10&answer=42&valid=true',
{
Foo: {
Foe: 'few',
},
Bar: 'bar/:type/:fruit',
Baz: {
Bis: {
path: 'bis/:author',
parse: {
author: (author: string) =>
author.replace(/^\w/, c => c.toUpperCase()),
count: Number,
valid: Boolean,
},
},
},
}
)
).toEqual({
routes: [
{
name: 'Bar',
params: { fruit: 'apple', type: 'sweet' },
state: {
routes: [
{
name: 'Foo',
state: {
routes: [
{
name: 'Foe',
state: {
routes: [
{
name: 'Baz',
state: {
routes: [
{
name: 'Bis',
params: {
author: 'Jane',
count: 10,
answer: '42',
valid: true,
},
},
],
},
},
],
},
},
],
},
},
],
},
},
],
});
});
it('handles parse in nested object for second route depth', () => {
expect(
getStateFromPath('/baz', {
Foo: {
path: 'foo',
Foe: 'foe',
Bar: {
Baz: 'baz',
},
},
})
).toEqual({
routes: [
{
name: 'Foo',
state: {
routes: [
{
name: 'Bar',
state: {
routes: [{ name: 'Baz' }],
},
},
],
},
},
],
});
});
it('handles parse in nested object for second route depth and and path and parse in roots', () => {
expect(
getStateFromPath('/baz', {
Foo: {
path: 'foo/:id',
parse: {
id: Number,
},
Foe: 'foe',
Bar: {
path: 'bar/:id',
parse: {
id: Number,
},
Baz: 'baz',
},
},
})
).toEqual({
routes: [
{
name: 'Foo',
state: {
routes: [
{
name: 'Bar',
state: {
routes: [{ name: 'Baz' }],
},
},
],
},
},
],
});
});

View File

@@ -1,11 +1,18 @@
import escape from 'escape-string-regexp';
import queryString from 'query-string';
import { NavigationState, PartialState } from './types';
import { NavigationState, PartialState, InitialState } from './types';
type ParseConfig = Record<string, (value: string) => any>;
type Options = {
[routeName: string]: string | { path: string; parse?: ParseConfig };
[routeName: string]: string | { path: string; parse?: ParseConfig } | Options;
};
type RouteConfig = {
match: RegExp;
pattern: string;
routeNames: string[];
parse: Record<string, (value: string) => any> | undefined;
};
/**
@@ -31,27 +38,10 @@ export default function getStateFromPath(
path: string,
options: Options = {}
): PartialState<NavigationState> | undefined {
// Create a normalized config array which will be easier to use
const routeConfig = Object.keys(options).map(key => {
const pattern =
typeof options[key] === 'string'
? (options[key] as string)
: (options[key] as { path: string }).path;
// Create a regex from the provided path pattern
// With the pattern, we can match segements containing params and extract them
const match = new RegExp(
'^' + escape(pattern).replace(/:[a-z0-9]+/gi, '([^/]+)') + '/?'
);
return {
match,
pattern,
routeName: key,
// @ts-ignore
parse: options[key].parse,
};
});
// Create a normalized configs array which will be easier to use
const configs = ([] as RouteConfig[]).concat(
...Object.keys(options).map(key => createNormalizedConfigs(key, options))
);
let result: PartialState<NavigationState> | undefined;
let current: PartialState<NavigationState> | undefined;
@@ -62,16 +52,16 @@ export default function getStateFromPath(
.replace(/\?.*/, ''); // Remove query params which we will handle later
while (remaining) {
let routeName;
let routeNames;
let params;
// Go through all configs, and see if the next path segment matches our regex
for (const config of routeConfig) {
for (const config of configs) {
const match = remaining.match(config.match);
// If our regex matches, we need to extract params from the path
if (match) {
routeName = config.routeName;
routeNames = config.routeNames;
const paramPatterns = config.pattern
.split('/')
@@ -99,20 +89,54 @@ export default function getStateFromPath(
}
// If we hadn't matched any segments earlier, use the path as route name
if (routeName === undefined) {
if (routeNames === undefined) {
const segments = remaining.split('/');
routeName = decodeURIComponent(segments[0]);
routeNames = [decodeURIComponent(segments[0])];
segments.shift();
remaining = segments.join('/');
}
const state = {
routes: [{ name: routeName, params }],
};
let state: InitialState;
if (routeNames.length === 1) {
state = {
routes: [
{ name: routeNames.shift() as string, ...(params && { params }) },
],
};
} else {
state = {
routes: [{ name: routeNames.shift() as string, state: { routes: [] } }],
};
let helper = state.routes[0].state as InitialState;
let routeName;
while ((routeName = routeNames.shift())) {
if (routeNames.length === 0) {
helper.routes.push({
name: routeName,
...(params && { params }),
});
} else {
helper.routes[0] = {
name: routeName,
state: {
routes: [],
},
};
helper = helper.routes[0].state as InitialState;
}
}
}
if (current) {
// The state should be nested inside the route we parsed before
// The state should be nested inside the deepest route we parsed before
while (current.routes[0].state) {
current = current.routes[0].state;
}
current.routes[0].state = state;
} else {
result = state;
@@ -128,17 +152,20 @@ export default function getStateFromPath(
const query = path.split('?')[1];
if (query) {
while (current.routes[0].state) {
// The query params apply to the deepest route
current = current.routes[0].state;
}
const route = current.routes[0];
const params = queryString.parse(query);
const config = options[route.name]
? (options[route.name] as { parse?: ParseConfig }).parse
: undefined;
const parseFunction = findParseConfigForRoute(route.name, options);
if (config) {
if (parseFunction) {
Object.keys(params).forEach(name => {
if (config[name] && typeof params[name] === 'string') {
params[name] = config[name](params[name] as string);
if (parseFunction[name] && typeof params[name] === 'string') {
params[name] = parseFunction[name](params[name] as string);
}
});
}
@@ -148,3 +175,89 @@ export default function getStateFromPath(
return result;
}
function createNormalizedConfigs(
key: string,
routeConfig: Options,
routeNames: string[] = []
): RouteConfig[] {
const configs = [];
routeNames.push(key);
const value = routeConfig[key];
if (typeof value === 'string') {
// If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern
configs.push(createConfigItem(routeNames, value));
} else if (typeof value === 'object') {
// if an object is specified as the value (e.g. Foo: { ... }),
// it could have config object and optionally nested config
Object.keys(value).forEach(nestedKey => {
if (nestedKey === 'path') {
configs.push(
createConfigItem(
routeNames,
value[nestedKey] as string,
value.parse ? (value.parse as ParseConfig) : undefined
)
);
} else if (nestedKey === 'parse') {
// We handle custom parse function when a `path` is specified (in nestedKey === path)
} else {
// If the name of the key is not `path` or `parse`, it's a nested config for route
// So we need to traverse into it and collect the configs
const result = createNormalizedConfigs(
nestedKey,
routeConfig[key] as Options,
routeNames
);
configs.push(...result);
}
});
}
routeNames.pop();
return configs;
}
function createConfigItem(
routeNames: string[],
pattern: string,
parse?: ParseConfig
): RouteConfig {
const match = new RegExp(
'^' + escape(pattern).replace(/:[a-z0-9]+/gi, '([^/]+)') + '/?'
);
return {
match,
pattern,
// The routeNames array is mutated, so copy it to keep the current state
routeNames: [...routeNames],
parse,
};
}
function findParseConfigForRoute(
routeName: string,
config: Options
): ParseConfig | undefined {
if (config[routeName]) {
return (config[routeName] as { parse?: ParseConfig }).parse;
}
for (const name in config) {
if (typeof config[name] === 'object') {
const parse = findParseConfigForRoute(routeName, config[name] as Options);
if (parse) {
return parse;
}
}
}
return undefined;
}

View File

@@ -533,7 +533,7 @@ export type RouteConfig<
/**
* Initial params object for the route.
*/
initialParams?: ParamList[RouteName];
initialParams?: Partial<ParamList[RouteName]>;
} & (
| {
/**

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.0.0-alpha.29](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/drawer@5.0.0-alpha.28...@react-navigation/drawer@5.0.0-alpha.29) (2019-12-16)
**Note:** Version bump only for package @react-navigation/drawer
# [5.0.0-alpha.28](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/drawer@5.0.0-alpha.27...@react-navigation/drawer@5.0.0-alpha.28) (2019-12-14)

View File

@@ -11,7 +11,7 @@
"material",
"drawer"
],
"version": "5.0.0-alpha.28",
"version": "5.0.0-alpha.29",
"license": "MIT",
"repository": {
"type": "git",
@@ -34,7 +34,7 @@
"clean": "del lib"
},
"dependencies": {
"@react-navigation/routers": "^5.0.0-alpha.16",
"@react-navigation/routers": "^5.0.0-alpha.17",
"color": "^3.1.2"
},
"devDependencies": {

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.0.0-alpha.26](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/material-bottom-tabs@5.0.0-alpha.25...@react-navigation/material-bottom-tabs@5.0.0-alpha.26) (2019-12-16)
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
# [5.0.0-alpha.25](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/material-bottom-tabs@5.0.0-alpha.24...@react-navigation/material-bottom-tabs@5.0.0-alpha.25) (2019-12-14)

View File

@@ -11,7 +11,7 @@
"material",
"tab"
],
"version": "5.0.0-alpha.25",
"version": "5.0.0-alpha.26",
"license": "MIT",
"repository": {
"type": "git",
@@ -34,7 +34,7 @@
"clean": "del lib"
},
"dependencies": {
"@react-navigation/routers": "^5.0.0-alpha.16"
"@react-navigation/routers": "^5.0.0-alpha.17"
},
"devDependencies": {
"@react-native-community/bob": "^0.7.0",

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.0.0-alpha.24](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/material-top-tabs@5.0.0-alpha.23...@react-navigation/material-top-tabs@5.0.0-alpha.24) (2019-12-16)
**Note:** Version bump only for package @react-navigation/material-top-tabs
# [5.0.0-alpha.23](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/material-top-tabs@5.0.0-alpha.22...@react-navigation/material-top-tabs@5.0.0-alpha.23) (2019-12-14)

View File

@@ -11,7 +11,7 @@
"material",
"tab"
],
"version": "5.0.0-alpha.23",
"version": "5.0.0-alpha.24",
"license": "MIT",
"repository": {
"type": "git",
@@ -34,7 +34,7 @@
"clean": "del lib"
},
"dependencies": {
"@react-navigation/routers": "^5.0.0-alpha.16",
"@react-navigation/routers": "^5.0.0-alpha.17",
"color": "^3.1.2"
},
"devDependencies": {

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.0.0-alpha.18](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/native-stack@5.0.0-alpha.17...@react-navigation/native-stack@5.0.0-alpha.18) (2019-12-16)
**Note:** Version bump only for package @react-navigation/native-stack
# [5.0.0-alpha.17](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/native-stack@5.0.0-alpha.16...@react-navigation/native-stack@5.0.0-alpha.17) (2019-12-14)

View File

@@ -2,7 +2,7 @@
Stack navigator for React Native using native primitives for navigation. Uses [`react-native-screens`](https://github.com/kmagiera/react-native-screens) under the hood.
Expo is currently not supported as it includes an older version of `react-native-screens`.
Expo SDK 35 and lower is not supported as it includes an older version of `react-native-screens`.
## Installation
@@ -11,12 +11,30 @@ Open a Terminal in your project's folder and run,
```sh
yarn add @react-navigation/native @react-navigation/native-stack
```
Or with npm
Now we need to install [`react-native-screens`](https://github.com/kmagiera/react-native-screens).
```sh
npm install --save @react-navigation/native @react-navigation/native-stack
```
If you are using Expo, to ensure that you get the compatible versions of the libraries, run:
```sh
expo install react-native-screens
```
If you are not using Expo, run the following:
```sh
yarn add react-native-screens
```
Or with npm
```sh
npm install --save react-native-screens
```
If you are using Expo, you are done. Otherwise, continue to the next steps.
To complete the linking on iOS, make sure you have [Cocoapods](https://cocoapods.org/) installed. Then run:
@@ -36,9 +54,9 @@ implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha02'
Make sure to enable `react-native-screens`. This needs to be done before our app renders. To do it, add the following code in your entry file (e.g. `App.js`):
```js
import { useScreens } from 'react-native-screens';
import { enableScreens } from 'react-native-screens';
useScreens();
enableScreens();
```
## Usage

View File

@@ -6,7 +6,7 @@
"react-native",
"react-navigation"
],
"version": "5.0.0-alpha.17",
"version": "5.0.0-alpha.18",
"license": "MIT",
"repository": {
"type": "git",
@@ -29,7 +29,7 @@
"clean": "del lib"
},
"dependencies": {
"@react-navigation/routers": "^5.0.0-alpha.16"
"@react-navigation/routers": "^5.0.0-alpha.17"
},
"devDependencies": {
"@react-native-community/bob": "^0.7.0",

View File

@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [5.0.0-alpha.20](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/native@5.0.0-alpha.19...@react-navigation/native@5.0.0-alpha.20) (2019-12-16)
### Features
* add nested config in deep linking ([#210](https://github.com/react-navigation/navigation-ex/issues/210)) ([8002d51](https://github.com/react-navigation/navigation-ex/commit/8002d5179524a7211c37760a4ed45e8c12af4358)), closes [#154](https://github.com/react-navigation/navigation-ex/issues/154)
# [5.0.0-alpha.19](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/native@5.0.0-alpha.18...@react-navigation/native@5.0.0-alpha.19) (2019-12-14)

View File

@@ -7,7 +7,7 @@
"ios",
"android"
],
"version": "5.0.0-alpha.19",
"version": "5.0.0-alpha.20",
"license": "MIT",
"repository": {
"type": "git",
@@ -30,7 +30,7 @@
"clean": "del lib"
},
"dependencies": {
"@react-navigation/core": "^5.0.0-alpha.27"
"@react-navigation/core": "^5.0.0-alpha.28"
},
"devDependencies": {
"@react-native-community/bob": "^0.7.0",

View File

@@ -3,15 +3,11 @@ import { Linking } from 'react-native';
import {
getStateFromPath as getStateFromPathDefault,
NavigationContainerRef,
NavigationState,
PartialState,
} from '@react-navigation/core';
type Config = {
[routeName: string]:
| string
| { path: string; parse?: Record<string, (value: string) => any> };
};
type GetStateFromPath = typeof getStateFromPathDefault;
type Config = Parameters<GetStateFromPath>[1];
type Options = {
/**
@@ -36,10 +32,7 @@ type Options = {
/**
* Custom function to parse the URL object to a valid navigation state (advanced).
*/
getStateFromPath?: (
path: string,
options?: Config
) => PartialState<NavigationState> | undefined;
getStateFromPath?: GetStateFromPath;
};
export default function useLinking(

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.0.0-alpha.17](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/routers@5.0.0-alpha.16...@react-navigation/routers@5.0.0-alpha.17) (2019-12-16)
**Note:** Version bump only for package @react-navigation/routers
# [5.0.0-alpha.16](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/routers@5.0.0-alpha.15...@react-navigation/routers@5.0.0-alpha.16) (2019-12-11)
**Note:** Version bump only for package @react-navigation/routers

View File

@@ -6,7 +6,7 @@
"react-native",
"react-navigation"
],
"version": "5.0.0-alpha.16",
"version": "5.0.0-alpha.17",
"license": "MIT",
"repository": {
"type": "git",
@@ -29,7 +29,7 @@
"clean": "del lib"
},
"dependencies": {
"@react-navigation/core": "^5.0.0-alpha.27",
"@react-navigation/core": "^5.0.0-alpha.28",
"shortid": "^2.2.15"
},
"devDependencies": {

View File

@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [5.0.0-alpha.45](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/stack@5.0.0-alpha.44...@react-navigation/stack@5.0.0-alpha.45) (2019-12-16)
### Bug Fixes
* disable style interpolation for card when animation is disabled ([c110570](https://github.com/react-navigation/navigation-ex/commit/c110570d4c89a38336f19403e6f2d0870868620e))
# [5.0.0-alpha.44](https://github.com/react-navigation/navigation-ex/compare/@react-navigation/stack@5.0.0-alpha.43...@react-navigation/stack@5.0.0-alpha.44) (2019-12-14)

View File

@@ -10,7 +10,7 @@
"android",
"stack"
],
"version": "5.0.0-alpha.44",
"version": "5.0.0-alpha.45",
"license": "MIT",
"repository": {
"type": "git",
@@ -33,11 +33,13 @@
"clean": "del lib"
},
"dependencies": {
"@react-navigation/routers": "^5.0.0-alpha.16"
"@react-navigation/routers": "^5.0.0-alpha.17",
"color": "^3.1.2"
},
"devDependencies": {
"@react-native-community/bob": "^0.7.0",
"@react-native-community/masked-view": "^0.1.5",
"@types/color": "^3.0.0",
"@types/react": "^16.9.11",
"@types/react-native": "^0.60.22",
"del-cli": "^3.0.0",

View File

@@ -273,3 +273,7 @@ export function forScaleFromCenterAndroid({
},
};
}
export function forNoAnimation(): StackCardInterpolatedStyle {
return {};
}

View File

@@ -271,18 +271,14 @@ export type StackNavigationOptions = StackHeaderOptions &
* Defaults to `true` on Android and `false` on iOS.
*/
cardOverlayEnabled?: boolean;
/**
* Whether to use a transparent background for the card instead of a white one.
* This is useful to implement things like modal dialogs where the previous scene should still be visible underneath the current one.
* Defaults to `false`.
*
* If you use [`react-native-screens`](https://github.com/kmagiera/react-native-screens),
* you should also specify `mode: 'modal'` in the stack view config so previous screens aren't detached.
*/
cardTransparent?: boolean;
/**
* Style object for the card in stack.
* You can provide a custom background color to use instead of the default background here.
*
* You can also specify `{ backgroundColor: 'transparent' }` to make the previous screen visible underneath.
* This is useful to implement things like modal dialogs.
* If you use [`react-native-screens`](https://github.com/kmagiera/react-native-screens), you should also specify `mode: 'modal'`
* in the stack view config when using a transparent background so previous screens aren't detached.
*/
cardStyle?: StyleProp<ViewStyle>;
/**

View File

@@ -12,6 +12,7 @@ import {
import Animated, { Easing } from 'react-native-reanimated';
import { PanGestureHandler } from 'react-native-gesture-handler';
import { EdgeInsets } from 'react-native-safe-area-context';
import Color from 'color';
import animate, { Binary } from './CardAnimation';
import PointerEventsView from './PointerEventsView';
import memoize from '../../utils/memoize';
@@ -30,7 +31,6 @@ type Props = ViewProps & {
index: number;
active: boolean;
closing?: boolean;
transparent?: boolean;
next?: Animated.Node<number>;
current: Animated.Value<number>;
layout: Layout;
@@ -758,7 +758,6 @@ export default class Card extends React.Component<Props> {
render() {
const {
active,
transparent,
styleInterpolator,
index,
current,
@@ -813,6 +812,11 @@ export default class Card extends React.Component<Props> {
: this.handleGestureEventHorizontal
: undefined;
const { backgroundColor } = StyleSheet.flatten(contentStyle || {});
const isTransparent = backgroundColor
? Color(backgroundColor).alpha() === 0
: false;
return (
<StackGestureContext.Provider value={this.gestureRef}>
<View pointerEvents="box-none" {...rest}>
@@ -838,7 +842,7 @@ export default class Card extends React.Component<Props> {
{...this.gestureActivationCriteria()}
>
<Animated.View style={[styles.container, cardStyle]}>
{shadowEnabled && shadowStyle && !transparent ? (
{shadowEnabled && shadowStyle && !isTransparent ? (
<Animated.View
style={[
styles.shadow,

View File

@@ -21,10 +21,10 @@ type Props = TransitionPreset & {
safeAreaInsetRight: number;
safeAreaInsetBottom: number;
safeAreaInsetLeft: number;
cardTransparent?: boolean;
cardOverlayEnabled?: boolean;
cardShadowEnabled?: boolean;
cardStyle?: StyleProp<ViewStyle>;
animationEnabled?: boolean;
getPreviousRoute: (props: {
route: Route<string>;
}) => Route<string> | undefined;
@@ -59,7 +59,6 @@ export default function CardContainer({
cardShadowEnabled,
cardStyle,
cardStyleInterpolator,
cardTransparent,
closing,
current,
floatingHeaderHeight,
@@ -128,7 +127,6 @@ export default function CardContainer({
<Card
index={index}
active={active}
transparent={cardTransparent}
gestureDirection={gestureDirection}
layout={layout}
insets={insets}
@@ -155,12 +153,7 @@ export default function CardContainer({
? { marginTop: floatingHeaderHeight }
: null
}
contentStyle={[
{
backgroundColor: cardTransparent ? 'transparent' : colors.background,
},
cardStyle,
]}
contentStyle={[{ backgroundColor: colors.background }, cardStyle]}
style={StyleSheet.absoluteFill}
>
<View style={styles.container}>

View File

@@ -21,7 +21,8 @@ import {
DefaultTransition,
ModalTransition,
} from '../../TransitionConfigs/TransitionPresets';
import { forNoAnimation } from '../../TransitionConfigs/HeaderStyleInterpolators';
import { forNoAnimation as forNoAnimationHeader } from '../../TransitionConfigs/HeaderStyleInterpolators';
import { forNoAnimation as forNoAnimationCard } from '../../TransitionConfigs/CardStyleInterpolators';
import {
Layout,
StackHeaderMode,
@@ -314,7 +315,7 @@ export default class CardStack extends React.Component<Props, State> {
if (headerMode === 'screen') {
defaultTransitionPreset = {
...defaultTransitionPreset,
headerStyleInterpolator: forNoAnimation,
headerStyleInterpolator: forNoAnimationHeader,
};
}
@@ -354,15 +355,17 @@ export default class CardStack extends React.Component<Props, State> {
safeAreaInsets,
headerShown,
headerTransparent,
cardTransparent,
cardShadowEnabled,
cardOverlayEnabled,
cardStyle,
animationEnabled,
gestureResponseDistance,
gestureVelocityImpact,
gestureDirection = defaultTransitionPreset.gestureDirection,
transitionSpec = defaultTransitionPreset.transitionSpec,
cardStyleInterpolator = defaultTransitionPreset.cardStyleInterpolator,
cardStyleInterpolator = animationEnabled === false
? forNoAnimationCard
: defaultTransitionPreset.cardStyleInterpolator,
headerStyleInterpolator = defaultTransitionPreset.headerStyleInterpolator,
} = scene.descriptor
? scene.descriptor.options
@@ -385,8 +388,11 @@ export default class CardStack extends React.Component<Props, State> {
if (nextScene) {
const {
animationEnabled,
transitionSpec = defaultTransitionPreset.transitionSpec,
cardStyleInterpolator = defaultTransitionPreset.cardStyleInterpolator,
cardStyleInterpolator = animationEnabled === false
? forNoAnimationCard
: defaultTransitionPreset.cardStyleInterpolator,
headerStyleInterpolator = defaultTransitionPreset.headerStyleInterpolator,
} = nextScene.descriptor
? nextScene.descriptor.options
@@ -429,10 +435,10 @@ export default class CardStack extends React.Component<Props, State> {
safeAreaInsetRight={safeAreaInsetRight}
safeAreaInsetBottom={safeAreaInsetBottom}
safeAreaInsetLeft={safeAreaInsetLeft}
cardTransparent={cardTransparent}
cardOverlayEnabled={cardOverlayEnabled}
cardShadowEnabled={cardShadowEnabled}
cardStyle={cardStyle}
animationEnabled={animationEnabled}
onPageChangeStart={onPageChangeStart}
onPageChangeConfirm={onPageChangeConfirm}
onPageChangeCancel={onPageChangeCancel}