mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-18 18:08:17 +08:00
Compare commits
42 Commits
@satya164/
...
@react-nav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6dce0780ed | ||
|
|
dd7cff2016 | ||
|
|
740c6b6706 | ||
|
|
039017bc2a | ||
|
|
b85a1c3055 | ||
|
|
18f8188dc8 | ||
|
|
47a1229837 | ||
|
|
00b11e303e | ||
|
|
f384706741 | ||
|
|
d1a6f3e30e | ||
|
|
fd6636a8cd | ||
|
|
eb24fea8b9 | ||
|
|
85ae378d8c | ||
|
|
bea14aa26f | ||
|
|
4d1e102f8c | ||
|
|
f07cd13561 | ||
|
|
f6d06768d3 | ||
|
|
3381d680d7 | ||
|
|
fcd1cc64c1 | ||
|
|
3999fc2836 | ||
|
|
9fd2635756 | ||
|
|
6bec620a3f | ||
|
|
c7b8e2e966 | ||
|
|
719e1a7b46 | ||
|
|
10eca8b92e | ||
|
|
b66e3436a7 | ||
|
|
1c075ffb16 | ||
|
|
1ee3038a4d | ||
|
|
961b519fb1 | ||
|
|
0a19e94b23 | ||
|
|
1e73fed6de | ||
|
|
3193a30da6 | ||
|
|
499c50cd43 | ||
|
|
420f6926e1 | ||
|
|
70be3f6d86 | ||
|
|
bd35b4fc20 | ||
|
|
c511bc0b2b | ||
|
|
b4834ce703 | ||
|
|
ae5442ebe8 | ||
|
|
6dd52d35cf | ||
|
|
d6fa279d93 | ||
|
|
c3fa83efe0 |
@@ -1,46 +1,54 @@
|
|||||||
version: 2
|
version: 2.1
|
||||||
|
|
||||||
defaults: &defaults
|
executors:
|
||||||
|
default:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/node:10
|
- image: circleci/node:10
|
||||||
working_directory: ~/project
|
working_directory: ~/project
|
||||||
|
environment:
|
||||||
|
YARN_CACHE_FOLDER: "~/.cache/yarn"
|
||||||
|
|
||||||
|
commands:
|
||||||
|
attach_project:
|
||||||
|
steps:
|
||||||
|
- attach_workspace:
|
||||||
|
at: ~/project
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
install-dependencies:
|
install-dependencies:
|
||||||
<<: *defaults
|
executor: default
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- attach_workspace:
|
- attach_project
|
||||||
at: ~/project
|
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
keys:
|
keys:
|
||||||
- v1-dependencies-{{ checksum "yarn.lock" }}
|
- v2-dependencies-{{ checksum "yarn.lock" }}
|
||||||
- v1-dependencies-
|
- v2-dependencies-
|
||||||
- run:
|
- run:
|
||||||
name: Install project dependencies
|
name: Install project dependencies
|
||||||
command: yarn install --frozen-lockfile
|
command: yarn install --frozen-lockfile
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: v1-dependencies-{{ checksum "yarn.lock" }}
|
key: v2-dependencies-{{ checksum "yarn.lock" }}
|
||||||
paths: node_modules
|
paths: ~/.cache/yarn
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: .
|
root: .
|
||||||
paths: .
|
paths: .
|
||||||
|
|
||||||
lint-and-typecheck:
|
lint-and-typecheck:
|
||||||
<<: *defaults
|
executor: default
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_project
|
||||||
at: ~/project
|
|
||||||
- run:
|
- run:
|
||||||
name: Lint files
|
name: Lint files
|
||||||
command: yarn lint
|
command: yarn lint
|
||||||
- run:
|
- run:
|
||||||
name: Typecheck files
|
name: Typecheck files
|
||||||
command: yarn typescript
|
command: yarn typescript
|
||||||
|
|
||||||
unit-tests:
|
unit-tests:
|
||||||
<<: *defaults
|
executor: default
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_project
|
||||||
at: ~/project
|
|
||||||
- run:
|
- run:
|
||||||
name: Run unit tests
|
name: Run unit tests
|
||||||
command: yarn test --coverage
|
command: yarn test --coverage
|
||||||
@@ -50,11 +58,11 @@ jobs:
|
|||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: coverage
|
path: coverage
|
||||||
destination: coverage
|
destination: coverage
|
||||||
|
|
||||||
integration-tests:
|
integration-tests:
|
||||||
<<: *defaults
|
executor: default
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_project
|
||||||
at: ~/project
|
|
||||||
- run:
|
- run:
|
||||||
name: Install Headless Chrome dependencies
|
name: Install Headless Chrome dependencies
|
||||||
command: |
|
command: |
|
||||||
@@ -70,11 +78,11 @@ jobs:
|
|||||||
- run:
|
- run:
|
||||||
name: Run integration tests
|
name: Run integration tests
|
||||||
command: yarn example test --maxWorkers=2
|
command: yarn example test --maxWorkers=2
|
||||||
|
|
||||||
build-packages:
|
build-packages:
|
||||||
<<: *defaults
|
executor: default
|
||||||
steps:
|
steps:
|
||||||
- attach_workspace:
|
- attach_project
|
||||||
at: ~/project
|
|
||||||
- run:
|
- run:
|
||||||
name: Build packages in the monorepo
|
name: Build packages in the monorepo
|
||||||
command: yarn lerna run prepare
|
command: yarn lerna run prepare
|
||||||
@@ -83,7 +91,6 @@ jobs:
|
|||||||
command: node scripts/check-types-path.js
|
command: node scripts/check-types-path.js
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
version: 2
|
|
||||||
build-and-test:
|
build-and-test:
|
||||||
jobs:
|
jobs:
|
||||||
- install-dependencies
|
- install-dependencies
|
||||||
|
|||||||
@@ -12,33 +12,33 @@
|
|||||||
"test": "jest"
|
"test": "jest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/vector-icons": "^10.0.0",
|
"@expo/vector-icons": "^10.2.0",
|
||||||
"@react-native-community/masked-view": "^0.1.7",
|
"@react-native-community/masked-view": "^0.1.10",
|
||||||
"color": "^3.1.2",
|
"color": "^3.1.2",
|
||||||
"expo": "^37.0.0",
|
"expo": "^37.0.8",
|
||||||
"expo-asset": "~8.1.3",
|
"expo-asset": "~8.1.3",
|
||||||
"expo-blur": "~8.1.0",
|
"expo-blur": "~8.1.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-dom": "~16.9.0",
|
"react-dom": "~16.9.0",
|
||||||
"react-native": "~0.61.5",
|
"react-native": "~0.61.5",
|
||||||
"react-native-gesture-handler": "^1.6.0",
|
"react-native-gesture-handler": "^1.6.0",
|
||||||
"react-native-paper": "^3.7.0",
|
"react-native-paper": "^3.10.1",
|
||||||
"react-native-reanimated": "^1.7.0",
|
"react-native-reanimated": "^1.8.0",
|
||||||
"react-native-restart": "^0.0.14",
|
"react-native-restart": "^0.0.15",
|
||||||
"react-native-safe-area-context": "^0.7.3",
|
"react-native-safe-area-context": "^0.7.3",
|
||||||
"react-native-screens": "^2.3.0",
|
"react-native-screens": "^2.7.0",
|
||||||
"react-native-tab-view": "2.14.0",
|
"react-native-tab-view": "2.14.0",
|
||||||
"react-native-unimodules": "~0.8.1",
|
"react-native-unimodules": "~0.9.1",
|
||||||
"react-native-web": "^0.11.7"
|
"react-native-web": "^0.11.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@expo/webpack-config": "^0.11.19",
|
"@expo/webpack-config": "^0.11.19",
|
||||||
"@types/jest-dev-server": "^4.2.0",
|
"@types/jest-dev-server": "^4.2.0",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-native": "^0.60.22",
|
"@types/react-native": "^0.62.7",
|
||||||
"babel-preset-expo": "^8.1.0",
|
"babel-preset-expo": "^8.1.0",
|
||||||
"expo-cli": "^3.17.18",
|
"expo-cli": "^3.20.1",
|
||||||
"jest": "^25.2.7",
|
"jest": "^26.0.1",
|
||||||
"jest-dev-server": "^4.4.0",
|
"jest-dev-server": "^4.4.0",
|
||||||
"playwright": "^0.14.0",
|
"playwright": "^0.14.0",
|
||||||
"serve": "^11.3.0",
|
"serve": "^11.3.0",
|
||||||
|
|||||||
3
example/src/AsyncStorage.native.tsx
Normal file
3
example/src/AsyncStorage.native.tsx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { AsyncStorage } from 'react-native';
|
||||||
|
|
||||||
|
export default AsyncStorage;
|
||||||
14
example/src/AsyncStorage.tsx
Normal file
14
example/src/AsyncStorage.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
export default {
|
||||||
|
getItem(key: string) {
|
||||||
|
return Promise.resolve(localStorage.getItem(key));
|
||||||
|
},
|
||||||
|
setItem(key: string, value: string) {
|
||||||
|
return Promise.resolve(localStorage.setItem(key, value));
|
||||||
|
},
|
||||||
|
removeItem(key: string) {
|
||||||
|
return Promise.resolve(localStorage.removeItem(key));
|
||||||
|
},
|
||||||
|
clear() {
|
||||||
|
return Promise.resolve(localStorage.clear());
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { View, ScrollView, StyleSheet } from 'react-native';
|
import { View, ScrollView, StyleSheet, Platform } from 'react-native';
|
||||||
import { Button } from 'react-native-paper';
|
import { Button } from 'react-native-paper';
|
||||||
import {
|
import {
|
||||||
createCompatNavigatorFactory,
|
createCompatNavigatorFactory,
|
||||||
@@ -23,6 +23,8 @@ type NestedStackParams = {
|
|||||||
Article: { author: string };
|
Article: { author: string };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const scrollEnabled = Platform.select({ web: true, default: false });
|
||||||
|
|
||||||
const AlbumsScreen: CompatScreenType<StackNavigationProp<
|
const AlbumsScreen: CompatScreenType<StackNavigationProp<
|
||||||
CompatStackParams
|
CompatStackParams
|
||||||
>> = ({ navigation }) => {
|
>> = ({ navigation }) => {
|
||||||
@@ -44,7 +46,7 @@ const AlbumsScreen: CompatScreenType<StackNavigationProp<
|
|||||||
Go back
|
Go back
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
<Albums scrollEnabled={false} />
|
<Albums scrollEnabled={scrollEnabled} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -70,7 +72,7 @@ const FeedScreen: CompatScreenType<StackNavigationProp<NestedStackParams>> = ({
|
|||||||
Go back
|
Go back
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
<NewsFeed scrollEnabled={false} />
|
<NewsFeed scrollEnabled={scrollEnabled} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -100,7 +102,7 @@ const ArticleScreen: CompatScreenType<StackNavigationProp<
|
|||||||
</View>
|
</View>
|
||||||
<Article
|
<Article
|
||||||
author={{ name: navigation.getParam('author') }}
|
author={{ name: navigation.getParam('author') }}
|
||||||
scrollEnabled={false}
|
scrollEnabled={scrollEnabled}
|
||||||
/>
|
/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { View, StyleSheet, ScrollView } from 'react-native';
|
import { View, StyleSheet, ScrollView, Platform } from 'react-native';
|
||||||
import { Button } from 'react-native-paper';
|
import { Button } from 'react-native-paper';
|
||||||
import {
|
import {
|
||||||
Link,
|
Link,
|
||||||
@@ -22,13 +22,24 @@ type SimpleStackParams = {
|
|||||||
|
|
||||||
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
|
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
|
||||||
|
|
||||||
|
const scrollEnabled = Platform.select({ web: true, default: false });
|
||||||
|
|
||||||
const LinkButton = ({
|
const LinkButton = ({
|
||||||
to,
|
to,
|
||||||
...rest
|
...rest
|
||||||
}: React.ComponentProps<typeof Button> & { to: string }) => {
|
}: React.ComponentProps<typeof Button> & { to: string }) => {
|
||||||
const props = useLinkProps({ to });
|
const { onPress, ...props } = useLinkProps({ to });
|
||||||
|
|
||||||
return <Button {...props} {...rest} />;
|
return (
|
||||||
|
<Button
|
||||||
|
{...props}
|
||||||
|
{...rest}
|
||||||
|
{...Platform.select({
|
||||||
|
web: { onClick: onPress } as any,
|
||||||
|
default: { onPress },
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ArticleScreen = ({
|
const ArticleScreen = ({
|
||||||
@@ -69,7 +80,10 @@ const ArticleScreen = ({
|
|||||||
Go back
|
Go back
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
<Article author={{ name: route.params.author }} scrollEnabled={false} />
|
<Article
|
||||||
|
author={{ name: route.params.author }}
|
||||||
|
scrollEnabled={scrollEnabled}
|
||||||
|
/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -103,7 +117,7 @@ const AlbumsScreen = ({
|
|||||||
Go back
|
Go back
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
<Albums scrollEnabled={false} />
|
<Albums scrollEnabled={scrollEnabled} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { View, StyleSheet, ScrollView } from 'react-native';
|
import { View, StyleSheet, ScrollView, Platform } from 'react-native';
|
||||||
import { Button } from 'react-native-paper';
|
import { Button } from 'react-native-paper';
|
||||||
import { RouteProp, ParamListBase } from '@react-navigation/native';
|
import { RouteProp, ParamListBase } from '@react-navigation/native';
|
||||||
import {
|
import {
|
||||||
@@ -17,6 +17,8 @@ type ModalStackParams = {
|
|||||||
|
|
||||||
type ModalStackNavigation = StackNavigationProp<ModalStackParams>;
|
type ModalStackNavigation = StackNavigationProp<ModalStackParams>;
|
||||||
|
|
||||||
|
const scrollEnabled = Platform.select({ web: true, default: false });
|
||||||
|
|
||||||
const ArticleScreen = ({
|
const ArticleScreen = ({
|
||||||
navigation,
|
navigation,
|
||||||
route,
|
route,
|
||||||
@@ -42,7 +44,10 @@ const ArticleScreen = ({
|
|||||||
Go back
|
Go back
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
<Article author={{ name: route.params.author }} scrollEnabled={false} />
|
<Article
|
||||||
|
author={{ name: route.params.author }}
|
||||||
|
scrollEnabled={scrollEnabled}
|
||||||
|
/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -66,7 +71,7 @@ const AlbumsScreen = ({ navigation }: { navigation: ModalStackNavigation }) => {
|
|||||||
Go back
|
Go back
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
<Albums scrollEnabled={false} />
|
<Albums scrollEnabled={scrollEnabled} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { View, StyleSheet, ScrollView } from 'react-native';
|
import { View, Platform, StyleSheet, ScrollView } from 'react-native';
|
||||||
import { Button } from 'react-native-paper';
|
import { Button } from 'react-native-paper';
|
||||||
import { RouteProp, ParamListBase } from '@react-navigation/native';
|
import { RouteProp, ParamListBase } from '@react-navigation/native';
|
||||||
import {
|
import {
|
||||||
@@ -18,6 +18,8 @@ type SimpleStackParams = {
|
|||||||
|
|
||||||
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
|
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
|
||||||
|
|
||||||
|
const scrollEnabled = Platform.select({ web: true, default: false });
|
||||||
|
|
||||||
const ArticleScreen = ({
|
const ArticleScreen = ({
|
||||||
navigation,
|
navigation,
|
||||||
route,
|
route,
|
||||||
@@ -43,7 +45,10 @@ const ArticleScreen = ({
|
|||||||
Pop screen
|
Pop screen
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
<Article author={{ name: route.params.author }} scrollEnabled={false} />
|
<Article
|
||||||
|
author={{ name: route.params.author }}
|
||||||
|
scrollEnabled={scrollEnabled}
|
||||||
|
/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -71,7 +76,7 @@ const NewsFeedScreen = ({
|
|||||||
Go back
|
Go back
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
<NewsFeed scrollEnabled={false} />
|
<NewsFeed scrollEnabled={scrollEnabled} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -99,7 +104,7 @@ const AlbumsScreen = ({
|
|||||||
Pop by 2
|
Pop by 2
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
<Albums scrollEnabled={false} />
|
<Albums scrollEnabled={scrollEnabled} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ type SimpleStackParams = {
|
|||||||
|
|
||||||
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
|
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
|
||||||
|
|
||||||
|
const scrollEnabled = Platform.select({ web: true, default: false });
|
||||||
|
|
||||||
const ArticleScreen = ({
|
const ArticleScreen = ({
|
||||||
navigation,
|
navigation,
|
||||||
route,
|
route,
|
||||||
@@ -45,7 +47,10 @@ const ArticleScreen = ({
|
|||||||
Go back
|
Go back
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
<Article author={{ name: route.params.author }} scrollEnabled={false} />
|
<Article
|
||||||
|
author={{ name: route.params.author }}
|
||||||
|
scrollEnabled={scrollEnabled}
|
||||||
|
/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -75,7 +80,7 @@ const AlbumsScreen = ({
|
|||||||
Go back
|
Go back
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
<Albums scrollEnabled={false} />
|
<Albums scrollEnabled={scrollEnabled} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { View, StyleSheet, ScrollView } from 'react-native';
|
import { View, StyleSheet, ScrollView, Platform } from 'react-native';
|
||||||
import { Button, Paragraph } from 'react-native-paper';
|
import { Button, Paragraph } from 'react-native-paper';
|
||||||
import { RouteProp, ParamListBase, useTheme } from '@react-navigation/native';
|
import { RouteProp, ParamListBase, useTheme } from '@react-navigation/native';
|
||||||
import {
|
import {
|
||||||
@@ -15,6 +15,8 @@ type SimpleStackParams = {
|
|||||||
|
|
||||||
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
|
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
|
||||||
|
|
||||||
|
const scrollEnabled = Platform.select({ web: true, default: false });
|
||||||
|
|
||||||
const ArticleScreen = ({
|
const ArticleScreen = ({
|
||||||
navigation,
|
navigation,
|
||||||
route,
|
route,
|
||||||
@@ -40,7 +42,10 @@ const ArticleScreen = ({
|
|||||||
Go back
|
Go back
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
<Article author={{ name: route.params.author }} scrollEnabled={false} />
|
<Article
|
||||||
|
author={{ name: route.params.author }}
|
||||||
|
scrollEnabled={scrollEnabled}
|
||||||
|
/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import {
|
import {
|
||||||
ScrollView,
|
ScrollView,
|
||||||
AsyncStorage,
|
|
||||||
YellowBox,
|
YellowBox,
|
||||||
Platform,
|
Platform,
|
||||||
StatusBar,
|
StatusBar,
|
||||||
I18nManager,
|
I18nManager,
|
||||||
Dimensions,
|
Dimensions,
|
||||||
ScaledSize,
|
ScaledSize,
|
||||||
|
Linking,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
// eslint-disable-next-line import/no-unresolved
|
// eslint-disable-next-line import/no-unresolved
|
||||||
import { enableScreens } from 'react-native-screens';
|
import { enableScreens } from 'react-native-screens';
|
||||||
@@ -26,7 +26,6 @@ import {
|
|||||||
} from 'react-native-paper';
|
} from 'react-native-paper';
|
||||||
import {
|
import {
|
||||||
InitialState,
|
InitialState,
|
||||||
NavigationContainerRef,
|
|
||||||
NavigationContainer,
|
NavigationContainer,
|
||||||
DefaultTheme,
|
DefaultTheme,
|
||||||
DarkTheme,
|
DarkTheme,
|
||||||
@@ -42,6 +41,7 @@ import {
|
|||||||
HeaderStyleInterpolators,
|
HeaderStyleInterpolators,
|
||||||
} from '@react-navigation/stack';
|
} from '@react-navigation/stack';
|
||||||
|
|
||||||
|
import AsyncStorage from './AsyncStorage';
|
||||||
import LinkingPrefixes from './LinkingPrefixes';
|
import LinkingPrefixes from './LinkingPrefixes';
|
||||||
import SettingsItem from './Shared/SettingsItem';
|
import SettingsItem from './Shared/SettingsItem';
|
||||||
import SimpleStack from './Screens/SimpleStack';
|
import SimpleStack from './Screens/SimpleStack';
|
||||||
@@ -129,8 +129,6 @@ const THEME_PERSISTENCE_KEY = 'THEME_TYPE';
|
|||||||
Asset.loadAsync(StackAssets);
|
Asset.loadAsync(StackAssets);
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const containerRef = React.useRef<NavigationContainerRef>(null);
|
|
||||||
|
|
||||||
const [theme, setTheme] = React.useState(DefaultTheme);
|
const [theme, setTheme] = React.useState(DefaultTheme);
|
||||||
|
|
||||||
const [isReady, setIsReady] = React.useState(false);
|
const [isReady, setIsReady] = React.useState(false);
|
||||||
@@ -141,19 +139,19 @@ export default function App() {
|
|||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const restoreState = async () => {
|
const restoreState = async () => {
|
||||||
try {
|
try {
|
||||||
let state;
|
const initialUrl = await Linking.getInitialURL();
|
||||||
|
|
||||||
if (Platform.OS !== 'web' && state === undefined) {
|
if (Platform.OS !== 'web' || initialUrl === null) {
|
||||||
const savedState = await AsyncStorage.getItem(
|
const savedState = await AsyncStorage.getItem(
|
||||||
NAVIGATION_PERSISTENCE_KEY
|
NAVIGATION_PERSISTENCE_KEY
|
||||||
);
|
);
|
||||||
|
|
||||||
state = savedState ? JSON.parse(savedState) : undefined;
|
const state = savedState ? JSON.parse(savedState) : undefined;
|
||||||
}
|
|
||||||
|
|
||||||
if (state !== undefined) {
|
if (state !== undefined) {
|
||||||
setInitialState(state);
|
setInitialState(state);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
const themeName = await AsyncStorage.getItem(THEME_PERSISTENCE_KEY);
|
const themeName = await AsyncStorage.getItem(THEME_PERSISTENCE_KEY);
|
||||||
@@ -208,7 +206,6 @@ export default function App() {
|
|||||||
<StatusBar barStyle={theme.dark ? 'light-content' : 'dark-content'} />
|
<StatusBar barStyle={theme.dark ? 'light-content' : 'dark-content'} />
|
||||||
)}
|
)}
|
||||||
<NavigationContainer
|
<NavigationContainer
|
||||||
ref={containerRef}
|
|
||||||
initialState={initialState}
|
initialState={initialState}
|
||||||
onStateChange={(state) =>
|
onStateChange={(state) =>
|
||||||
AsyncStorage.setItem(
|
AsyncStorage.setItem(
|
||||||
|
|||||||
1
example/web/_redirects
Normal file
1
example/web/_redirects
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/* /index.html 200
|
||||||
@@ -24,17 +24,19 @@ module.exports = async function (env, argv) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Object.assign(config.resolve.alias, {
|
Object.assign(config.resolve.alias, {
|
||||||
react: path.resolve(node_modules, 'react'),
|
'react': path.resolve(node_modules, 'react'),
|
||||||
'react-native': path.resolve(node_modules, 'react-native-web'),
|
'react-native': path.resolve(node_modules, 'react-native-web'),
|
||||||
'react-native-web': path.resolve(node_modules, 'react-native-web'),
|
'react-native-web': path.resolve(node_modules, 'react-native-web'),
|
||||||
'@expo/vector-icons': path.resolve(node_modules, '@expo/vector-icons'),
|
'@expo/vector-icons': path.resolve(node_modules, '@expo/vector-icons'),
|
||||||
});
|
});
|
||||||
|
|
||||||
fs.readdirSync(packages).forEach((name) => {
|
fs.readdirSync(packages)
|
||||||
|
.filter((name) => !name.startsWith('.'))
|
||||||
|
.forEach((name) => {
|
||||||
config.resolve.alias[`@react-navigation/${name}`] = path.resolve(
|
config.resolve.alias[`@react-navigation/${name}`] = path.resolve(
|
||||||
packages,
|
packages,
|
||||||
name,
|
name,
|
||||||
'src'
|
require(`../packages/${name}/package.json`).source
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
16
package.json
16
package.json
@@ -27,23 +27,23 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
||||||
"@babel/plugin-proposal-optional-chaining": "^7.9.0",
|
"@babel/plugin-proposal-optional-chaining": "^7.9.0",
|
||||||
"@babel/preset-env": "^7.9.0",
|
"@babel/preset-env": "^7.9.6",
|
||||||
"@babel/preset-flow": "^7.9.0",
|
"@babel/preset-flow": "^7.9.0",
|
||||||
"@babel/preset-react": "^7.9.4",
|
"@babel/preset-react": "^7.9.4",
|
||||||
"@babel/preset-typescript": "^7.9.0",
|
"@babel/preset-typescript": "^7.9.0",
|
||||||
"@babel/runtime": "^7.9.2",
|
"@babel/runtime": "^7.9.6",
|
||||||
"@commitlint/config-conventional": "^8.3.4",
|
"@commitlint/config-conventional": "^8.3.4",
|
||||||
"@types/jest": "^25.2.1",
|
"@types/jest": "^25.2.1",
|
||||||
"babel-jest": "^25.2.6",
|
"babel-jest": "^26.0.1",
|
||||||
"codecov": "^3.6.5",
|
"codecov": "^3.6.5",
|
||||||
"commitlint": "^8.3.5",
|
"commitlint": "^8.3.5",
|
||||||
"core-js": "^3.6.4",
|
"core-js": "^3.6.5",
|
||||||
"eslint": "^6.8.0",
|
"eslint": "^6.8.0",
|
||||||
"eslint-config-satya164": "^3.1.6",
|
"eslint-config-satya164": "^3.1.7",
|
||||||
"husky": "^4.2.3",
|
"husky": "^4.2.5",
|
||||||
"jest": "^25.2.7",
|
"jest": "^26.0.1",
|
||||||
"lerna": "^3.20.2",
|
"lerna": "^3.20.2",
|
||||||
"prettier": "^2.0.4",
|
"prettier": "^2.0.5",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
|
|||||||
@@ -3,6 +3,80 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [5.4.2](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.1...@react-navigation/bottom-tabs@5.4.2) (2020-05-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.1](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.4.0...@react-navigation/bottom-tabs@5.4.1) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.4.0](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.4...@react-navigation/bottom-tabs@5.4.0) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add generic type aliases for screen props ([bea14aa](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/bea14aa26fd5cbfebc7973733c5cf1f44fd323aa)), closes [#7971](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/issues/7971)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.4](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.3...@react-navigation/bottom-tabs@5.3.4) (2020-05-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.3](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.2...@react-navigation/bottom-tabs@5.3.3) (2020-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.2](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.1...@react-navigation/bottom-tabs@5.3.2) (2020-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.1](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.3.0...@react-navigation/bottom-tabs@5.3.1) (2020-04-30)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.3.0](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.8...@react-navigation/bottom-tabs@5.3.0) (2020-04-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add `useLinkBuilder` hook to build links ([2792f43](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/2792f438fe45428fe193e3708fee7ad61966cbf4))
|
||||||
|
* add action prop to Link ([942d2be](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/commit/942d2be2c72720469475ce12ec8df23825994dbf))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.2.8](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.7...@react-navigation/bottom-tabs@5.2.8) (2020-04-27)
|
## [5.2.8](https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.2.7...@react-navigation/bottom-tabs@5.2.8) (2020-04-27)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/bottom-tabs",
|
"name": "@react-navigation/bottom-tabs",
|
||||||
"description": "Bottom tab navigator following iOS design guidelines",
|
"description": "Bottom tab navigator following iOS design guidelines",
|
||||||
"version": "5.2.8",
|
"version": "5.4.2",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
"repository": "https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs",
|
"repository": "https://github.com/react-navigation/react-navigation/tree/master/packages/bottom-tabs",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
@@ -34,16 +35,16 @@
|
|||||||
"react-native-iphone-x-helper": "^1.2.1"
|
"react-native-iphone-x-helper": "^1.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.13.1",
|
||||||
"@react-navigation/native": "^5.1.7",
|
"@react-navigation/native": "^5.3.0",
|
||||||
"@types/color": "^3.0.1",
|
"@types/color": "^3.0.1",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.62.7",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-native": "~0.61.5",
|
"react-native": "~0.61.5",
|
||||||
"react-native-safe-area-context": "^0.7.3",
|
"react-native-safe-area-context": "^0.7.3",
|
||||||
"react-native-screens": "^2.3.0",
|
"react-native-screens": "^2.7.0",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export { default as BottomTabBar } from './views/BottomTabBar';
|
|||||||
export type {
|
export type {
|
||||||
BottomTabNavigationOptions,
|
BottomTabNavigationOptions,
|
||||||
BottomTabNavigationProp,
|
BottomTabNavigationProp,
|
||||||
|
BottomTabScreenProps,
|
||||||
BottomTabBarProps,
|
BottomTabBarProps,
|
||||||
BottomTabBarOptions,
|
BottomTabBarOptions,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
Descriptor,
|
Descriptor,
|
||||||
TabNavigationState,
|
TabNavigationState,
|
||||||
TabActionHelpers,
|
TabActionHelpers,
|
||||||
|
RouteProp,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
|
|
||||||
export type BottomTabNavigationEventMap = {
|
export type BottomTabNavigationEventMap = {
|
||||||
@@ -45,6 +46,14 @@ export type BottomTabNavigationProp<
|
|||||||
> &
|
> &
|
||||||
TabActionHelpers<ParamList>;
|
TabActionHelpers<ParamList>;
|
||||||
|
|
||||||
|
export type BottomTabScreenProps<
|
||||||
|
ParamList extends ParamListBase,
|
||||||
|
RouteName extends keyof ParamList = string
|
||||||
|
> = {
|
||||||
|
navigation: BottomTabNavigationProp<ParamList, RouteName>;
|
||||||
|
route: RouteProp<ParamList, RouteName>;
|
||||||
|
};
|
||||||
|
|
||||||
export type BottomTabNavigationOptions = {
|
export type BottomTabNavigationOptions = {
|
||||||
/**
|
/**
|
||||||
* Title text for the screen.
|
* Title text for the screen.
|
||||||
|
|||||||
@@ -3,6 +3,73 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [5.1.18](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.17...@react-navigation/compat@5.1.18) (2020-05-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.17](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.16...@react-navigation/compat@5.1.17) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.16](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.15...@react-navigation/compat@5.1.16) (2020-05-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.15](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.14...@react-navigation/compat@5.1.15) (2020-05-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.14](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.13...@react-navigation/compat@5.1.14) (2020-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.13](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.12...@react-navigation/compat@5.1.13) (2020-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.12](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.11...@react-navigation/compat@5.1.12) (2020-04-30)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.11](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.10...@react-navigation/compat@5.1.11) (2020-04-30)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/compat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.1.10](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.9...@react-navigation/compat@5.1.10) (2020-04-27)
|
## [5.1.10](https://github.com/react-navigation/react-navigation/tree/master/packages/compat/compare/@react-navigation/compat@5.1.9...@react-navigation/compat@5.1.10) (2020-04-27)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/compat",
|
"name": "@react-navigation/compat",
|
||||||
"description": "Compatibility layer to write navigator definitions in static configuration format",
|
"description": "Compatibility layer to write navigator definitions in static configuration format",
|
||||||
"version": "5.1.10",
|
"version": "5.1.18",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": "https://github.com/react-navigation/react-navigation/tree/master/packages/compat",
|
"repository": "https://github.com/react-navigation/react-navigation/tree/master/packages/compat",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
"homepage": "https://reactnavigation.org/docs/compatibility.html",
|
"homepage": "https://reactnavigation.org/docs/compatibility.html",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
@@ -25,9 +26,9 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.13.1",
|
||||||
"@react-navigation/native": "^5.1.7",
|
"@react-navigation/native": "^5.3.0",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,57 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [5.5.2](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.5.1...@react-navigation/core@5.5.2) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.5.1](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.5.0...@react-navigation/core@5.5.1) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* avoid cleaning up state when a new navigator is mounted. fixes [#8195](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/8195) ([f6d0676](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/f6d06768d3c36d1f5beaffcb660f3c259209f2e7))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.5.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.4.0...@react-navigation/core@5.5.0) (2020-05-05)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add support for optional params to linking ([#8196](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/8196)) ([fcd1cc6](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/fcd1cc64c151e4941f3f544a54b5048d853821f6))
|
||||||
|
* support params anywhere in path segement ([#8184](https://github.com/react-navigation/react-navigation/tree/master/packages/core/issues/8184)) ([3999fc2](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/3999fc28365c3a06a17d963c7be7fb7e897f99e0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.4.0](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.3.5...@react-navigation/core@5.4.0) (2020-04-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* handle empty paths when parsing ([c3fa83e](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/c3fa83efe0d73db76365f8be3d6a8ca1d1289b71))
|
||||||
|
* parsing url ([bd35b4f](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/bd35b4fc202c3868fb75c3675b62de67557089e1))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add `useLinkBuilder` hook to build links ([2792f43](https://github.com/react-navigation/react-navigation/tree/master/packages/core/commit/2792f438fe45428fe193e3708fee7ad61966cbf4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.3.5](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.3.4...@react-navigation/core@5.3.5) (2020-04-27)
|
## [5.3.5](https://github.com/react-navigation/react-navigation/tree/master/packages/core/compare/@react-navigation/core@5.3.4...@react-navigation/core@5.3.5) (2020-04-27)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/core",
|
"name": "@react-navigation/core",
|
||||||
"description": "Core utilities for building navigators",
|
"description": "Core utilities for building navigators",
|
||||||
"version": "5.3.5",
|
"version": "5.5.2",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react",
|
"react",
|
||||||
"react-native",
|
"react-native",
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
"homepage": "https://reactnavigation.org",
|
"homepage": "https://reactnavigation.org",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
@@ -29,21 +30,21 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/routers": "^5.4.1",
|
"@react-navigation/routers": "^5.4.4",
|
||||||
"escape-string-regexp": "^2.0.0",
|
"escape-string-regexp": "^4.0.0",
|
||||||
"nanoid": "^3.0.2",
|
"nanoid": "^3.1.5",
|
||||||
"query-string": "^6.12.0",
|
"query-string": "^6.12.1",
|
||||||
"react-is": "^16.13.0",
|
"react-is": "^16.13.0",
|
||||||
"use-subscription": "^1.4.0"
|
"use-subscription": "^1.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.13.1",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-is": "^16.7.1",
|
"@types/react-is": "^16.7.1",
|
||||||
"@types/use-subscription": "^1.0.0",
|
"@types/use-subscription": "^1.0.0",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-native-testing-library": "^1.12.0",
|
"react-native-testing-library": "^1.13.2",
|
||||||
"react-test-renderer": "~16.13.1",
|
"react-test-renderer": "~16.13.1",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -219,6 +219,8 @@ const BaseNavigationContainer = React.forwardRef(
|
|||||||
dispatch,
|
dispatch,
|
||||||
canGoBack,
|
canGoBack,
|
||||||
getRootState,
|
getRootState,
|
||||||
|
dangerouslyGetState: () => state,
|
||||||
|
dangerouslyGetParent: () => undefined,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const builderContext = React.useMemo(
|
const builderContext = React.useMemo(
|
||||||
|
|||||||
@@ -426,6 +426,49 @@ it('ignores empty string paths', () => {
|
|||||||
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('keeps query params if path is empty', () => {
|
||||||
|
const path = '/?foo=42';
|
||||||
|
const config = {
|
||||||
|
Foo: {
|
||||||
|
screens: {
|
||||||
|
Foe: 'foe',
|
||||||
|
Bar: {
|
||||||
|
screens: {
|
||||||
|
Qux: {
|
||||||
|
path: '',
|
||||||
|
parse: { foo: Number },
|
||||||
|
},
|
||||||
|
Baz: 'baz',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Foo',
|
||||||
|
state: {
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
name: 'Bar',
|
||||||
|
state: {
|
||||||
|
routes: [{ name: 'Qux', params: { foo: 42 } }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(getPathFromState(state, config)).toBe(path);
|
||||||
|
expect(getPathFromState(getStateFromPath(path, config), config)).toEqual(
|
||||||
|
path
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('cuts nested configs too', () => {
|
it('cuts nested configs too', () => {
|
||||||
const path = '/baz';
|
const path = '/baz';
|
||||||
const config = {
|
const config = {
|
||||||
@@ -495,6 +538,8 @@ it('handles empty path at the end', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('returns "/" for empty path', () => {
|
it('returns "/" for empty path', () => {
|
||||||
|
const path = '/';
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
Foo: {
|
Foo: {
|
||||||
path: '',
|
path: '',
|
||||||
@@ -519,7 +564,8 @@ it('returns "/" for empty path', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe('/');
|
expect(getPathFromState(state, config)).toBe(path);
|
||||||
|
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('parses no path specified', () => {
|
it('parses no path specified', () => {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -379,6 +379,8 @@ it("doesn't update state if action wasn't handled", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('cleans up state when the navigator unmounts', () => {
|
it('cleans up state when the navigator unmounts', () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
const TestNavigator = (props: any) => {
|
const TestNavigator = (props: any) => {
|
||||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
@@ -426,6 +428,8 @@ it('cleans up state when the navigator unmounts', () => {
|
|||||||
<BaseNavigationContainer onStateChange={onStateChange} children={null} />
|
<BaseNavigationContainer onStateChange={onStateChange} children={null} />
|
||||||
);
|
);
|
||||||
|
|
||||||
|
act(() => jest.runAllTimers());
|
||||||
|
|
||||||
expect(onStateChange).toBeCalledTimes(2);
|
expect(onStateChange).toBeCalledTimes(2);
|
||||||
expect(onStateChange).lastCalledWith(undefined);
|
expect(onStateChange).lastCalledWith(undefined);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -115,8 +115,6 @@ export default function getPathFromState(
|
|||||||
pattern = nestedRouteNames.substring(1);
|
pattern = nestedRouteNames.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we don't add empty path strings to path
|
|
||||||
if (pattern !== '') {
|
|
||||||
const config =
|
const config =
|
||||||
currentOptions[route.name] !== undefined
|
currentOptions[route.name] !== undefined
|
||||||
? (currentOptions[route.name] as { stringify?: StringifyConfig })
|
? (currentOptions[route.name] as { stringify?: StringifyConfig })
|
||||||
@@ -137,7 +135,7 @@ export default function getPathFromState(
|
|||||||
path += pattern
|
path += pattern
|
||||||
.split('/')
|
.split('/')
|
||||||
.map((p) => {
|
.map((p) => {
|
||||||
const name = p.replace(/^:/, '');
|
const name = p.replace(/^:/, '').replace(/\?$/, '');
|
||||||
|
|
||||||
// If the path has a pattern for a param, put the param in the path
|
// If the path has a pattern for a param, put the param in the path
|
||||||
if (params && name in params && p.startsWith(':')) {
|
if (params && name in params && p.startsWith(':')) {
|
||||||
@@ -146,8 +144,10 @@ export default function getPathFromState(
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||||
delete params[name];
|
delete params[name];
|
||||||
return encodeURIComponent(value);
|
return encodeURIComponent(value);
|
||||||
|
} else if (p.endsWith('?')) {
|
||||||
|
// optional params without value assigned in route.params should be ignored
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return encodeURIComponent(p);
|
return encodeURIComponent(p);
|
||||||
})
|
})
|
||||||
.join('/');
|
.join('/');
|
||||||
@@ -170,15 +170,13 @@ export default function getPathFromState(
|
|||||||
path += `?${query}`;
|
path += `?${query}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
current = route.state;
|
current = route.state;
|
||||||
}
|
}
|
||||||
|
|
||||||
path =
|
// Remove multiple as well as trailing slashes
|
||||||
path !== '/' && path.slice(path.length - 1) === '/'
|
path = path.replace(/\/+/g, '/');
|
||||||
? path.slice(0, -1)
|
path = path.length > 1 ? path.replace(/\/$/, '') : path;
|
||||||
: path;
|
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ type Options = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type RouteConfig = {
|
type RouteConfig = {
|
||||||
match: RegExp;
|
screen: string;
|
||||||
|
match: RegExp | null;
|
||||||
pattern: string;
|
pattern: string;
|
||||||
routeNames: string[];
|
routeNames: string[];
|
||||||
parse: ParseConfig | undefined;
|
parse: ParseConfig | undefined;
|
||||||
@@ -58,10 +59,8 @@ export default function getStateFromPath(
|
|||||||
path: string,
|
path: string,
|
||||||
options: Options = {}
|
options: Options = {}
|
||||||
): ResultState | undefined {
|
): ResultState | undefined {
|
||||||
if (path === '') {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
let initialRoutes: InitialRouteConfig[] = [];
|
let initialRoutes: InitialRouteConfig[] = [];
|
||||||
|
|
||||||
// Create a normalized configs array which will be easier to use
|
// Create a normalized configs array which will be easier to use
|
||||||
const configs = ([] as RouteConfig[]).concat(
|
const configs = ([] as RouteConfig[]).concat(
|
||||||
...Object.keys(options).map((key) =>
|
...Object.keys(options).map((key) =>
|
||||||
@@ -69,13 +68,45 @@ export default function getStateFromPath(
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
let result: PartialState<NavigationState> | undefined;
|
// sort configs so the most exhaustive is always first to be chosen
|
||||||
let current: PartialState<NavigationState> | undefined;
|
configs.sort(
|
||||||
|
(config1, config2) =>
|
||||||
|
config2.pattern.split('/').length - config1.pattern.split('/').length
|
||||||
|
);
|
||||||
|
|
||||||
let remaining = path
|
let remaining = path
|
||||||
.replace(/[/]+/, '/') // Replace multiple slash (//) with single ones
|
.replace(/\/+/g, '/') // Replace multiple slash (//) with single ones
|
||||||
.replace(/^\//, '') // Remove extra leading slash
|
.replace(/^\//, '') // Remove extra leading slash
|
||||||
.replace(/\?.*/, ''); // Remove query params which we will handle later
|
.replace(/\?.*$/, ''); // Remove query params which we will handle later
|
||||||
|
|
||||||
|
// Make sure there is a trailing slash
|
||||||
|
remaining = remaining.endsWith('/') ? remaining : `${remaining}/`;
|
||||||
|
|
||||||
|
if (remaining === '/') {
|
||||||
|
// We need to add special handling of empty path so navigation to empty path also works
|
||||||
|
// When handling empty path, we should only look at the root level config
|
||||||
|
const match = configs.find(
|
||||||
|
(config) =>
|
||||||
|
config.pattern === '' &&
|
||||||
|
config.routeNames.every(
|
||||||
|
// make sure that none of the parent configs have a non-empty path defined
|
||||||
|
(name) => !configs.find((c) => c.screen === name)?.pattern
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
return createNestedStateObject(
|
||||||
|
match.routeNames,
|
||||||
|
initialRoutes,
|
||||||
|
parseQueryParams(path, match.parse)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
let result: PartialState<NavigationState> | undefined;
|
||||||
|
let current: PartialState<NavigationState> | undefined;
|
||||||
|
|
||||||
while (remaining) {
|
while (remaining) {
|
||||||
let routeNames: string[] | undefined;
|
let routeNames: string[] | undefined;
|
||||||
@@ -83,6 +114,10 @@ export default function getStateFromPath(
|
|||||||
|
|
||||||
// Go through all configs, and see if the next path segment matches our regex
|
// Go through all configs, and see if the next path segment matches our regex
|
||||||
for (const config of configs) {
|
for (const config of configs) {
|
||||||
|
if (!config.match) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const match = remaining.match(config.match);
|
const match = remaining.match(config.match);
|
||||||
|
|
||||||
// If our regex matches, we need to extract params from the path
|
// If our regex matches, we need to extract params from the path
|
||||||
@@ -95,20 +130,21 @@ export default function getStateFromPath(
|
|||||||
|
|
||||||
if (paramPatterns.length) {
|
if (paramPatterns.length) {
|
||||||
params = paramPatterns.reduce<Record<string, any>>((acc, p, i) => {
|
params = paramPatterns.reduce<Record<string, any>>((acc, p, i) => {
|
||||||
const key = p.replace(/^:/, '');
|
const key = p.replace(/^:/, '').replace(/\?$/, '');
|
||||||
const value = match[i + 1]; // The param segments start from index 1 in the regex match result
|
const value = match[(i + 1) * 2].replace(/\//, ''); // The param segments appear every second item starting from 2 in the regex match result
|
||||||
|
|
||||||
|
if (value) {
|
||||||
acc[key] =
|
acc[key] =
|
||||||
config.parse && config.parse[key]
|
config.parse && config.parse[key]
|
||||||
? config.parse[key](value)
|
? config.parse[key](value)
|
||||||
: value;
|
: value;
|
||||||
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the matched segment from the remaining path
|
remaining = remaining.replace(match[1], '');
|
||||||
remaining = remaining.replace(match[0], '');
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -123,34 +159,7 @@ export default function getStateFromPath(
|
|||||||
remaining = segments.join('/');
|
remaining = segments.join('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
let state: InitialState;
|
const state = createNestedStateObject(routeNames, initialRoutes, params);
|
||||||
let routeName = routeNames.shift() as string;
|
|
||||||
let initialRoute = findInitialRoute(routeName, initialRoutes);
|
|
||||||
|
|
||||||
state = createNestedState(
|
|
||||||
initialRoute,
|
|
||||||
routeName,
|
|
||||||
routeNames.length === 0,
|
|
||||||
params
|
|
||||||
);
|
|
||||||
|
|
||||||
if (routeNames.length > 0) {
|
|
||||||
let nestedState = state;
|
|
||||||
|
|
||||||
while ((routeName = routeNames.shift() as string)) {
|
|
||||||
initialRoute = findInitialRoute(routeName, initialRoutes);
|
|
||||||
nestedState.routes[nestedState.index || 0].state = createNestedState(
|
|
||||||
initialRoute,
|
|
||||||
routeName,
|
|
||||||
routeNames.length === 0,
|
|
||||||
params
|
|
||||||
);
|
|
||||||
if (routeNames.length > 0) {
|
|
||||||
nestedState = nestedState.routes[nestedState.index || 0]
|
|
||||||
.state as InitialState;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current) {
|
if (current) {
|
||||||
// The state should be nested inside the deepest route we parsed before
|
// The state should be nested inside the deepest route we parsed before
|
||||||
@@ -172,29 +181,13 @@ export default function getStateFromPath(
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const query = path.split('?')[1];
|
const route = findFocusedRoute(current);
|
||||||
|
const params = parseQueryParams(
|
||||||
if (query) {
|
path,
|
||||||
while (current?.routes[current.index || 0].state) {
|
findParseConfigForRoute(route.name, configs)
|
||||||
// The query params apply to the deepest route
|
);
|
||||||
current = current.routes[current.index || 0].state;
|
|
||||||
}
|
|
||||||
|
|
||||||
const route = (current as PartialState<NavigationState>).routes[
|
|
||||||
current?.index || 0
|
|
||||||
];
|
|
||||||
|
|
||||||
const params = queryString.parse(query);
|
|
||||||
const parseFunction = findParseConfigForRoute(route.name, configs);
|
|
||||||
|
|
||||||
if (parseFunction) {
|
|
||||||
Object.keys(params).forEach((name) => {
|
|
||||||
if (parseFunction[name] && typeof params[name] === 'string') {
|
|
||||||
params[name] = parseFunction[name](params[name] as string);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (params) {
|
||||||
route.params = { ...route.params, ...params };
|
route.params = { ...route.params, ...params };
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,16 +208,15 @@ function createNormalizedConfigs(
|
|||||||
|
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
// If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern
|
// If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern
|
||||||
if (value !== '') {
|
configs.push(createConfigItem(key, routeNames, value));
|
||||||
configs.push(createConfigItem(routeNames, value));
|
|
||||||
}
|
|
||||||
} else if (typeof value === 'object') {
|
} else if (typeof value === 'object') {
|
||||||
// if an object is specified as the value (e.g. Foo: { ... }),
|
// if an object is specified as the value (e.g. Foo: { ... }),
|
||||||
// it can have `path` property and
|
// it can have `path` property and
|
||||||
// it could have `screens` prop which has nested configs
|
// it could have `screens` prop which has nested configs
|
||||||
if (value.path && value.path !== '') {
|
if (typeof value.path === 'string') {
|
||||||
configs.push(createConfigItem(routeNames, value.path, value.parse));
|
configs.push(createConfigItem(key, routeNames, value.path, value.parse));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.screens) {
|
if (value.screens) {
|
||||||
// property `initialRouteName` without `screens` has no purpose
|
// property `initialRouteName` without `screens` has no purpose
|
||||||
if (value.initialRouteName) {
|
if (value.initialRouteName) {
|
||||||
@@ -251,15 +243,28 @@ function createNormalizedConfigs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createConfigItem(
|
function createConfigItem(
|
||||||
|
screen: string,
|
||||||
routeNames: string[],
|
routeNames: string[],
|
||||||
pattern: string,
|
pattern: string,
|
||||||
parse?: ParseConfig
|
parse?: ParseConfig
|
||||||
): RouteConfig {
|
): RouteConfig {
|
||||||
const match = new RegExp(
|
const match = pattern
|
||||||
'^' + escape(pattern).replace(/:[a-z0-9]+/gi, '([^/]+)') + '/?'
|
? new RegExp(
|
||||||
);
|
`^(${pattern
|
||||||
|
.split('/')
|
||||||
|
.map((it) => {
|
||||||
|
if (it.startsWith(':')) {
|
||||||
|
return `(([^/]+\\/)${it.endsWith('?') ? '?' : ''})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${escape(it)}\\/`;
|
||||||
|
})
|
||||||
|
.join('')})`
|
||||||
|
)
|
||||||
|
: null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
screen,
|
||||||
match,
|
match,
|
||||||
pattern,
|
pattern,
|
||||||
// The routeNames array is mutated, so copy it to keep the current state
|
// The routeNames array is mutated, so copy it to keep the current state
|
||||||
@@ -295,9 +300,9 @@ function findInitialRoute(
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns nested state object with values depending on whether
|
// returns state object with values depending on whether
|
||||||
// it is the end of state and if there is initialRoute for this level
|
// it is the end of state and if there is initialRoute for this level
|
||||||
function createNestedState(
|
function createStateObject(
|
||||||
initialRoute: string | undefined,
|
initialRoute: string | undefined,
|
||||||
routeName: string,
|
routeName: string,
|
||||||
isEmpty: boolean,
|
isEmpty: boolean,
|
||||||
@@ -331,3 +336,73 @@ function createNestedState(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createNestedStateObject(
|
||||||
|
routeNames: string[],
|
||||||
|
initialRoutes: InitialRouteConfig[],
|
||||||
|
params: object | undefined
|
||||||
|
) {
|
||||||
|
let state: InitialState;
|
||||||
|
let routeName = routeNames.shift() as string;
|
||||||
|
let initialRoute = findInitialRoute(routeName, initialRoutes);
|
||||||
|
|
||||||
|
state = createStateObject(
|
||||||
|
initialRoute,
|
||||||
|
routeName,
|
||||||
|
routeNames.length === 0,
|
||||||
|
params
|
||||||
|
);
|
||||||
|
|
||||||
|
if (routeNames.length > 0) {
|
||||||
|
let nestedState = state;
|
||||||
|
|
||||||
|
while ((routeName = routeNames.shift() as string)) {
|
||||||
|
initialRoute = findInitialRoute(routeName, initialRoutes);
|
||||||
|
nestedState.routes[nestedState.index || 0].state = createStateObject(
|
||||||
|
initialRoute,
|
||||||
|
routeName,
|
||||||
|
routeNames.length === 0,
|
||||||
|
params
|
||||||
|
);
|
||||||
|
if (routeNames.length > 0) {
|
||||||
|
nestedState = nestedState.routes[nestedState.index || 0]
|
||||||
|
.state as InitialState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findFocusedRoute(state: InitialState) {
|
||||||
|
let current: InitialState | undefined = state;
|
||||||
|
|
||||||
|
while (current?.routes[current.index || 0].state) {
|
||||||
|
// The query params apply to the deepest route
|
||||||
|
current = current.routes[current.index || 0].state;
|
||||||
|
}
|
||||||
|
|
||||||
|
const route = (current as PartialState<NavigationState>).routes[
|
||||||
|
current?.index || 0
|
||||||
|
];
|
||||||
|
|
||||||
|
return route;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseQueryParams(
|
||||||
|
path: string,
|
||||||
|
parseConfig?: Record<string, (value: string) => any>
|
||||||
|
) {
|
||||||
|
const query = path.split('?')[1];
|
||||||
|
const params = queryString.parse(query);
|
||||||
|
|
||||||
|
if (parseConfig) {
|
||||||
|
Object.keys(params).forEach((name) => {
|
||||||
|
if (parseConfig[name] && typeof params[name] === 'string') {
|
||||||
|
params[name] = parseConfig[name](params[name] as string);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Object.keys(params).length ? params : undefined;
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import useNavigation from './useNavigation';
|
|||||||
*/
|
*/
|
||||||
export default function useIsFocused(): boolean {
|
export default function useIsFocused(): boolean {
|
||||||
const navigation = useNavigation();
|
const navigation = useNavigation();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
const getCurrentValue = React.useCallback(navigation.isFocused, [navigation]);
|
const getCurrentValue = React.useCallback(navigation.isFocused, [navigation]);
|
||||||
const subscribe = React.useCallback(
|
const subscribe = React.useCallback(
|
||||||
(callback: (value: boolean) => void) => {
|
(callback: (value: boolean) => void) => {
|
||||||
|
|||||||
@@ -362,9 +362,14 @@ export default function useNavigationBuilder<
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
// We need to clean up state for this navigator on unmount
|
// We need to clean up state for this navigator on unmount
|
||||||
|
// We do it in a timeout because we need to detect if another navigator mounted in the meantime
|
||||||
|
// For example, if another navigator has started rendering, we should skip cleanup
|
||||||
|
// Otherwise, our cleanup step will cleanup state for the other navigator and re-initialize it
|
||||||
|
setTimeout(() => {
|
||||||
if (getCurrentState() !== undefined && getKey() === navigatorKey) {
|
if (getCurrentState() !== undefined && getKey() === navigatorKey) {
|
||||||
setState(undefined);
|
setState(undefined);
|
||||||
}
|
}
|
||||||
|
}, 0);
|
||||||
};
|
};
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|||||||
@@ -3,6 +3,86 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [5.7.2](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.7.1...@react-navigation/drawer@5.7.2) (2020-05-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.7.1](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.7.0...@react-navigation/drawer@5.7.1) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.7.0](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.6.4...@react-navigation/drawer@5.7.0) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add generic type aliases for screen props ([bea14aa](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/bea14aa26fd5cbfebc7973733c5cf1f44fd323aa)), closes [#7971](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/issues/7971)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.6.4](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.6.3...@react-navigation/drawer@5.6.4) (2020-05-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.6.3](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.6.2...@react-navigation/drawer@5.6.3) (2020-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.6.2](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.6.1...@react-navigation/drawer@5.6.2) (2020-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.6.1](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.6.0...@react-navigation/drawer@5.6.1) (2020-04-30)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.6.0](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.5.1...@react-navigation/drawer@5.6.0) (2020-04-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix closing drawer on web with tap on overlay ([70be3f6](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/70be3f6d863c56211e2f90bdf743bd8526338248))
|
||||||
|
* make sure the address bar hides when scrolling on web ([0a19e94](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/0a19e94b23a4d2b5f22d1d9deb0544f586f475ee))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add `useLinkBuilder` hook to build links ([2792f43](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/2792f438fe45428fe193e3708fee7ad61966cbf4))
|
||||||
|
* add action prop to Link ([942d2be](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/commit/942d2be2c72720469475ce12ec8df23825994dbf))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.5.1](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.5.0...@react-navigation/drawer@5.5.1) (2020-04-27)
|
## [5.5.1](https://github.com/react-navigation/react-navigation/tree/master/packages/drawer/compare/@react-navigation/drawer@5.5.0...@react-navigation/drawer@5.5.1) (2020-04-27)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/drawer
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/drawer",
|
"name": "@react-navigation/drawer",
|
||||||
"description": "Drawer navigator component with animated transitions and gesturess",
|
"description": "Drawer navigator component with animated transitions and gesturess",
|
||||||
"version": "5.5.1",
|
"version": "5.7.2",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
"homepage": "https://reactnavigation.org/docs/drawer-navigator.html",
|
"homepage": "https://reactnavigation.org/docs/drawer-navigator.html",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
@@ -39,17 +40,17 @@
|
|||||||
"react-native-iphone-x-helper": "^1.2.1"
|
"react-native-iphone-x-helper": "^1.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.13.1",
|
||||||
"@react-navigation/native": "^5.1.7",
|
"@react-navigation/native": "^5.3.0",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.62.7",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-native": "~0.61.5",
|
"react-native": "~0.61.5",
|
||||||
"react-native-gesture-handler": "^1.6.0",
|
"react-native-gesture-handler": "^1.6.0",
|
||||||
"react-native-reanimated": "^1.7.0",
|
"react-native-reanimated": "^1.8.0",
|
||||||
"react-native-safe-area-context": "^0.7.3",
|
"react-native-safe-area-context": "^0.7.3",
|
||||||
"react-native-screens": "^2.3.0",
|
"react-native-screens": "^2.7.0",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export { default as useIsDrawerOpen } from './utils/useIsDrawerOpen';
|
|||||||
export type {
|
export type {
|
||||||
DrawerNavigationOptions,
|
DrawerNavigationOptions,
|
||||||
DrawerNavigationProp,
|
DrawerNavigationProp,
|
||||||
|
DrawerScreenProps,
|
||||||
DrawerContentOptions,
|
DrawerContentOptions,
|
||||||
DrawerContentComponentProps,
|
DrawerContentComponentProps,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|||||||
@@ -8,8 +8,9 @@ import {
|
|||||||
NavigationHelpers,
|
NavigationHelpers,
|
||||||
DrawerNavigationState,
|
DrawerNavigationState,
|
||||||
DrawerActionHelpers,
|
DrawerActionHelpers,
|
||||||
|
RouteProp,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
import { PanGestureHandler } from 'react-native-gesture-handler';
|
import type { PanGestureHandlerProperties } from 'react-native-gesture-handler';
|
||||||
|
|
||||||
export type Scene = {
|
export type Scene = {
|
||||||
route: Route<string>;
|
route: Route<string>;
|
||||||
@@ -32,6 +33,7 @@ export type DrawerNavigationConfig<T = DrawerContentOptions> = {
|
|||||||
drawerType?: 'front' | 'back' | 'slide' | 'permanent';
|
drawerType?: 'front' | 'back' | 'slide' | 'permanent';
|
||||||
/**
|
/**
|
||||||
* How far from the edge of the screen the swipe gesture should activate.
|
* How far from the edge of the screen the swipe gesture should activate.
|
||||||
|
* Not supported on Web.
|
||||||
*/
|
*/
|
||||||
edgeWidth?: number;
|
edgeWidth?: number;
|
||||||
/**
|
/**
|
||||||
@@ -58,8 +60,9 @@ export type DrawerNavigationConfig<T = DrawerContentOptions> = {
|
|||||||
statusBarAnimation?: 'slide' | 'none' | 'fade';
|
statusBarAnimation?: 'slide' | 'none' | 'fade';
|
||||||
/**
|
/**
|
||||||
* Props to pass to the underlying pan gesture handler.
|
* Props to pass to the underlying pan gesture handler.
|
||||||
|
* Not supported on Web.
|
||||||
*/
|
*/
|
||||||
gestureHandlerProps?: React.ComponentProps<typeof PanGestureHandler>;
|
gestureHandlerProps?: PanGestureHandlerProperties;
|
||||||
/**
|
/**
|
||||||
* Whether the screens should render the first time they are accessed. Defaults to `true`.
|
* Whether the screens should render the first time they are accessed. Defaults to `true`.
|
||||||
* Set it to `false` if you want to render all screens on initial render.
|
* Set it to `false` if you want to render all screens on initial render.
|
||||||
@@ -113,13 +116,15 @@ export type DrawerNavigationOptions = {
|
|||||||
* Whether you can use gestures to open or close the drawer.
|
* 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.
|
* Setting this to `false` disables swipe gestures as well as tap on overlay to close.
|
||||||
* See `swipeEnabled` to disable only the swipe gesture.
|
* See `swipeEnabled` to disable only the swipe gesture.
|
||||||
* Defaults to `true`
|
* Defaults to `true`.
|
||||||
|
* Not supported on Web.
|
||||||
*/
|
*/
|
||||||
gestureEnabled?: boolean;
|
gestureEnabled?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether you can use swipe gestures to open or close the drawer.
|
* Whether you can use swipe gestures to open or close the drawer.
|
||||||
* Defaults to `true`
|
* Defaults to `true`.
|
||||||
|
* Not supported on Web.
|
||||||
*/
|
*/
|
||||||
swipeEnabled?: boolean;
|
swipeEnabled?: boolean;
|
||||||
|
|
||||||
@@ -204,6 +209,14 @@ export type DrawerNavigationProp<
|
|||||||
> &
|
> &
|
||||||
DrawerActionHelpers<ParamList>;
|
DrawerActionHelpers<ParamList>;
|
||||||
|
|
||||||
|
export type DrawerScreenProps<
|
||||||
|
ParamList extends ParamListBase,
|
||||||
|
RouteName extends keyof ParamList = string
|
||||||
|
> = {
|
||||||
|
navigation: DrawerNavigationProp<ParamList, RouteName>;
|
||||||
|
route: RouteProp<ParamList, RouteName>;
|
||||||
|
};
|
||||||
|
|
||||||
export type DrawerDescriptor = Descriptor<
|
export type DrawerDescriptor = Descriptor<
|
||||||
ParamListBase,
|
ParamListBase,
|
||||||
string,
|
string,
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ import {
|
|||||||
StyleProp,
|
StyleProp,
|
||||||
View,
|
View,
|
||||||
InteractionManager,
|
InteractionManager,
|
||||||
|
TouchableWithoutFeedback,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
|
import Animated from 'react-native-reanimated';
|
||||||
import {
|
import {
|
||||||
PanGestureHandler,
|
PanGestureHandler,
|
||||||
TapGestureHandler,
|
TapGestureHandler,
|
||||||
State as GestureState,
|
GestureState,
|
||||||
TapGestureHandlerStateChangeEvent,
|
} from './GestureHandler';
|
||||||
} from 'react-native-gesture-handler';
|
|
||||||
import Animated from 'react-native-reanimated';
|
|
||||||
import Overlay from './Overlay';
|
import Overlay from './Overlay';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -79,7 +79,6 @@ type Props = {
|
|||||||
open: boolean;
|
open: boolean;
|
||||||
onOpen: () => void;
|
onOpen: () => void;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onGestureRef?: (ref: PanGestureHandler | null) => void;
|
|
||||||
gestureEnabled: boolean;
|
gestureEnabled: boolean;
|
||||||
swipeEnabled: boolean;
|
swipeEnabled: boolean;
|
||||||
drawerPosition: 'left' | 'right';
|
drawerPosition: 'left' | 'right';
|
||||||
@@ -511,18 +510,7 @@ export default class DrawerView extends React.Component<Props> {
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
private handleTapStateChange =
|
private handleTapStateChange = event([
|
||||||
Platform.OS === 'web'
|
|
||||||
? // FIXME: Drawer doesn't close on Web with the same code that we use for native
|
|
||||||
({ nativeEvent }: TapGestureHandlerStateChangeEvent) => {
|
|
||||||
if (
|
|
||||||
nativeEvent.state === GestureState.END &&
|
|
||||||
nativeEvent.oldState === GestureState.ACTIVE
|
|
||||||
) {
|
|
||||||
this.toggleDrawer(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
: event([
|
|
||||||
{
|
{
|
||||||
nativeEvent: {
|
nativeEvent: {
|
||||||
oldState: (s: Animated.Value<number>) =>
|
oldState: (s: Animated.Value<number>) =>
|
||||||
@@ -579,7 +567,6 @@ export default class DrawerView extends React.Component<Props> {
|
|||||||
sceneContainerStyle,
|
sceneContainerStyle,
|
||||||
drawerStyle,
|
drawerStyle,
|
||||||
overlayStyle,
|
overlayStyle,
|
||||||
onGestureRef,
|
|
||||||
renderDrawerContent,
|
renderDrawerContent,
|
||||||
renderSceneContent,
|
renderSceneContent,
|
||||||
gestureHandlerProps,
|
gestureHandlerProps,
|
||||||
@@ -624,7 +611,6 @@ export default class DrawerView extends React.Component<Props> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<PanGestureHandler
|
<PanGestureHandler
|
||||||
ref={onGestureRef}
|
|
||||||
activeOffsetX={[-SWIPE_DISTANCE_MINIMUM, SWIPE_DISTANCE_MINIMUM]}
|
activeOffsetX={[-SWIPE_DISTANCE_MINIMUM, SWIPE_DISTANCE_MINIMUM]}
|
||||||
failOffsetY={[-SWIPE_DISTANCE_MINIMUM, SWIPE_DISTANCE_MINIMUM]}
|
failOffsetY={[-SWIPE_DISTANCE_MINIMUM, SWIPE_DISTANCE_MINIMUM]}
|
||||||
onGestureEvent={this.handleGestureEvent}
|
onGestureEvent={this.handleGestureEvent}
|
||||||
@@ -663,12 +649,20 @@ export default class DrawerView extends React.Component<Props> {
|
|||||||
</View>
|
</View>
|
||||||
{
|
{
|
||||||
// Disable overlay if sidebar is permanent
|
// Disable overlay if sidebar is permanent
|
||||||
drawerType === 'permanent' ? null : (
|
drawerType === 'permanent' ? null : Platform.OS === 'web' ? (
|
||||||
|
<TouchableWithoutFeedback
|
||||||
|
onPress={
|
||||||
|
gestureEnabled ? () => this.toggleDrawer(false) : undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Overlay progress={progress} style={overlayStyle as any} />
|
||||||
|
</TouchableWithoutFeedback>
|
||||||
|
) : (
|
||||||
<TapGestureHandler
|
<TapGestureHandler
|
||||||
enabled={gestureEnabled}
|
enabled={gestureEnabled}
|
||||||
onHandlerStateChange={this.handleTapStateChange}
|
onHandlerStateChange={this.handleTapStateChange}
|
||||||
>
|
>
|
||||||
<Overlay progress={progress} style={overlayStyle} />
|
<Overlay progress={progress} style={overlayStyle as any} />
|
||||||
</TapGestureHandler>
|
</TapGestureHandler>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -737,6 +731,11 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
main: {
|
main: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
overflow: 'hidden',
|
...Platform.select({
|
||||||
|
// FIXME: We need to hide `overflowX` on Web so the translated content doesn't show offscreen.
|
||||||
|
// But adding `overflowX: 'hidden'` prevents content from collapsing the URL bar.
|
||||||
|
web: null,
|
||||||
|
default: { overflow: 'hidden' },
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,10 +11,6 @@ import {
|
|||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
// eslint-disable-next-line import/no-unresolved
|
// eslint-disable-next-line import/no-unresolved
|
||||||
import { ScreenContainer } from 'react-native-screens';
|
import { ScreenContainer } from 'react-native-screens';
|
||||||
import {
|
|
||||||
PanGestureHandler,
|
|
||||||
GestureHandlerRootView,
|
|
||||||
} from 'react-native-gesture-handler';
|
|
||||||
import {
|
import {
|
||||||
NavigationHelpersContext,
|
NavigationHelpersContext,
|
||||||
DrawerNavigationState,
|
DrawerNavigationState,
|
||||||
@@ -22,7 +18,7 @@ import {
|
|||||||
useTheme,
|
useTheme,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
|
|
||||||
import DrawerGestureContext from '../utils/DrawerGestureContext';
|
import { GestureHandlerRootView } from './GestureHandler';
|
||||||
import SafeAreaProviderCompat from './SafeAreaProviderCompat';
|
import SafeAreaProviderCompat from './SafeAreaProviderCompat';
|
||||||
import ResourceSavingScene from './ResourceSavingScene';
|
import ResourceSavingScene from './ResourceSavingScene';
|
||||||
import DrawerContent from './DrawerContent';
|
import DrawerContent from './DrawerContent';
|
||||||
@@ -94,8 +90,6 @@ export default function DrawerView({
|
|||||||
Dimensions.get('window')
|
Dimensions.get('window')
|
||||||
);
|
);
|
||||||
|
|
||||||
const drawerGestureRef = React.useRef<PanGestureHandler>(null);
|
|
||||||
|
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
|
|
||||||
const isDrawerOpen = state.history.some((it) => it.type === 'drawer');
|
const isDrawerOpen = state.history.some((it) => it.type === 'drawer');
|
||||||
@@ -205,7 +199,6 @@ export default function DrawerView({
|
|||||||
<NavigationHelpersContext.Provider value={navigation}>
|
<NavigationHelpersContext.Provider value={navigation}>
|
||||||
<GestureHandlerWrapper style={styles.content}>
|
<GestureHandlerWrapper style={styles.content}>
|
||||||
<SafeAreaProviderCompat>
|
<SafeAreaProviderCompat>
|
||||||
<DrawerGestureContext.Provider value={drawerGestureRef}>
|
|
||||||
<DrawerOpenContext.Provider value={isDrawerOpen}>
|
<DrawerOpenContext.Provider value={isDrawerOpen}>
|
||||||
<Drawer
|
<Drawer
|
||||||
open={isDrawerOpen}
|
open={isDrawerOpen}
|
||||||
@@ -213,10 +206,6 @@ export default function DrawerView({
|
|||||||
swipeEnabled={swipeEnabled}
|
swipeEnabled={swipeEnabled}
|
||||||
onOpen={handleDrawerOpen}
|
onOpen={handleDrawerOpen}
|
||||||
onClose={handleDrawerClose}
|
onClose={handleDrawerClose}
|
||||||
onGestureRef={(ref) => {
|
|
||||||
// @ts-ignore
|
|
||||||
drawerGestureRef.current = ref;
|
|
||||||
}}
|
|
||||||
gestureHandlerProps={gestureHandlerProps}
|
gestureHandlerProps={gestureHandlerProps}
|
||||||
drawerType={drawerType}
|
drawerType={drawerType}
|
||||||
drawerPosition={drawerPosition}
|
drawerPosition={drawerPosition}
|
||||||
@@ -253,7 +242,6 @@ export default function DrawerView({
|
|||||||
dimensions={dimensions}
|
dimensions={dimensions}
|
||||||
/>
|
/>
|
||||||
</DrawerOpenContext.Provider>
|
</DrawerOpenContext.Provider>
|
||||||
</DrawerGestureContext.Provider>
|
|
||||||
</SafeAreaProviderCompat>
|
</SafeAreaProviderCompat>
|
||||||
</GestureHandlerWrapper>
|
</GestureHandlerWrapper>
|
||||||
</NavigationHelpersContext.Provider>
|
</NavigationHelpersContext.Provider>
|
||||||
|
|||||||
23
packages/drawer/src/views/GestureHandler.native.tsx
Normal file
23
packages/drawer/src/views/GestureHandler.native.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import {
|
||||||
|
PanGestureHandler as PanGestureHandlerNative,
|
||||||
|
PanGestureHandlerProperties,
|
||||||
|
} from 'react-native-gesture-handler';
|
||||||
|
import DrawerGestureContext from '../utils/DrawerGestureContext';
|
||||||
|
|
||||||
|
export function PanGestureHandler(props: PanGestureHandlerProperties) {
|
||||||
|
const gestureRef = React.useRef<PanGestureHandlerNative>(null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DrawerGestureContext.Provider value={gestureRef}>
|
||||||
|
<PanGestureHandlerNative {...props} />
|
||||||
|
</DrawerGestureContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
GestureHandlerRootView,
|
||||||
|
TapGestureHandler,
|
||||||
|
State as GestureState,
|
||||||
|
PanGestureHandlerGestureEvent,
|
||||||
|
} from 'react-native-gesture-handler';
|
||||||
31
packages/drawer/src/views/GestureHandler.tsx
Normal file
31
packages/drawer/src/views/GestureHandler.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { View } from 'react-native';
|
||||||
|
import type {
|
||||||
|
PanGestureHandlerProperties,
|
||||||
|
TapGestureHandlerProperties,
|
||||||
|
} from 'react-native-gesture-handler';
|
||||||
|
|
||||||
|
const Dummy: any = ({ children }: { children: React.ReactNode }) => (
|
||||||
|
<>{children}</>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const PanGestureHandler = Dummy as React.ComponentType<
|
||||||
|
PanGestureHandlerProperties
|
||||||
|
>;
|
||||||
|
|
||||||
|
export const TapGestureHandler = Dummy as React.ComponentType<
|
||||||
|
TapGestureHandlerProperties
|
||||||
|
>;
|
||||||
|
|
||||||
|
export const GestureHandlerRootView = View;
|
||||||
|
|
||||||
|
export const GestureState = {
|
||||||
|
UNDETERMINED: 0,
|
||||||
|
FAILED: 1,
|
||||||
|
BEGAN: 2,
|
||||||
|
CANCELLED: 3,
|
||||||
|
ACTIVE: 4,
|
||||||
|
END: 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type { PanGestureHandlerGestureEvent } from 'react-native-gesture-handler';
|
||||||
@@ -29,7 +29,7 @@ export default class ResourceSavingScene extends React.Component<Props> {
|
|||||||
styles.container,
|
styles.container,
|
||||||
Platform.OS === 'web'
|
Platform.OS === 'web'
|
||||||
? { display: isVisible ? 'flex' : 'none' }
|
? { display: isVisible ? 'flex' : 'none' }
|
||||||
: null,
|
: { overflow: 'hidden' },
|
||||||
style,
|
style,
|
||||||
]}
|
]}
|
||||||
collapsable={false}
|
collapsable={false}
|
||||||
@@ -52,7 +52,6 @@ export default class ResourceSavingScene extends React.Component<Props> {
|
|||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
overflow: 'hidden',
|
|
||||||
},
|
},
|
||||||
attached: {
|
attached: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
|||||||
@@ -3,6 +3,77 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [5.2.2](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.2.1...@react-navigation/material-bottom-tabs@5.2.2) (2020-05-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.2.0...@react-navigation/material-bottom-tabs@5.2.1) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.2.0](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.15...@react-navigation/material-bottom-tabs@5.2.0) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add generic type aliases for screen props ([bea14aa](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/commit/bea14aa26fd5cbfebc7973733c5cf1f44fd323aa)), closes [#7971](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/issues/7971)
|
||||||
|
* use links in bottom navigation tabs ([f384706](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/commit/f384706741f7e2422c284b65da10425f7af680c0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.15](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.14...@react-navigation/material-bottom-tabs@5.1.15) (2020-05-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.14](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.13...@react-navigation/material-bottom-tabs@5.1.14) (2020-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.13](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.12...@react-navigation/material-bottom-tabs@5.1.13) (2020-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.12](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.11...@react-navigation/material-bottom-tabs@5.1.12) (2020-04-30)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.11](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.10...@react-navigation/material-bottom-tabs@5.1.11) (2020-04-30)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.1.10](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.9...@react-navigation/material-bottom-tabs@5.1.10) (2020-04-27)
|
## [5.1.10](https://github.com/react-navigation/react-navigation/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.1.9...@react-navigation/material-bottom-tabs@5.1.10) (2020-04-27)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/material-bottom-tabs",
|
"name": "@react-navigation/material-bottom-tabs",
|
||||||
"description": "Integration for bottom navigation component from react-native-paper",
|
"description": "Integration for bottom navigation component from react-native-paper",
|
||||||
"version": "5.1.10",
|
"version": "5.2.2",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
"homepage": "https://reactnavigation.org/docs/material-bottom-tab-navigator.html",
|
"homepage": "https://reactnavigation.org/docs/material-bottom-tab-navigator.html",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
@@ -35,15 +36,15 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.13.1",
|
||||||
"@react-navigation/native": "^5.1.7",
|
"@react-navigation/native": "^5.3.0",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.62.7",
|
||||||
"@types/react-native-vector-icons": "^6.4.5",
|
"@types/react-native-vector-icons": "^6.4.5",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-native": "~0.61.5",
|
"react-native": "~0.61.5",
|
||||||
"react-native-paper": "^3.7.0",
|
"react-native-paper": "^3.10.1",
|
||||||
"react-native-vector-icons": "^6.6.0",
|
"react-native-vector-icons": "^6.6.0",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,4 +14,5 @@ export { default as MaterialBottomTabView } from './views/MaterialBottomTabView'
|
|||||||
export type {
|
export type {
|
||||||
MaterialBottomTabNavigationOptions,
|
MaterialBottomTabNavigationOptions,
|
||||||
MaterialBottomTabNavigationProp,
|
MaterialBottomTabNavigationProp,
|
||||||
|
MaterialBottomTabScreenProps,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
NavigationHelpers,
|
NavigationHelpers,
|
||||||
TabNavigationState,
|
TabNavigationState,
|
||||||
TabActionHelpers,
|
TabActionHelpers,
|
||||||
|
RouteProp,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
|
|
||||||
export type MaterialBottomTabNavigationEventMap = {
|
export type MaterialBottomTabNavigationEventMap = {
|
||||||
@@ -32,6 +33,14 @@ export type MaterialBottomTabNavigationProp<
|
|||||||
> &
|
> &
|
||||||
TabActionHelpers<ParamList>;
|
TabActionHelpers<ParamList>;
|
||||||
|
|
||||||
|
export type MaterialBottomTabScreenProps<
|
||||||
|
ParamList extends ParamListBase,
|
||||||
|
RouteName extends keyof ParamList = string
|
||||||
|
> = {
|
||||||
|
navigation: MaterialBottomTabNavigationProp<ParamList, RouteName>;
|
||||||
|
route: RouteProp<ParamList, RouteName>;
|
||||||
|
};
|
||||||
|
|
||||||
export type MaterialBottomTabNavigationOptions = {
|
export type MaterialBottomTabNavigationOptions = {
|
||||||
/**
|
/**
|
||||||
* Title text for the screen.
|
* Title text for the screen.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { StyleSheet } from 'react-native';
|
import { StyleSheet, Platform } from 'react-native';
|
||||||
import { BottomNavigation, DefaultTheme, DarkTheme } from 'react-native-paper';
|
import { BottomNavigation, DefaultTheme, DarkTheme } from 'react-native-paper';
|
||||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
import {
|
import {
|
||||||
@@ -8,6 +8,8 @@ import {
|
|||||||
TabNavigationState,
|
TabNavigationState,
|
||||||
TabActions,
|
TabActions,
|
||||||
useTheme,
|
useTheme,
|
||||||
|
useLinkBuilder,
|
||||||
|
Link,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -24,13 +26,14 @@ type Props = MaterialBottomTabNavigationConfig & {
|
|||||||
|
|
||||||
type Scene = { route: { key: string } };
|
type Scene = { route: { key: string } };
|
||||||
|
|
||||||
export default function MaterialBottomTabView({
|
function MaterialBottomTabViewInner({
|
||||||
state,
|
state,
|
||||||
navigation,
|
navigation,
|
||||||
descriptors,
|
descriptors,
|
||||||
...rest
|
...rest
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const { dark, colors } = useTheme();
|
const { dark, colors } = useTheme();
|
||||||
|
const buildLink = useLinkBuilder();
|
||||||
|
|
||||||
const theme = React.useMemo(() => {
|
const theme = React.useMemo(() => {
|
||||||
const t = dark ? DarkTheme : DefaultTheme;
|
const t = dark ? DarkTheme : DefaultTheme;
|
||||||
@@ -46,7 +49,6 @@ export default function MaterialBottomTabView({
|
|||||||
}, [colors, dark]);
|
}, [colors, dark]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavigationHelpersContext.Provider value={navigation}>
|
|
||||||
<BottomNavigation
|
<BottomNavigation
|
||||||
{...rest}
|
{...rest}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
@@ -58,6 +60,37 @@ export default function MaterialBottomTabView({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
renderScene={({ route }) => descriptors[route.key].render()}
|
renderScene={({ route }) => descriptors[route.key].render()}
|
||||||
|
renderTouchable={
|
||||||
|
Platform.OS === 'web'
|
||||||
|
? ({
|
||||||
|
onPress,
|
||||||
|
route,
|
||||||
|
accessibilityRole: _0,
|
||||||
|
borderless: _1,
|
||||||
|
centered: _2,
|
||||||
|
rippleColor: _3,
|
||||||
|
...rest
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
{...rest}
|
||||||
|
// @ts-ignore
|
||||||
|
to={buildLink(route.name, route.params)}
|
||||||
|
accessibilityRole="link"
|
||||||
|
onPress={(e: any) => {
|
||||||
|
if (
|
||||||
|
!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) && // ignore clicks with modifier keys
|
||||||
|
(e.button == null || e.button === 0) // ignore everything but left clicks
|
||||||
|
) {
|
||||||
|
e.preventDefault();
|
||||||
|
onPress?.(e);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
renderIcon={({ route, focused, color }) => {
|
renderIcon={({ route, focused, color }) => {
|
||||||
const { options } = descriptors[route.key];
|
const { options } = descriptors[route.key];
|
||||||
|
|
||||||
@@ -68,8 +101,6 @@ export default function MaterialBottomTabView({
|
|||||||
color={color}
|
color={color}
|
||||||
size={24}
|
size={24}
|
||||||
style={styles.icon}
|
style={styles.icon}
|
||||||
importantForAccessibility="no-hide-descendants"
|
|
||||||
accessibilityElementsHidden
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -107,6 +138,13 @@ export default function MaterialBottomTabView({
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function MaterialBottomTabView(props: Props) {
|
||||||
|
return (
|
||||||
|
<NavigationHelpersContext.Provider value={props.navigation}>
|
||||||
|
<MaterialBottomTabViewInner {...props} />
|
||||||
</NavigationHelpersContext.Provider>
|
</NavigationHelpersContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,76 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [5.2.2](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.2.1...@react-navigation/material-top-tabs@5.2.2) (2020-05-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.2.0...@react-navigation/material-top-tabs@5.2.1) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.2.0](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.15...@react-navigation/material-top-tabs@5.2.0) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add generic type aliases for screen props ([bea14aa](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/commit/bea14aa26fd5cbfebc7973733c5cf1f44fd323aa)), closes [#7971](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/issues/7971)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.15](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.14...@react-navigation/material-top-tabs@5.1.15) (2020-05-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.14](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.13...@react-navigation/material-top-tabs@5.1.14) (2020-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.13](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.12...@react-navigation/material-top-tabs@5.1.13) (2020-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.12](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.11...@react-navigation/material-top-tabs@5.1.12) (2020-04-30)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.1.11](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.10...@react-navigation/material-top-tabs@5.1.11) (2020-04-30)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.1.10](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.9...@react-navigation/material-top-tabs@5.1.10) (2020-04-27)
|
## [5.1.10](https://github.com/react-navigation/react-navigation/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.1.9...@react-navigation/material-top-tabs@5.1.10) (2020-04-27)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/material-top-tabs",
|
"name": "@react-navigation/material-top-tabs",
|
||||||
"description": "Integration for the animated tab view component from react-native-tab-view",
|
"description": "Integration for the animated tab view component from react-native-tab-view",
|
||||||
"version": "5.1.10",
|
"version": "5.2.2",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
"homepage": "https://reactnavigation.org/docs/material-top-tab-navigator.html",
|
"homepage": "https://reactnavigation.org/docs/material-top-tab-navigator.html",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
@@ -38,15 +39,15 @@
|
|||||||
"color": "^3.1.2"
|
"color": "^3.1.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.13.1",
|
||||||
"@react-navigation/native": "^5.1.7",
|
"@react-navigation/native": "^5.3.0",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.62.7",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-native": "~0.61.5",
|
"react-native": "~0.61.5",
|
||||||
"react-native-gesture-handler": "^1.6.0",
|
"react-native-gesture-handler": "^1.6.0",
|
||||||
"react-native-reanimated": "^1.7.0",
|
"react-native-reanimated": "^1.8.0",
|
||||||
"react-native-tab-view": "^2.14.0",
|
"react-native-tab-view": "^2.14.0",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ export { default as MaterialTopTabBar } from './views/MaterialTopTabBar';
|
|||||||
export type {
|
export type {
|
||||||
MaterialTopTabNavigationOptions,
|
MaterialTopTabNavigationOptions,
|
||||||
MaterialTopTabNavigationProp,
|
MaterialTopTabNavigationProp,
|
||||||
|
MaterialTopTabScreenProps,
|
||||||
MaterialTopTabBarProps,
|
MaterialTopTabBarProps,
|
||||||
MaterialTopTabBarOptions,
|
MaterialTopTabBarOptions,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
NavigationProp,
|
NavigationProp,
|
||||||
TabNavigationState,
|
TabNavigationState,
|
||||||
TabActionHelpers,
|
TabActionHelpers,
|
||||||
|
RouteProp,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
|
|
||||||
export type MaterialTopTabNavigationEventMap = {
|
export type MaterialTopTabNavigationEventMap = {
|
||||||
@@ -46,6 +47,14 @@ export type MaterialTopTabNavigationProp<
|
|||||||
> &
|
> &
|
||||||
TabActionHelpers<ParamList>;
|
TabActionHelpers<ParamList>;
|
||||||
|
|
||||||
|
export type MaterialTopTabScreenProps<
|
||||||
|
ParamList extends ParamListBase,
|
||||||
|
RouteName extends keyof ParamList = string
|
||||||
|
> = {
|
||||||
|
navigation: MaterialTopTabNavigationProp<ParamList, RouteName>;
|
||||||
|
route: RouteProp<ParamList, RouteName>;
|
||||||
|
};
|
||||||
|
|
||||||
export type MaterialTopTabNavigationOptions = {
|
export type MaterialTopTabNavigationOptions = {
|
||||||
/**
|
/**
|
||||||
* Title text for the screen.
|
* Title text for the screen.
|
||||||
|
|||||||
@@ -3,6 +3,103 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [5.3.0](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.2.6...@react-navigation/native@5.3.0) (2020-05-10)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* initialState should take priority over deep link ([039017b](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/039017bc2af69120d2d10e8f2c8a62919c37eb65))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.6](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.2.5...@react-navigation/native@5.2.6) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/native/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.5](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.2.4...@react-navigation/native@5.2.5) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* return a promise-like from getInitialState ([#8210](https://github.com/react-navigation/react-navigation/tree/master/packages/native/issues/8210)) ([85ae378](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/85ae378d8cb1073895b281e13ebccee881d4c062))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.4](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.2.3...@react-navigation/native@5.2.4) (2020-05-05)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* return undefined for buildLink if linking is not enabled ([9fd2635](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/9fd2635756362c8da79656b4d9b101bebaaf7003))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.3](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.2.2...@react-navigation/native@5.2.3) (2020-05-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* default linking enabled to true ([c7b8e2e](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/c7b8e2e9666733143eef156b27f3e4995c36b856))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.2](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.2.1...@react-navigation/native@5.2.2) (2020-05-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* don't throw when using 'useLinking'. fixes [#8171](https://github.com/react-navigation/react-navigation/tree/master/packages/native/issues/8171) ([10eca8b](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/10eca8b92edbce6dbef8abaf189e4b59a29b3748))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.1](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.2.0...@react-navigation/native@5.2.1) (2020-04-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* render fallback only if linking is enabled. closes [#8161](https://github.com/react-navigation/react-navigation/tree/master/packages/native/issues/8161) ([1c075ff](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/1c075ffb169d233ed0515efea264a5a69b4de52e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.2.0](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.1.7...@react-navigation/native@5.2.0) (2020-04-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add catch to thenable returned by getInitialState ([d6fa279](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/d6fa279d9371c7a6403d10d209a2a64147891c63))
|
||||||
|
* return onPress instead of onClick for useLinkProps ([ae5442e](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/ae5442ebe812b91fa1f12164f27d1aeed918ab0e))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add `useLinkBuilder` hook to build links ([2792f43](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/2792f438fe45428fe193e3708fee7ad61966cbf4))
|
||||||
|
* add a useLinkProps hook ([f2291d1](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/f2291d110faa2aa8e10c9133c1c0c28d54af7917))
|
||||||
|
* add action prop to Link ([942d2be](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/942d2be2c72720469475ce12ec8df23825994dbf))
|
||||||
|
* add Link component as useLinkTo hook for navigating to links ([2573b5b](https://github.com/react-navigation/react-navigation/tree/master/packages/native/commit/2573b5beaac1240434e52f3f57bb29da2f541c88))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.1.7](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.1.6...@react-navigation/native@5.1.7) (2020-04-27)
|
## [5.1.7](https://github.com/react-navigation/react-navigation/tree/master/packages/native/compare/@react-navigation/native@5.1.6...@react-navigation/native@5.1.7) (2020-04-27)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/native
|
**Note:** Version bump only for package @react-navigation/native
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/native",
|
"name": "@react-navigation/native",
|
||||||
"description": "React Native integration for React Navigation",
|
"description": "React Native integration for React Navigation",
|
||||||
"version": "5.1.7",
|
"version": "5.3.0",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native",
|
"react-native",
|
||||||
"react-navigation",
|
"react-navigation",
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
"homepage": "https://reactnavigation.org",
|
"homepage": "https://reactnavigation.org",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
@@ -31,16 +32,16 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/core": "^5.3.5"
|
"@react-navigation/core": "^5.5.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.13.1",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.62.7",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-native": "~0.61.5",
|
"react-native": "~0.61.5",
|
||||||
"react-native-testing-library": "^1.12.0",
|
"react-native-testing-library": "^1.13.2",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Text, TextProps, GestureResponderEvent } from 'react-native';
|
import { Text, TextProps, GestureResponderEvent, Platform } from 'react-native';
|
||||||
import { NavigationAction } from '@react-navigation/core';
|
import { NavigationAction } from '@react-navigation/core';
|
||||||
import useLinkProps from './useLinkProps';
|
import useLinkProps from './useLinkProps';
|
||||||
|
|
||||||
@@ -28,16 +28,15 @@ export default function Link({ to, action, ...rest }: Props) {
|
|||||||
rest.onPress?.(e);
|
rest.onPress?.(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props.onClick) {
|
|
||||||
props.onClick(e);
|
|
||||||
} else {
|
|
||||||
props.onPress(e);
|
props.onPress(e);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return React.createElement(Text, {
|
return React.createElement(Text, {
|
||||||
...props,
|
...props,
|
||||||
...rest,
|
...rest,
|
||||||
...(props.onClick ? { onClick: onPress } : { onPress }),
|
...Platform.select({
|
||||||
|
web: { onClick: onPress } as any,
|
||||||
|
default: { onPress },
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ type Props = NavigationContainerProps & {
|
|||||||
* Container component which holds the navigation state designed for React Native apps.
|
* Container component which holds the navigation state designed for React Native apps.
|
||||||
* This should be rendered at the root wrapping the whole app.
|
* This should be rendered at the root wrapping the whole app.
|
||||||
*
|
*
|
||||||
* @param props.initialState Initial state object for the navigation tree. When deep link handling is enabled, this will be ignored if there's an incoming link.
|
* @param props.initialState Initial state object for the navigation tree. When deep link handling is enabled, this will override deep links when specified. Make sure that you don't specify an `initialState` when there's a deep link (`Linking.getInitialURL()`).
|
||||||
* @param props.onStateChange Callback which is called with the latest navigation state when it changes.
|
* @param props.onStateChange Callback which is called with the latest navigation state when it changes.
|
||||||
* @param props.theme Theme object for the navigators.
|
* @param props.theme Theme object for the navigators.
|
||||||
* @param props.linking Options for deep linking. Deep link handling is enabled when this prop is provided, unless `linking.enabled` is `false`.
|
* @param props.linking Options for deep linking. Deep link handling is enabled when this prop is provided, unless `linking.enabled` is `false`.
|
||||||
@@ -46,15 +46,13 @@ const NavigationContainer = React.forwardRef(function NavigationContainer(
|
|||||||
...linking,
|
...linking,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [isReady, initialState = rest.initialState] = useThenable(
|
const [isReady, initialState] = useThenable(getInitialState);
|
||||||
getInitialState
|
|
||||||
);
|
|
||||||
|
|
||||||
React.useImperativeHandle(ref, () => refContainer.current);
|
React.useImperativeHandle(ref, () => refContainer.current);
|
||||||
|
|
||||||
const linkingContext = React.useMemo(() => ({ options: linking }), [linking]);
|
const linkingContext = React.useMemo(() => ({ options: linking }), [linking]);
|
||||||
|
|
||||||
if (!isReady) {
|
if (rest.initialState == null && isLinkingEnabled && !isReady) {
|
||||||
// This is temporary until we have Suspense for data-fetching
|
// This is temporary until we have Suspense for data-fetching
|
||||||
// Then the fallback will be handled by a parent `Suspense` component
|
// Then the fallback will be handled by a parent `Suspense` component
|
||||||
return fallback as React.ReactElement;
|
return fallback as React.ReactElement;
|
||||||
@@ -65,7 +63,9 @@ const NavigationContainer = React.forwardRef(function NavigationContainer(
|
|||||||
<ThemeProvider value={theme}>
|
<ThemeProvider value={theme}>
|
||||||
<BaseNavigationContainer
|
<BaseNavigationContainer
|
||||||
{...rest}
|
{...rest}
|
||||||
initialState={initialState}
|
initialState={
|
||||||
|
rest.initialState == null ? initialState : rest.initialState
|
||||||
|
}
|
||||||
ref={refContainer}
|
ref={refContainer}
|
||||||
/>
|
/>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ it('throws if multiple instances of useLinking are used', () => {
|
|||||||
let element;
|
let element;
|
||||||
|
|
||||||
expect(() => (element = render(<Sample />))).toThrowError(
|
expect(() => (element = render(<Sample />))).toThrowError(
|
||||||
"Looks like you are using 'useLinking' in multiple components."
|
'Looks like you have configured linking in multiple places.'
|
||||||
);
|
);
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@@ -41,9 +41,7 @@ it('throws if multiple instances of useLinking are used', () => {
|
|||||||
<B />
|
<B />
|
||||||
</>
|
</>
|
||||||
))
|
))
|
||||||
).toThrowError(
|
).toThrowError('Looks like you have configured linking in multiple places.');
|
||||||
"Looks like you are using 'useLinking' in multiple components."
|
|
||||||
);
|
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
element?.unmount();
|
element?.unmount();
|
||||||
@@ -57,5 +55,19 @@ it('throws if multiple instances of useLinking are used', () => {
|
|||||||
|
|
||||||
render(wrapper2).unmount();
|
render(wrapper2).unmount();
|
||||||
|
|
||||||
expect(() => render(wrapper2)).not.toThrow();
|
expect(() => (element = render(wrapper2))).not.toThrow();
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
element?.unmount();
|
||||||
|
|
||||||
|
function Sample3() {
|
||||||
|
useLinking(ref, options);
|
||||||
|
useLinking(ref, { ...options, enabled: false });
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(() => (element = render(<Sample3 />))).not.toThrowError();
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
element?.unmount();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -52,14 +52,18 @@ export default function useLinkBuilder() {
|
|||||||
(name: string, params?: object) => {
|
(name: string, params?: object) => {
|
||||||
const { options } = linking;
|
const { options } = linking;
|
||||||
|
|
||||||
// If we couldn't find a navigation object in context, we're at root
|
if (options?.enabled === false) {
|
||||||
// So we'll construct a basic state object to use
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
const state = navigation
|
const state = navigation
|
||||||
? getRootStateForNavigate(navigation, {
|
? getRootStateForNavigate(navigation, {
|
||||||
index: 0,
|
index: 0,
|
||||||
routes: [{ name, params }],
|
routes: [{ name, params }],
|
||||||
})
|
})
|
||||||
: {
|
: // If we couldn't find a navigation object in context, we're at root
|
||||||
|
// So we'll construct a basic state object to use
|
||||||
|
{
|
||||||
index: 0,
|
index: 0,
|
||||||
routes: [{ name, params }],
|
routes: [{ name, params }],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -49,6 +49,14 @@ export default function useLinkProps({ to, action }: Props) {
|
|||||||
throw new Error("Couldn't find a navigation object.");
|
throw new Error("Couldn't find a navigation object.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (typeof to !== 'string') {
|
||||||
|
throw new Error(
|
||||||
|
`To 'to' option is invalid (found '${String(
|
||||||
|
to
|
||||||
|
)}'. It must be a valid string for navigation.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
linkTo(to);
|
linkTo(to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,9 +65,6 @@ export default function useLinkProps({ to, action }: Props) {
|
|||||||
return {
|
return {
|
||||||
href: to,
|
href: to,
|
||||||
accessibilityRole: 'link' as const,
|
accessibilityRole: 'link' as const,
|
||||||
...Platform.select({
|
onPress,
|
||||||
web: { onClick: onPress } as any,
|
|
||||||
default: { onPress },
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,22 +12,28 @@ let isUsingLinking = false;
|
|||||||
export default function useLinking(
|
export default function useLinking(
|
||||||
ref: React.RefObject<NavigationContainerRef>,
|
ref: React.RefObject<NavigationContainerRef>,
|
||||||
{
|
{
|
||||||
enabled,
|
enabled = true,
|
||||||
prefixes,
|
prefixes,
|
||||||
config,
|
config,
|
||||||
getStateFromPath = getStateFromPathDefault,
|
getStateFromPath = getStateFromPathDefault,
|
||||||
}: LinkingOptions
|
}: LinkingOptions
|
||||||
) {
|
) {
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (isUsingLinking) {
|
if (enabled !== false && isUsingLinking) {
|
||||||
throw new Error(
|
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." +
|
[
|
||||||
(Platform.OS === 'android'
|
'Looks like you have configured linking in multiple places. This is likely an error since deep links should only be handled in one place to avoid conflicts. Make sure that:',
|
||||||
? "\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."
|
"- You are not using both 'linking' prop and 'useLinking'",
|
||||||
: '')
|
"- You don't have 'useLinking' in multiple components",
|
||||||
|
Platform.OS === 'android'
|
||||||
|
? "- You have set 'android:launchMode=singleTask' in the '<activity />' section of the 'AndroidManifest.xml' file to avoid launching multiple instances"
|
||||||
|
: '',
|
||||||
|
]
|
||||||
|
.join('\n')
|
||||||
|
.trim()
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
isUsingLinking = true;
|
isUsingLinking = enabled !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
|||||||
@@ -10,6 +10,15 @@ import { LinkingOptions } from './types';
|
|||||||
|
|
||||||
type ResultState = ReturnType<typeof getStateFromPathDefault>;
|
type ResultState = ReturnType<typeof getStateFromPathDefault>;
|
||||||
|
|
||||||
|
type HistoryState = { index: number };
|
||||||
|
|
||||||
|
declare const history: {
|
||||||
|
state?: HistoryState;
|
||||||
|
go(delta: number): void;
|
||||||
|
pushState(state: HistoryState, title: string, url: string): void;
|
||||||
|
replaceState(state: HistoryState, title: string, url: string): void;
|
||||||
|
};
|
||||||
|
|
||||||
const getStateLength = (state: NavigationState) => {
|
const getStateLength = (state: NavigationState) => {
|
||||||
let length = 0;
|
let length = 0;
|
||||||
|
|
||||||
@@ -34,19 +43,25 @@ let isUsingLinking = false;
|
|||||||
export default function useLinking(
|
export default function useLinking(
|
||||||
ref: React.RefObject<NavigationContainerRef>,
|
ref: React.RefObject<NavigationContainerRef>,
|
||||||
{
|
{
|
||||||
enabled,
|
enabled = true,
|
||||||
config,
|
config,
|
||||||
getStateFromPath = getStateFromPathDefault,
|
getStateFromPath = getStateFromPathDefault,
|
||||||
getPathFromState = getPathFromStateDefault,
|
getPathFromState = getPathFromStateDefault,
|
||||||
}: LinkingOptions
|
}: LinkingOptions
|
||||||
) {
|
) {
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (isUsingLinking) {
|
if (enabled !== false && isUsingLinking) {
|
||||||
throw new Error(
|
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. Also ensure that you set your android activity launchMode to single task in your AndroiManifest.xml file."
|
[
|
||||||
|
'Looks like you have configured linking in multiple places. This is likely an error since URL integration should only be handled in one place to avoid conflicts. Make sure that:',
|
||||||
|
"- You are not using both 'linking' prop and 'useLinking'",
|
||||||
|
"- You don't have 'useLinking' in multiple components",
|
||||||
|
]
|
||||||
|
.join('\n')
|
||||||
|
.trim()
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
isUsingLinking = true;
|
isUsingLinking = enabled !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
@@ -81,10 +96,16 @@ export default function useLinking(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make it a thenable to keep consistent with the native impl
|
// Make it a thenable to keep consistent with the native impl
|
||||||
return {
|
const thenable = {
|
||||||
then: (callback: (state: ResultState | undefined) => void) =>
|
then(onfulfilled?: (state: ResultState | undefined) => void) {
|
||||||
callback(value),
|
return Promise.resolve(onfulfilled ? onfulfilled(value) : value);
|
||||||
|
},
|
||||||
|
catch() {
|
||||||
|
return thenable;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return thenable as PromiseLike<ResultState | undefined>;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const previousStateLengthRef = React.useRef<number | undefined>(undefined);
|
const previousStateLengthRef = React.useRef<number | undefined>(undefined);
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
export default function useThenable<T>(
|
export default function useThenable<T>(create: () => PromiseLike<T>) {
|
||||||
create: () => {
|
|
||||||
then(success: (result: T) => void, error?: (error: any) => void): void;
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
const [promise] = React.useState(create);
|
const [promise] = React.useState(create);
|
||||||
|
|
||||||
// Check if our thenable is synchronous
|
// Check if our thenable is synchronous
|
||||||
@@ -24,20 +20,20 @@ export default function useThenable<T>(
|
|||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
let cancelled = false;
|
let cancelled = false;
|
||||||
|
|
||||||
if (!resolved) {
|
const resolve = async () => {
|
||||||
promise.then(
|
let result;
|
||||||
(result) => {
|
|
||||||
|
try {
|
||||||
|
result = await promise;
|
||||||
|
} finally {
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
setState([true, result]);
|
setState([true, result]);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
if (!cancelled) {
|
|
||||||
console.error(error);
|
|
||||||
setState([true, undefined]);
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
);
|
|
||||||
|
if (!resolved) {
|
||||||
|
resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
|||||||
@@ -3,6 +3,36 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [5.4.4](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.4.3...@react-navigation/routers@5.4.4) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.3](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.4.2...@react-navigation/routers@5.4.3) (2020-05-08)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/routers
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.4.2](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.4.1...@react-navigation/routers@5.4.2) (2020-04-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix backBehavior with initialRoute ([#8110](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/issues/8110)) ([420f692](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/commit/420f6926e111d32c2388c44ff0bee2b8ea238a57))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.4.1](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.4.0...@react-navigation/routers@5.4.1) (2020-04-27)
|
## [5.4.1](https://github.com/react-navigation/react-navigation/tree/master/packages/routers/compare/@react-navigation/routers@5.4.0...@react-navigation/routers@5.4.1) (2020-04-27)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/routers",
|
"name": "@react-navigation/routers",
|
||||||
"description": "Routers to help build custom navigators",
|
"description": "Routers to help build custom navigators",
|
||||||
"version": "5.4.1",
|
"version": "5.4.4",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react",
|
"react",
|
||||||
"react-native",
|
"react-native",
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
"homepage": "https://reactnavigation.org/docs/custom-routers.html",
|
"homepage": "https://reactnavigation.org/docs/custom-routers.html",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
@@ -30,10 +31,10 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.0.2"
|
"nanoid": "^3.1.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.13.1",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -59,21 +59,31 @@ export const TabActions = {
|
|||||||
const getRouteHistory = (
|
const getRouteHistory = (
|
||||||
routes: Route<string>[],
|
routes: Route<string>[],
|
||||||
index: number,
|
index: number,
|
||||||
backBehavior: BackBehavior
|
backBehavior: BackBehavior,
|
||||||
|
initialRouteName: string | undefined
|
||||||
) => {
|
) => {
|
||||||
const history = [{ type: TYPE_ROUTE, key: routes[index].key }];
|
const history = [{ type: TYPE_ROUTE, key: routes[index].key }];
|
||||||
|
let initialRouteIndex;
|
||||||
|
|
||||||
switch (backBehavior) {
|
switch (backBehavior) {
|
||||||
case 'initialRoute':
|
|
||||||
if (index !== 0) {
|
|
||||||
history.unshift({ type: TYPE_ROUTE, key: routes[0].key });
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'order':
|
case 'order':
|
||||||
for (let i = index; i > 0; i--) {
|
for (let i = index; i > 0; i--) {
|
||||||
history.unshift({ type: TYPE_ROUTE, key: routes[i - 1].key });
|
history.unshift({ type: TYPE_ROUTE, key: routes[i - 1].key });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'initialRoute':
|
||||||
|
initialRouteIndex = routes.findIndex(
|
||||||
|
(route) => route.name === initialRouteName
|
||||||
|
);
|
||||||
|
initialRouteIndex = initialRouteIndex === -1 ? 0 : initialRouteIndex;
|
||||||
|
|
||||||
|
if (initialRouteIndex !== index) {
|
||||||
|
history.unshift({
|
||||||
|
type: TYPE_ROUTE,
|
||||||
|
key: routes[initialRouteIndex].key,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'history':
|
case 'history':
|
||||||
// The history will fill up on navigation
|
// The history will fill up on navigation
|
||||||
break;
|
break;
|
||||||
@@ -85,7 +95,8 @@ const getRouteHistory = (
|
|||||||
const changeIndex = (
|
const changeIndex = (
|
||||||
state: TabNavigationState,
|
state: TabNavigationState,
|
||||||
index: number,
|
index: number,
|
||||||
backBehavior: BackBehavior
|
backBehavior: BackBehavior,
|
||||||
|
initialRouteName: string | undefined
|
||||||
) => {
|
) => {
|
||||||
let history;
|
let history;
|
||||||
|
|
||||||
@@ -96,7 +107,12 @@ const changeIndex = (
|
|||||||
.filter((it) => (it.type === 'route' ? it.key !== currentKey : false))
|
.filter((it) => (it.type === 'route' ? it.key !== currentKey : false))
|
||||||
.concat({ type: TYPE_ROUTE, key: currentKey });
|
.concat({ type: TYPE_ROUTE, key: currentKey });
|
||||||
} else {
|
} else {
|
||||||
history = getRouteHistory(state.routes, index, backBehavior);
|
history = getRouteHistory(
|
||||||
|
state.routes,
|
||||||
|
index,
|
||||||
|
backBehavior,
|
||||||
|
initialRouteName
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -130,7 +146,12 @@ export default function TabRouter({
|
|||||||
params: routeParamList[name],
|
params: routeParamList[name],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const history = getRouteHistory(routes, index, backBehavior);
|
const history = getRouteHistory(
|
||||||
|
routes,
|
||||||
|
index,
|
||||||
|
backBehavior,
|
||||||
|
initialRouteName
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
stale: false,
|
stale: false,
|
||||||
@@ -189,7 +210,12 @@ export default function TabRouter({
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!history?.length) {
|
if (!history?.length) {
|
||||||
history = getRouteHistory(routes, index, backBehavior);
|
history = getRouteHistory(
|
||||||
|
routes,
|
||||||
|
index,
|
||||||
|
backBehavior,
|
||||||
|
initialRouteName
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -223,7 +249,12 @@ export default function TabRouter({
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (!history.length) {
|
if (!history.length) {
|
||||||
history = getRouteHistory(routes, index, backBehavior);
|
history = getRouteHistory(
|
||||||
|
routes,
|
||||||
|
index,
|
||||||
|
backBehavior,
|
||||||
|
initialRouteName
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -242,7 +273,7 @@ export default function TabRouter({
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
return changeIndex(state, index, backBehavior);
|
return changeIndex(state, index, backBehavior, initialRouteName);
|
||||||
},
|
},
|
||||||
|
|
||||||
getStateForAction(state, action) {
|
getStateForAction(state, action) {
|
||||||
@@ -284,7 +315,8 @@ export default function TabRouter({
|
|||||||
: state.routes,
|
: state.routes,
|
||||||
},
|
},
|
||||||
index,
|
index,
|
||||||
backBehavior
|
backBehavior,
|
||||||
|
initialRouteName
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -882,6 +882,78 @@ it('handles back action with backBehavior: initialRoute', () => {
|
|||||||
).toEqual(null);
|
).toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('handles back action with backBehavior: initialRoute and initialRouteName', () => {
|
||||||
|
const router = TabRouter({
|
||||||
|
backBehavior: 'initialRoute',
|
||||||
|
initialRouteName: 'baz',
|
||||||
|
});
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
routeNames: ['bar', 'baz', 'qux'],
|
||||||
|
routeParamList: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
let state = router.getInitialState(options);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
router.getStateForAction(state, CommonActions.goBack(), options)
|
||||||
|
).toEqual(null);
|
||||||
|
|
||||||
|
state = router.getStateForAction(
|
||||||
|
state,
|
||||||
|
TabActions.jumpTo('qux'),
|
||||||
|
options
|
||||||
|
) as TabNavigationState;
|
||||||
|
|
||||||
|
expect(
|
||||||
|
router.getStateForAction(state, CommonActions.goBack(), options)
|
||||||
|
).toEqual({
|
||||||
|
stale: false,
|
||||||
|
type: 'tab',
|
||||||
|
key: 'tab-test',
|
||||||
|
index: 1,
|
||||||
|
routeNames: ['bar', 'baz', 'qux'],
|
||||||
|
routes: [
|
||||||
|
{ key: 'bar-test', name: 'bar' },
|
||||||
|
{ key: 'baz-test', name: 'baz' },
|
||||||
|
{ key: 'qux-test', name: 'qux' },
|
||||||
|
],
|
||||||
|
history: [{ type: 'route', key: 'baz-test' }],
|
||||||
|
});
|
||||||
|
|
||||||
|
state = router.getStateForAction(
|
||||||
|
state,
|
||||||
|
TabActions.jumpTo('bar'),
|
||||||
|
options
|
||||||
|
) as TabNavigationState;
|
||||||
|
|
||||||
|
expect(
|
||||||
|
router.getStateForAction(state, CommonActions.goBack(), options)
|
||||||
|
).toEqual({
|
||||||
|
stale: false,
|
||||||
|
type: 'tab',
|
||||||
|
key: 'tab-test',
|
||||||
|
index: 1,
|
||||||
|
routeNames: ['bar', 'baz', 'qux'],
|
||||||
|
routes: [
|
||||||
|
{ key: 'bar-test', name: 'bar' },
|
||||||
|
{ key: 'baz-test', name: 'baz' },
|
||||||
|
{ key: 'qux-test', name: 'qux' },
|
||||||
|
],
|
||||||
|
history: [{ type: 'route', key: 'baz-test' }],
|
||||||
|
});
|
||||||
|
|
||||||
|
state = router.getStateForAction(
|
||||||
|
state,
|
||||||
|
TabActions.jumpTo('baz'),
|
||||||
|
options
|
||||||
|
) as TabNavigationState;
|
||||||
|
|
||||||
|
expect(
|
||||||
|
router.getStateForAction(state, CommonActions.goBack(), options)
|
||||||
|
).toEqual(null);
|
||||||
|
});
|
||||||
|
|
||||||
it('handles back action with backBehavior: none', () => {
|
it('handles back action with backBehavior: none', () => {
|
||||||
const router = TabRouter({ backBehavior: 'none' });
|
const router = TabRouter({ backBehavior: 'none' });
|
||||||
const options = {
|
const options = {
|
||||||
|
|||||||
@@ -3,6 +3,96 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [5.3.3](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.3.2...@react-navigation/stack@5.3.3) (2020-05-11)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix ios transitionspec settle time ([#8028](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/8028)) ([dd7cff2](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/dd7cff201608365a80f1d50a006df3e0d18e94a1))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.2](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.3.1...@react-navigation/stack@5.3.2) (2020-05-10)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.3.1](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.3.0...@react-navigation/stack@5.3.1) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix building typescript definitions. closes [#8216](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/8216) ([47a1229](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/47a12298378747edd2d22e54dc1c8677f98c49b4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [5.3.0](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.19...@react-navigation/stack@5.3.0) (2020-05-08)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add proper margins to the header title ([f07cd13](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/f07cd135619d635e8841aa0df0b6e687636e7408))
|
||||||
|
* include safe are insets in title's margins ([4d1e102](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/4d1e102f8c3ffab116d0195fbab3086f6345a077))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add generic type aliases for screen props ([bea14aa](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/bea14aa26fd5cbfebc7973733c5cf1f44fd323aa)), closes [#7971](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/issues/7971)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.19](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.18...@react-navigation/stack@5.2.19) (2020-05-05)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.18](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.17...@react-navigation/stack@5.2.18) (2020-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.17](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.16...@react-navigation/stack@5.2.17) (2020-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.16](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.15...@react-navigation/stack@5.2.16) (2020-04-30)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [5.2.15](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.14...@react-navigation/stack@5.2.15) (2020-04-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* make sure the address bar hides when scrolling on web ([0a19e94](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/commit/0a19e94b23a4d2b5f22d1d9deb0544f586f475ee))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [5.2.14](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.13...@react-navigation/stack@5.2.14) (2020-04-27)
|
## [5.2.14](https://github.com/react-navigation/react-navigation/tree/master/packages/stack/compare/@react-navigation/stack@5.2.13...@react-navigation/stack@5.2.14) (2020-04-27)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/stack",
|
"name": "@react-navigation/stack",
|
||||||
"description": "Stack navigator component for iOS and Android with animated transitions and gestures",
|
"description": "Stack navigator component for iOS and Android with animated transitions and gestures",
|
||||||
"version": "5.2.14",
|
"version": "5.3.3",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
"homepage": "https://reactnavigation.org/docs/stack-navigator.html",
|
"homepage": "https://reactnavigation.org/docs/stack-navigator.html",
|
||||||
"main": "lib/commonjs/index.js",
|
"main": "lib/commonjs/index.js",
|
||||||
"react-native": "src/index.tsx",
|
"react-native": "src/index.tsx",
|
||||||
|
"source": "src/index.tsx",
|
||||||
"module": "lib/module/index.js",
|
"module": "lib/module/index.js",
|
||||||
"types": "lib/typescript/src/index.d.ts",
|
"types": "lib/typescript/src/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
@@ -38,18 +39,18 @@
|
|||||||
"react-native-iphone-x-helper": "^1.2.1"
|
"react-native-iphone-x-helper": "^1.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-community/bob": "^0.10.0",
|
"@react-native-community/bob": "^0.13.1",
|
||||||
"@react-native-community/masked-view": "^0.1.7",
|
"@react-native-community/masked-view": "^0.1.10",
|
||||||
"@react-navigation/native": "^5.1.7",
|
"@react-navigation/native": "^5.3.0",
|
||||||
"@types/color": "^3.0.1",
|
"@types/color": "^3.0.1",
|
||||||
"@types/react": "^16.9.23",
|
"@types/react": "^16.9.34",
|
||||||
"@types/react-native": "^0.61.22",
|
"@types/react-native": "^0.62.7",
|
||||||
"del-cli": "^3.0.0",
|
"del-cli": "^3.0.0",
|
||||||
"react": "~16.9.0",
|
"react": "~16.9.0",
|
||||||
"react-native": "~0.61.5",
|
"react-native": "~0.61.5",
|
||||||
"react-native-gesture-handler": "^1.6.0",
|
"react-native-gesture-handler": "^1.6.0",
|
||||||
"react-native-safe-area-context": "^0.7.3",
|
"react-native-safe-area-context": "^0.7.3",
|
||||||
"react-native-screens": "^2.3.0",
|
"react-native-screens": "^2.7.0",
|
||||||
"typescript": "^3.8.3"
|
"typescript": "^3.8.3"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ export const TransitionIOSSpec: TransitionSpec = {
|
|||||||
damping: 500,
|
damping: 500,
|
||||||
mass: 3,
|
mass: 3,
|
||||||
overshootClamping: true,
|
overshootClamping: true,
|
||||||
restDisplacementThreshold: 0.01,
|
restDisplacementThreshold: 10,
|
||||||
restSpeedThreshold: 0.01,
|
restSpeedThreshold: 10,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ export { default as useGestureHandlerRef } from './utils/useGestureHandlerRef';
|
|||||||
export type {
|
export type {
|
||||||
StackNavigationOptions,
|
StackNavigationOptions,
|
||||||
StackNavigationProp,
|
StackNavigationProp,
|
||||||
|
StackScreenProps,
|
||||||
StackHeaderProps,
|
StackHeaderProps,
|
||||||
StackHeaderLeftButtonProps,
|
StackHeaderLeftButtonProps,
|
||||||
StackHeaderTitleProps,
|
StackHeaderTitleProps,
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
NavigationHelpers,
|
NavigationHelpers,
|
||||||
StackNavigationState,
|
StackNavigationState,
|
||||||
StackActionHelpers,
|
StackActionHelpers,
|
||||||
|
RouteProp,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
|
|
||||||
export type StackNavigationEventMap = {
|
export type StackNavigationEventMap = {
|
||||||
@@ -45,6 +46,14 @@ export type StackNavigationProp<
|
|||||||
> &
|
> &
|
||||||
StackActionHelpers<ParamList>;
|
StackActionHelpers<ParamList>;
|
||||||
|
|
||||||
|
export type StackScreenProps<
|
||||||
|
ParamList extends ParamListBase,
|
||||||
|
RouteName extends keyof ParamList = string
|
||||||
|
> = {
|
||||||
|
navigation: StackNavigationProp<ParamList, RouteName>;
|
||||||
|
route: RouteProp<ParamList, RouteName>;
|
||||||
|
};
|
||||||
|
|
||||||
export type Layout = { width: number; height: number };
|
export type Layout = { width: number; height: number };
|
||||||
|
|
||||||
export type GestureDirection =
|
export type GestureDirection =
|
||||||
@@ -276,7 +285,8 @@ export type StackNavigationOptions = StackHeaderOptions &
|
|||||||
cardStyle?: StyleProp<ViewStyle>;
|
cardStyle?: StyleProp<ViewStyle>;
|
||||||
/**
|
/**
|
||||||
* Whether transition animation should be enabled the screen.
|
* Whether transition animation should be enabled the screen.
|
||||||
* If you set it to `false`, the screen won't animate when pushing or popping. Defaults to `true`.
|
* If you set it to `false`, the screen won't animate when pushing or popping.
|
||||||
|
* Defaults to `true` on Android and iOS, `false` on Web.
|
||||||
*/
|
*/
|
||||||
animationEnabled?: boolean;
|
animationEnabled?: boolean;
|
||||||
/**
|
/**
|
||||||
@@ -286,10 +296,12 @@ export type StackNavigationOptions = StackHeaderOptions &
|
|||||||
animationTypeForReplace?: 'push' | 'pop';
|
animationTypeForReplace?: 'push' | 'pop';
|
||||||
/**
|
/**
|
||||||
* Whether you can use gestures to dismiss this screen. Defaults to `true` on iOS, `false` on Android.
|
* Whether you can use gestures to dismiss this screen. Defaults to `true` on iOS, `false` on Android.
|
||||||
|
* Not supported on Web.
|
||||||
*/
|
*/
|
||||||
gestureEnabled?: boolean;
|
gestureEnabled?: boolean;
|
||||||
/**
|
/**
|
||||||
* Object to override the distance of touch start from the edge of the screen to recognize gestures.
|
* Object to override the distance of touch start from the edge of the screen to recognize gestures.
|
||||||
|
* Not supported on Web.
|
||||||
*/
|
*/
|
||||||
gestureResponseDistance?: {
|
gestureResponseDistance?: {
|
||||||
/**
|
/**
|
||||||
@@ -302,8 +314,8 @@ export type StackNavigationOptions = StackHeaderOptions &
|
|||||||
horizontal?: number;
|
horizontal?: number;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* Number which determines the relevance of velocity for the gesture.
|
* Number which determines the relevance of velocity for the gesture. Defaults to 0.3.
|
||||||
* Defaults to 0.3.
|
* Not supported on Web.
|
||||||
*/
|
*/
|
||||||
gestureVelocityImpact?: number;
|
gestureVelocityImpact?: number;
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { PanGestureHandler } from 'react-native-gesture-handler';
|
|
||||||
|
|
||||||
export default React.createContext<React.Ref<PanGestureHandler> | undefined>(
|
export default React.createContext<React.Ref<
|
||||||
undefined
|
import('react-native-gesture-handler').PanGestureHandler
|
||||||
);
|
> | null>(null);
|
||||||
|
|||||||
22
packages/stack/src/views/GestureHandler.native.tsx
Normal file
22
packages/stack/src/views/GestureHandler.native.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import {
|
||||||
|
PanGestureHandler as PanGestureHandlerNative,
|
||||||
|
PanGestureHandlerProperties,
|
||||||
|
} from 'react-native-gesture-handler';
|
||||||
|
import GestureHandlerRefContext from '../utils/GestureHandlerRefContext';
|
||||||
|
|
||||||
|
export function PanGestureHandler(props: PanGestureHandlerProperties) {
|
||||||
|
const gestureRef = React.useRef<PanGestureHandlerNative>(null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GestureHandlerRefContext.Provider value={gestureRef}>
|
||||||
|
<PanGestureHandlerNative {...props} />
|
||||||
|
</GestureHandlerRefContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
GestureHandlerRootView,
|
||||||
|
State as GestureState,
|
||||||
|
PanGestureHandlerGestureEvent,
|
||||||
|
} from 'react-native-gesture-handler';
|
||||||
24
packages/stack/src/views/GestureHandler.tsx
Normal file
24
packages/stack/src/views/GestureHandler.tsx
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { View } from 'react-native';
|
||||||
|
import type { PanGestureHandlerProperties } from 'react-native-gesture-handler';
|
||||||
|
|
||||||
|
const Dummy: any = ({ children }: { children: React.ReactNode }) => (
|
||||||
|
<>{children}</>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const PanGestureHandler = Dummy as React.ComponentType<
|
||||||
|
PanGestureHandlerProperties
|
||||||
|
>;
|
||||||
|
|
||||||
|
export const GestureHandlerRootView = View;
|
||||||
|
|
||||||
|
export const GestureState = {
|
||||||
|
UNDETERMINED: 0,
|
||||||
|
FAILED: 1,
|
||||||
|
BEGAN: 2,
|
||||||
|
CANCELLED: 3,
|
||||||
|
ACTIVE: 4,
|
||||||
|
END: 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type { PanGestureHandlerGestureEvent } from 'react-native-gesture-handler';
|
||||||
@@ -41,6 +41,7 @@ export default React.memo(function Header(props: StackHeaderProps) {
|
|||||||
: previous.route.name;
|
: previous.route.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
const goBack = React.useCallback(
|
const goBack = React.useCallback(
|
||||||
debounce(() => {
|
debounce(() => {
|
||||||
if (navigation.isFocused() && navigation.canGoBack()) {
|
if (navigation.isFocused() && navigation.canGoBack()) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { useTheme } from '@react-navigation/native';
|
import { useTheme } from '@react-navigation/native';
|
||||||
import MaskedView from '../MaskedView';
|
import MaskedView from '../MaskedView';
|
||||||
import TouchableItem from '../TouchableItem';
|
import { TouchableItem } from '../TouchableItem';
|
||||||
import { StackHeaderLeftButtonProps } from '../../types';
|
import { StackHeaderLeftButtonProps } from '../../types';
|
||||||
|
|
||||||
type Props = StackHeaderLeftButtonProps;
|
type Props = StackHeaderLeftButtonProps;
|
||||||
|
|||||||
@@ -307,6 +307,8 @@ export default class HeaderSegment extends React.Component<Props, State> {
|
|||||||
})
|
})
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
const rightButton = right ? right({ tintColor: headerTintColor }) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Animated.View
|
<Animated.View
|
||||||
@@ -345,8 +347,17 @@ export default class HeaderSegment extends React.Component<Props, State> {
|
|||||||
pointerEvents="box-none"
|
pointerEvents="box-none"
|
||||||
style={[
|
style={[
|
||||||
headerTitleAlign === 'left'
|
headerTitleAlign === 'left'
|
||||||
? { position: 'absolute', left: leftButton ? 72 : 16 }
|
? {
|
||||||
: { marginHorizontal: 18 },
|
position: 'absolute',
|
||||||
|
left: (leftButton ? 72 : 16) + insets.left,
|
||||||
|
right: (rightButton ? 72 : 16) + insets.right,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
marginHorizontal:
|
||||||
|
(leftButton ? 32 : 16) +
|
||||||
|
(leftLabelLayout?.width || 0) +
|
||||||
|
Math.max(insets.left, insets.right),
|
||||||
|
},
|
||||||
titleStyle,
|
titleStyle,
|
||||||
titleContainerStyle,
|
titleContainerStyle,
|
||||||
]}
|
]}
|
||||||
@@ -359,7 +370,7 @@ export default class HeaderSegment extends React.Component<Props, State> {
|
|||||||
style: customTitleStyle,
|
style: customTitleStyle,
|
||||||
})}
|
})}
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
{right ? (
|
{rightButton ? (
|
||||||
<Animated.View
|
<Animated.View
|
||||||
pointerEvents="box-none"
|
pointerEvents="box-none"
|
||||||
style={[
|
style={[
|
||||||
@@ -369,7 +380,7 @@ export default class HeaderSegment extends React.Component<Props, State> {
|
|||||||
rightContainerStyle,
|
rightContainerStyle,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
{right({ tintColor: headerTintColor })}
|
{rightButton}
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
) : null}
|
) : null}
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import * as React from 'react';
|
|||||||
import { Animated, StyleSheet, Platform } from 'react-native';
|
import { Animated, StyleSheet, Platform } from 'react-native';
|
||||||
import { useTheme } from '@react-navigation/native';
|
import { useTheme } from '@react-navigation/native';
|
||||||
|
|
||||||
type Props = React.ComponentProps<typeof Animated.Text> & {
|
type Props = Omit<React.ComponentProps<typeof Animated.Text>, 'key'> & {
|
||||||
tintColor?: string;
|
tintColor?: string;
|
||||||
children?: string;
|
children?: string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,14 +9,15 @@ import {
|
|||||||
Platform,
|
Platform,
|
||||||
InteractionManager,
|
InteractionManager,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import {
|
|
||||||
PanGestureHandler,
|
|
||||||
State as GestureState,
|
|
||||||
PanGestureHandlerGestureEvent,
|
|
||||||
} from 'react-native-gesture-handler';
|
|
||||||
import { EdgeInsets } from 'react-native-safe-area-context';
|
import { EdgeInsets } from 'react-native-safe-area-context';
|
||||||
import Color from 'color';
|
import Color from 'color';
|
||||||
import StackGestureRefContext from '../../utils/GestureHandlerRefContext';
|
|
||||||
|
import CardSheet from './CardSheet';
|
||||||
|
import {
|
||||||
|
PanGestureHandler,
|
||||||
|
GestureState,
|
||||||
|
PanGestureHandlerGestureEvent,
|
||||||
|
} from '../GestureHandler';
|
||||||
import CardAnimationContext from '../../utils/CardAnimationContext';
|
import CardAnimationContext from '../../utils/CardAnimationContext';
|
||||||
import getDistanceForDirection from '../../utils/getDistanceForDirection';
|
import getDistanceForDirection from '../../utils/getDistanceForDirection';
|
||||||
import getInvertedMultiplier from '../../utils/getInvertedMultiplier';
|
import getInvertedMultiplier from '../../utils/getInvertedMultiplier';
|
||||||
@@ -36,6 +37,7 @@ type Props = ViewProps & {
|
|||||||
gesture: Animated.Value;
|
gesture: Animated.Value;
|
||||||
layout: Layout;
|
layout: Layout;
|
||||||
insets: EdgeInsets;
|
insets: EdgeInsets;
|
||||||
|
pageOverflowEnabled: boolean;
|
||||||
gestureDirection: GestureDirection;
|
gestureDirection: GestureDirection;
|
||||||
onOpen: () => void;
|
onOpen: () => void;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
@@ -412,8 +414,6 @@ export default class Card extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private gestureRef = React.createRef<PanGestureHandler>();
|
|
||||||
|
|
||||||
private contentRef = React.createRef<View>();
|
private contentRef = React.createRef<View>();
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@@ -430,6 +430,7 @@ export default class Card extends React.Component<Props> {
|
|||||||
shadowEnabled,
|
shadowEnabled,
|
||||||
gestureEnabled,
|
gestureEnabled,
|
||||||
gestureDirection,
|
gestureDirection,
|
||||||
|
pageOverflowEnabled,
|
||||||
children,
|
children,
|
||||||
containerStyle: customContainerStyle,
|
containerStyle: customContainerStyle,
|
||||||
contentStyle,
|
contentStyle,
|
||||||
@@ -499,7 +500,6 @@ export default class Card extends React.Component<Props> {
|
|||||||
pointerEvents="box-none"
|
pointerEvents="box-none"
|
||||||
>
|
>
|
||||||
<PanGestureHandler
|
<PanGestureHandler
|
||||||
ref={this.gestureRef}
|
|
||||||
enabled={layout.width !== 0 && gestureEnabled}
|
enabled={layout.width !== 0 && gestureEnabled}
|
||||||
onGestureEvent={handleGestureEvent}
|
onGestureEvent={handleGestureEvent}
|
||||||
onHandlerStateChange={this.handleGestureStateChange}
|
onHandlerStateChange={this.handleGestureStateChange}
|
||||||
@@ -523,14 +523,14 @@ export default class Card extends React.Component<Props> {
|
|||||||
pointerEvents="none"
|
pointerEvents="none"
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
<View
|
<CardSheet
|
||||||
ref={this.contentRef}
|
ref={this.contentRef}
|
||||||
style={[styles.content, contentStyle]}
|
enabled={pageOverflowEnabled}
|
||||||
|
layout={layout}
|
||||||
|
style={contentStyle}
|
||||||
>
|
>
|
||||||
<StackGestureRefContext.Provider value={this.gestureRef}>
|
|
||||||
{children}
|
{children}
|
||||||
</StackGestureRefContext.Provider>
|
</CardSheet>
|
||||||
</View>
|
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
</PanGestureHandler>
|
</PanGestureHandler>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
@@ -544,10 +544,6 @@ const styles = StyleSheet.create({
|
|||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
},
|
},
|
||||||
content: {
|
|
||||||
flex: 1,
|
|
||||||
overflow: 'hidden',
|
|
||||||
},
|
|
||||||
overlay: {
|
overlay: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: '#000',
|
backgroundColor: '#000',
|
||||||
|
|||||||
@@ -4,7 +4,13 @@ import { Route, useTheme } from '@react-navigation/native';
|
|||||||
import { Props as HeaderContainerProps } from '../Header/HeaderContainer';
|
import { Props as HeaderContainerProps } from '../Header/HeaderContainer';
|
||||||
import Card from './Card';
|
import Card from './Card';
|
||||||
import HeaderHeightContext from '../../utils/HeaderHeightContext';
|
import HeaderHeightContext from '../../utils/HeaderHeightContext';
|
||||||
import { Scene, Layout, StackHeaderMode, TransitionPreset } from '../../types';
|
import {
|
||||||
|
Scene,
|
||||||
|
Layout,
|
||||||
|
StackHeaderMode,
|
||||||
|
StackCardMode,
|
||||||
|
TransitionPreset,
|
||||||
|
} from '../../types';
|
||||||
|
|
||||||
type Props = TransitionPreset & {
|
type Props = TransitionPreset & {
|
||||||
index: number;
|
index: number;
|
||||||
@@ -45,6 +51,7 @@ type Props = TransitionPreset & {
|
|||||||
horizontal?: number;
|
horizontal?: number;
|
||||||
};
|
};
|
||||||
gestureVelocityImpact?: number;
|
gestureVelocityImpact?: number;
|
||||||
|
mode: StackCardMode;
|
||||||
headerMode: StackHeaderMode;
|
headerMode: StackHeaderMode;
|
||||||
headerShown?: boolean;
|
headerShown?: boolean;
|
||||||
headerTransparent?: boolean;
|
headerTransparent?: boolean;
|
||||||
@@ -73,6 +80,7 @@ function CardContainer({
|
|||||||
gestureVelocityImpact,
|
gestureVelocityImpact,
|
||||||
getPreviousRoute,
|
getPreviousRoute,
|
||||||
getFocusedRoute,
|
getFocusedRoute,
|
||||||
|
mode,
|
||||||
headerMode,
|
headerMode,
|
||||||
headerShown,
|
headerShown,
|
||||||
headerStyleInterpolator,
|
headerStyleInterpolator,
|
||||||
@@ -178,6 +186,7 @@ function CardContainer({
|
|||||||
accessibilityElementsHidden={!focused}
|
accessibilityElementsHidden={!focused}
|
||||||
importantForAccessibility={focused ? 'auto' : 'no-hide-descendants'}
|
importantForAccessibility={focused ? 'auto' : 'no-hide-descendants'}
|
||||||
pointerEvents={active ? 'box-none' : pointerEvents}
|
pointerEvents={active ? 'box-none' : pointerEvents}
|
||||||
|
pageOverflowEnabled={headerMode === 'screen' && mode === 'card'}
|
||||||
containerStyle={
|
containerStyle={
|
||||||
headerMode === 'float' && !headerTransparent && headerShown !== false
|
headerMode === 'float' && !headerTransparent && headerShown !== false
|
||||||
? { marginTop: headerHeight }
|
? { marginTop: headerHeight }
|
||||||
|
|||||||
49
packages/stack/src/views/Stack/CardSheet.tsx
Normal file
49
packages/stack/src/views/Stack/CardSheet.tsx
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { View, ViewProps, StyleSheet } from 'react-native';
|
||||||
|
|
||||||
|
type Props = ViewProps & {
|
||||||
|
enabled: boolean;
|
||||||
|
layout: { width: number; height: number };
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This component will render a page which overflows the screen
|
||||||
|
// if the container fills the body by comparing the size
|
||||||
|
// This lets the document.body handle scrolling of the content
|
||||||
|
// It's necessary for mobile browsers to be able to hide address bar on scroll
|
||||||
|
export default React.forwardRef<View, Props>(function CardSheet(
|
||||||
|
{ enabled, layout, style, ...rest },
|
||||||
|
ref
|
||||||
|
) {
|
||||||
|
const [fill, setFill] = React.useState(false);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (typeof document === 'undefined' || !document.body) {
|
||||||
|
// Only run when DOM is available
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const width = document.body.clientWidth;
|
||||||
|
const height = document.body.clientHeight;
|
||||||
|
|
||||||
|
setFill(width === layout.width && height === layout.height);
|
||||||
|
}, [layout.height, layout.width]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
{...rest}
|
||||||
|
ref={ref}
|
||||||
|
style={[enabled && fill ? styles.page : styles.card, style]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
page: {
|
||||||
|
minHeight: '100%',
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
flex: 1,
|
||||||
|
overflow: 'hidden',
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -519,6 +519,7 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
onHeaderHeightChange={this.handleHeaderLayout}
|
onHeaderHeightChange={this.handleHeaderLayout}
|
||||||
getPreviousRoute={getPreviousRoute}
|
getPreviousRoute={getPreviousRoute}
|
||||||
getFocusedRoute={this.getFocusedRoute}
|
getFocusedRoute={this.getFocusedRoute}
|
||||||
|
mode={mode}
|
||||||
headerMode={headerMode}
|
headerMode={headerMode}
|
||||||
headerShown={headerShown}
|
headerShown={headerShown}
|
||||||
headerTransparent={headerTransparent}
|
headerTransparent={headerTransparent}
|
||||||
@@ -564,7 +565,6 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
overflow: 'hidden',
|
|
||||||
},
|
},
|
||||||
floating: {
|
floating: {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { View, Platform, StyleSheet } from 'react-native';
|
import { View, Platform, StyleSheet } from 'react-native';
|
||||||
import { SafeAreaConsumer, EdgeInsets } from 'react-native-safe-area-context';
|
import { SafeAreaConsumer, EdgeInsets } from 'react-native-safe-area-context';
|
||||||
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
||||||
import {
|
import {
|
||||||
NavigationHelpersContext,
|
NavigationHelpersContext,
|
||||||
StackActions,
|
StackActions,
|
||||||
@@ -9,6 +8,7 @@ import {
|
|||||||
Route,
|
Route,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
|
|
||||||
|
import { GestureHandlerRootView } from '../GestureHandler';
|
||||||
import CardStack from './CardStack';
|
import CardStack from './CardStack';
|
||||||
import KeyboardManager from '../KeyboardManager';
|
import KeyboardManager from '../KeyboardManager';
|
||||||
import HeaderContainer, {
|
import HeaderContainer, {
|
||||||
@@ -420,7 +420,7 @@ export default class StackView extends React.Component<Props, State> {
|
|||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
const headerMode =
|
const headerMode =
|
||||||
mode !== 'modal' && Platform.OS === 'ios' ? 'float' : 'screen';
|
mode === 'card' && Platform.OS === 'ios' ? 'float' : 'screen';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavigationHelpersContext.Provider value={navigation}>
|
<NavigationHelpersContext.Provider value={navigation}>
|
||||||
|
|||||||
81
packages/stack/src/views/TouchableItem.native.tsx
Normal file
81
packages/stack/src/views/TouchableItem.native.tsx
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
* TouchableItem renders a touchable that looks native on both iOS and Android.
|
||||||
|
*
|
||||||
|
* It provides an abstraction on top of TouchableNativeFeedback and
|
||||||
|
* TouchableOpacity.
|
||||||
|
*
|
||||||
|
* On iOS you can pass the props of TouchableOpacity, on Android pass the props
|
||||||
|
* of TouchableNativeFeedback.
|
||||||
|
*/
|
||||||
|
import * as React from 'react';
|
||||||
|
import {
|
||||||
|
Platform,
|
||||||
|
TouchableNativeFeedback,
|
||||||
|
TouchableOpacity,
|
||||||
|
View,
|
||||||
|
ViewProps,
|
||||||
|
} from 'react-native';
|
||||||
|
|
||||||
|
import BorderlessButton from './BorderlessButton';
|
||||||
|
|
||||||
|
export type Props = ViewProps & {
|
||||||
|
pressColor: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
borderless?: boolean;
|
||||||
|
delayPressIn?: number;
|
||||||
|
onPress?: () => void;
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ANDROID_VERSION_LOLLIPOP = 21;
|
||||||
|
|
||||||
|
export class TouchableItem extends React.Component<Props> {
|
||||||
|
static defaultProps = {
|
||||||
|
borderless: false,
|
||||||
|
pressColor: 'rgba(0, 0, 0, .32)',
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
/*
|
||||||
|
* TouchableNativeFeedback.Ripple causes a crash on old Android versions,
|
||||||
|
* therefore only enable it on Android Lollipop and above.
|
||||||
|
*
|
||||||
|
* All touchables on Android should have the ripple effect according to
|
||||||
|
* platform design guidelines.
|
||||||
|
* We need to pass the background prop to specify a borderless ripple effect.
|
||||||
|
*/
|
||||||
|
if (
|
||||||
|
Platform.OS === 'android' &&
|
||||||
|
Platform.Version >= ANDROID_VERSION_LOLLIPOP
|
||||||
|
) {
|
||||||
|
const { style, pressColor, borderless, children, ...rest } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchableNativeFeedback
|
||||||
|
{...rest}
|
||||||
|
useForeground={TouchableNativeFeedback.canUseNativeForeground()}
|
||||||
|
background={TouchableNativeFeedback.Ripple(pressColor, borderless)}
|
||||||
|
>
|
||||||
|
<View style={style}>{React.Children.only(children)}</View>
|
||||||
|
</TouchableNativeFeedback>
|
||||||
|
);
|
||||||
|
} else if (Platform.OS === 'ios') {
|
||||||
|
return (
|
||||||
|
<BorderlessButton
|
||||||
|
hitSlop={{ top: 10, bottom: 10, right: 10, left: 10 }}
|
||||||
|
disallowInterruption
|
||||||
|
enabled={!this.props.disabled}
|
||||||
|
{...this.props}
|
||||||
|
>
|
||||||
|
{this.props.children}
|
||||||
|
</BorderlessButton>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<TouchableOpacity {...this.props}>
|
||||||
|
{this.props.children}
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,80 +1,3 @@
|
|||||||
/**
|
import { TouchableOpacity } from 'react-native';
|
||||||
* TouchableItem renders a touchable that looks native on both iOS and Android.
|
|
||||||
*
|
|
||||||
* It provides an abstraction on top of TouchableNativeFeedback and
|
|
||||||
* TouchableOpacity.
|
|
||||||
*
|
|
||||||
* On iOS you can pass the props of TouchableOpacity, on Android pass the props
|
|
||||||
* of TouchableNativeFeedback.
|
|
||||||
*/
|
|
||||||
import * as React from 'react';
|
|
||||||
import {
|
|
||||||
Platform,
|
|
||||||
TouchableNativeFeedback,
|
|
||||||
TouchableOpacity,
|
|
||||||
View,
|
|
||||||
ViewProps,
|
|
||||||
} from 'react-native';
|
|
||||||
|
|
||||||
import BorderlessButton from './BorderlessButton';
|
export const TouchableItem = (TouchableOpacity as any) as typeof import('./TouchableItem.native').TouchableItem;
|
||||||
|
|
||||||
type Props = ViewProps & {
|
|
||||||
pressColor: string;
|
|
||||||
disabled?: boolean;
|
|
||||||
borderless?: boolean;
|
|
||||||
delayPressIn?: number;
|
|
||||||
onPress?: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const ANDROID_VERSION_LOLLIPOP = 21;
|
|
||||||
|
|
||||||
export default class TouchableItem extends React.Component<Props> {
|
|
||||||
static defaultProps = {
|
|
||||||
borderless: false,
|
|
||||||
pressColor: 'rgba(0, 0, 0, .32)',
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
/*
|
|
||||||
* TouchableNativeFeedback.Ripple causes a crash on old Android versions,
|
|
||||||
* therefore only enable it on Android Lollipop and above.
|
|
||||||
*
|
|
||||||
* All touchables on Android should have the ripple effect according to
|
|
||||||
* platform design guidelines.
|
|
||||||
* We need to pass the background prop to specify a borderless ripple effect.
|
|
||||||
*/
|
|
||||||
if (
|
|
||||||
Platform.OS === 'android' &&
|
|
||||||
Platform.Version >= ANDROID_VERSION_LOLLIPOP
|
|
||||||
) {
|
|
||||||
const { style, pressColor, borderless, children, ...rest } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<TouchableNativeFeedback
|
|
||||||
{...rest}
|
|
||||||
useForeground={TouchableNativeFeedback.canUseNativeForeground()}
|
|
||||||
background={TouchableNativeFeedback.Ripple(pressColor, borderless)}
|
|
||||||
>
|
|
||||||
<View style={style}>{React.Children.only(children)}</View>
|
|
||||||
</TouchableNativeFeedback>
|
|
||||||
);
|
|
||||||
} else if (Platform.OS === 'ios') {
|
|
||||||
return (
|
|
||||||
<BorderlessButton
|
|
||||||
hitSlop={{ top: 10, bottom: 10, right: 10, left: 10 }}
|
|
||||||
disallowInterruption
|
|
||||||
enabled={!this.props.disabled}
|
|
||||||
{...this.props}
|
|
||||||
>
|
|
||||||
{this.props.children}
|
|
||||||
</BorderlessButton>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<TouchableOpacity {...this.props}>
|
|
||||||
{this.props.children}
|
|
||||||
</TouchableOpacity>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user