mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-23 04:18:18 +08:00
Compare commits
25 Commits
@react-nav
...
@react-nav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47134d7052 | ||
|
|
a369ba3645 | ||
|
|
4294318210 | ||
|
|
8da4c58065 | ||
|
|
7809bc0650 | ||
|
|
8f2b95ca97 | ||
|
|
6866ad2cda | ||
|
|
459fd27050 | ||
|
|
14786594c0 | ||
|
|
b28bfddc17 | ||
|
|
1a6aebefcb | ||
|
|
33b2dbb85c | ||
|
|
4bb0b43f1a | ||
|
|
260da9b103 | ||
|
|
9ac709ea1e | ||
|
|
60fa3b9be9 | ||
|
|
cf6a9e614d | ||
|
|
0ecd112ec9 | ||
|
|
def7c03d7d | ||
|
|
83242a7bef | ||
|
|
f48303f036 | ||
|
|
dc779b8d82 | ||
|
|
d7401b0200 | ||
|
|
372d5921b8 | ||
|
|
f940153d02 |
@@ -3,7 +3,7 @@ version: 2.1
|
|||||||
executors:
|
executors:
|
||||||
default:
|
default:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/node:10
|
- image: circleci/node:14
|
||||||
working_directory: ~/project
|
working_directory: ~/project
|
||||||
environment:
|
environment:
|
||||||
YARN_CACHE_FOLDER: "~/.cache/yarn"
|
YARN_CACHE_FOLDER: "~/.cache/yarn"
|
||||||
@@ -36,10 +36,12 @@ jobs:
|
|||||||
command: yarn install --frozen-lockfile
|
command: yarn install --frozen-lockfile
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
key: yarn-packages-v1-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
||||||
paths: ~/.cache/yarn
|
paths:
|
||||||
|
- ~/.cache/yarn
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: .
|
root: .
|
||||||
paths: .
|
paths:
|
||||||
|
- .
|
||||||
|
|
||||||
lint-and-typecheck:
|
lint-and-typecheck:
|
||||||
executor: default
|
executor: default
|
||||||
|
|||||||
2
.github/workflows/expo-preview.yml
vendored
2
.github/workflows/expo-preview.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
|||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 10.x
|
node-version: 14.x
|
||||||
|
|
||||||
- name: Setup Expo
|
- name: Setup Expo
|
||||||
uses: expo/expo-github-action@v5
|
uses: expo/expo-github-action@v5
|
||||||
|
|||||||
2
.github/workflows/expo.yml
vendored
2
.github/workflows/expo.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: 10.x
|
node-version: 14.x
|
||||||
|
|
||||||
- name: Setup Expo
|
- name: Setup Expo
|
||||||
uses: expo/expo-github-action@v5
|
uses: expo/expo-github-action@v5
|
||||||
|
|||||||
10
.github/workflows/first-pull-request.yml
vendored
10
.github/workflows/first-pull-request.yml
vendored
@@ -1,5 +1,5 @@
|
|||||||
name: First pull request
|
name: First pull request
|
||||||
on: pull_request
|
on: pull_request_target
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
welcome:
|
welcome:
|
||||||
@@ -12,13 +12,13 @@ jobs:
|
|||||||
// Get a list of all issues created by the PR opener
|
// Get a list of all issues created by the PR opener
|
||||||
// See: https://octokit.github.io/rest.js/#pagination
|
// See: https://octokit.github.io/rest.js/#pagination
|
||||||
const creator = context.payload.sender.login;
|
const creator = context.payload.sender.login;
|
||||||
const opts = github.issues.listForRepo.endpoint.merge({
|
const options = github.issues.listForRepo.endpoint.merge({
|
||||||
...context.issue,
|
...context.issue,
|
||||||
creator,
|
creator,
|
||||||
state: 'all'
|
state: 'all'
|
||||||
});
|
});
|
||||||
|
|
||||||
const issues = await github.paginate(opts);
|
const issues = await github.paginate(options);
|
||||||
|
|
||||||
for (const issue of issues) {
|
for (const issue of issues) {
|
||||||
if (issue.number === context.issue.number) {
|
if (issue.number === context.issue.number) {
|
||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (issue.pull_request) {
|
if (issue.pull_request) {
|
||||||
return ;// Creator is already a contributor.
|
return; // Creator is already a contributor.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,5 +41,5 @@ jobs:
|
|||||||
issue_number: context.issue.number,
|
issue_number: context.issue.number,
|
||||||
owner: context.repo.owner,
|
owner: context.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: context.repo.repo,
|
||||||
body: "Hey ${creator}! Thanks for opening the pull request. If you haven't already, make sure to read our [contribution guidelines](https://github.com/react-navigation/react-navigation/blob/main/CONTRIBUTING.md)."
|
body: `Hey ${creator}! Thanks for opening your first pull request in this repo. If you haven't already, make sure to read our [contribution guidelines](https://github.com/react-navigation/react-navigation/blob/main/CONTRIBUTING.md).`
|
||||||
});
|
});
|
||||||
|
|||||||
15
.github/workflows/sponsor.yml
vendored
Normal file
15
.github/workflows/sponsor.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
name: Label sponsors
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened]
|
||||||
|
issues:
|
||||||
|
types: [opened]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: is-sponsor-label
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: JasonEtco/is-sponsor-label-action@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
21
.github/workflows/stale.yml
vendored
Normal file
21
.github/workflows/stale.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
name: Close stale issues and PRs
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '30 1 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/stale@v3
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
days-before-stale: 30
|
||||||
|
days-before-close: 7
|
||||||
|
any-of-labels: 'needs more info,needs repro,needs response'
|
||||||
|
exempt-issue-labels: 'repro provided,keep open'
|
||||||
|
exempt-pr-labels: 'keep open'
|
||||||
|
stale-issue-label: 'stale'
|
||||||
|
stale-pr-label: 'stale'
|
||||||
|
stale-issue-message: 'Hello 👋, this issue has been open for more than a month without a repro or any activity. If the issue is still present in the latest version, please provide a repro or leave a comment within 7 days to keep it open, otherwise it will be closed automatically. If you found a solution or workaround for the issue, please comment here for others to find. If this issue is critical for you, please consider sending a pull request to fix it.'
|
||||||
|
stale-pr-message: 'Hello 👋, this pull request has been open for more than a month with no activity on it. If you think this is still necessary with the latest version, please comment and ping a maintainer to get this reviewed, otherwise it will be closed automatically in 7 days.'
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -26,6 +26,7 @@ build
|
|||||||
|
|
||||||
npm-debug.*
|
npm-debug.*
|
||||||
|
|
||||||
|
*.tsbuildinfo
|
||||||
*.log
|
*.log
|
||||||
*.jks
|
*.jks
|
||||||
*.p8
|
*.p8
|
||||||
@@ -33,3 +34,5 @@ npm-debug.*
|
|||||||
*.key
|
*.key
|
||||||
*.mobileprovision
|
*.mobileprovision
|
||||||
*.orig.*
|
*.orig.*
|
||||||
|
|
||||||
|
*.iml
|
||||||
|
|||||||
@@ -15,13 +15,13 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/vector-icons": "^12.0.0",
|
"@expo/vector-icons": "^12.0.0",
|
||||||
"@react-native-async-storage/async-storage": "^1.13.0",
|
"@react-native-async-storage/async-storage": "^1.13.0",
|
||||||
"@react-native-masked-view/masked-view": "0.2.3",
|
"@react-native-masked-view/masked-view": "~0.2.4",
|
||||||
"color": "^3.1.3",
|
"color": "^3.1.3",
|
||||||
"expo": "^41.0.0-beta.2",
|
"expo": "^41.0.1",
|
||||||
"expo-asset": "~8.3.1",
|
"expo-asset": "~8.3.1",
|
||||||
"expo-blur": "~9.0.3",
|
"expo-blur": "~9.0.3",
|
||||||
"expo-linking": "~2.2.1",
|
"expo-linking": "~2.2.3",
|
||||||
"expo-updates": "~0.5.3",
|
"expo-updates": "~0.5.4",
|
||||||
"koa": "^2.13.0",
|
"koa": "^2.13.0",
|
||||||
"react": "16.13.1",
|
"react": "16.13.1",
|
||||||
"react-dom": "16.13.1",
|
"react-dom": "16.13.1",
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
"babel-plugin-module-resolver": "^4.0.0",
|
"babel-plugin-module-resolver": "^4.0.0",
|
||||||
"babel-preset-expo": "8.3.0",
|
"babel-preset-expo": "8.3.0",
|
||||||
"cheerio": "^1.0.0-rc.3",
|
"cheerio": "^1.0.0-rc.3",
|
||||||
"expo-cli": "^4.3.4",
|
"expo-cli": "^4.4.4",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"jest-dev-server": "^4.4.0",
|
"jest-dev-server": "^4.4.0",
|
||||||
"mock-require-assets": "^0.0.1",
|
"mock-require-assets": "^0.0.1",
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Platform } from 'react-native';
|
|
||||||
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||||
import {
|
import {
|
||||||
getFocusedRouteNameFromRoute,
|
getFocusedRouteNameFromRoute,
|
||||||
@@ -9,7 +8,6 @@ import {
|
|||||||
import type { StackScreenProps } from '@react-navigation/stack';
|
import type { StackScreenProps } from '@react-navigation/stack';
|
||||||
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
||||||
import { HeaderBackButton } from '@react-navigation/elements';
|
import { HeaderBackButton } from '@react-navigation/elements';
|
||||||
import TouchableBounce from '../Shared/TouchableBounce';
|
|
||||||
import Albums from '../Shared/Albums';
|
import Albums from '../Shared/Albums';
|
||||||
import Contacts from '../Shared/Contacts';
|
import Contacts from '../Shared/Contacts';
|
||||||
import Chat from '../Shared/Chat';
|
import Chat from '../Shared/Chat';
|
||||||
@@ -51,10 +49,6 @@ export default function BottomTabsScreen({
|
|||||||
headerLeft: (props) => (
|
headerLeft: (props) => (
|
||||||
<HeaderBackButton {...props} onPress={navigation.goBack} />
|
<HeaderBackButton {...props} onPress={navigation.goBack} />
|
||||||
),
|
),
|
||||||
tabBarButton:
|
|
||||||
Platform.OS === 'web'
|
|
||||||
? undefined
|
|
||||||
: (props) => <TouchableBounce {...props} />,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<BottomTabs.Screen
|
<BottomTabs.Screen
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ 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> &
|
||||||
|
Parameters<typeof useLinkProps>[0]) => {
|
||||||
const props = useLinkProps({ to });
|
const props = useLinkProps({ to });
|
||||||
|
|
||||||
return <Button {...props} {...rest} />;
|
return <Button {...props} {...rest} />;
|
||||||
@@ -57,6 +58,13 @@ const ArticleScreen = ({
|
|||||||
>
|
>
|
||||||
Go to /link-component/music
|
Go to /link-component/music
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
|
<LinkButton
|
||||||
|
to={{ screen: 'Home' }}
|
||||||
|
mode="contained"
|
||||||
|
style={styles.button}
|
||||||
|
>
|
||||||
|
Go to /
|
||||||
|
</LinkButton>
|
||||||
<Button
|
<Button
|
||||||
mode="outlined"
|
mode="outlined"
|
||||||
onPress={() => navigation.goBack()}
|
onPress={() => navigation.goBack()}
|
||||||
|
|||||||
@@ -117,24 +117,29 @@ export default function SimpleStackScreen({
|
|||||||
return (
|
return (
|
||||||
<SimpleStack.Navigator
|
<SimpleStack.Navigator
|
||||||
screenOptions={{
|
screenOptions={{
|
||||||
...TransitionPresets.SlideFromRightIOS,
|
|
||||||
headerMode: 'float',
|
|
||||||
headerStyleInterpolator: HeaderStyleInterpolators.forUIKit,
|
headerStyleInterpolator: HeaderStyleInterpolators.forUIKit,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SimpleStack.Screen
|
<SimpleStack.Group
|
||||||
name="Article"
|
screenOptions={{
|
||||||
component={ArticleScreen}
|
...TransitionPresets.SlideFromRightIOS,
|
||||||
options={({ route }) => ({
|
headerMode: 'float',
|
||||||
title: `Article by ${route.params?.author ?? 'Unknown'}`,
|
}}
|
||||||
})}
|
>
|
||||||
initialParams={{ author: 'Gandalf' }}
|
<SimpleStack.Screen
|
||||||
/>
|
name="Article"
|
||||||
<SimpleStack.Screen
|
component={ArticleScreen}
|
||||||
name="NewsFeed"
|
options={({ route }) => ({
|
||||||
component={NewsFeedScreen}
|
title: `Article by ${route.params?.author ?? 'Unknown'}`,
|
||||||
options={{ title: 'Feed' }}
|
})}
|
||||||
/>
|
initialParams={{ author: 'Gandalf' }}
|
||||||
|
/>
|
||||||
|
<SimpleStack.Screen
|
||||||
|
name="NewsFeed"
|
||||||
|
component={NewsFeedScreen}
|
||||||
|
options={{ title: 'Feed' }}
|
||||||
|
/>
|
||||||
|
</SimpleStack.Group>
|
||||||
<SimpleStack.Screen
|
<SimpleStack.Screen
|
||||||
name="Albums"
|
name="Albums"
|
||||||
component={AlbumsScreen}
|
component={AlbumsScreen}
|
||||||
|
|||||||
137
example/src/Screens/MixedStack.tsx
Normal file
137
example/src/Screens/MixedStack.tsx
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { View, StyleSheet, ScrollView, Platform } from 'react-native';
|
||||||
|
import { Button } from 'react-native-paper';
|
||||||
|
import type { ParamListBase } from '@react-navigation/native';
|
||||||
|
import {
|
||||||
|
createStackNavigator,
|
||||||
|
StackScreenProps,
|
||||||
|
TransitionPresets,
|
||||||
|
} from '@react-navigation/stack';
|
||||||
|
import Article from '../Shared/Article';
|
||||||
|
import Albums from '../Shared/Albums';
|
||||||
|
|
||||||
|
type MixedStackParams = {
|
||||||
|
Article: { author: string };
|
||||||
|
Albums: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const scrollEnabled = Platform.select({ web: true, default: false });
|
||||||
|
|
||||||
|
const ArticleScreen = ({
|
||||||
|
navigation,
|
||||||
|
route,
|
||||||
|
}: StackScreenProps<MixedStackParams, 'Article'>) => {
|
||||||
|
return (
|
||||||
|
<ScrollView>
|
||||||
|
<View style={styles.buttons}>
|
||||||
|
<View>
|
||||||
|
<Button
|
||||||
|
mode="contained"
|
||||||
|
onPress={() => navigation.push('Article', { author: 'Dalek' })}
|
||||||
|
style={styles.button}
|
||||||
|
>
|
||||||
|
Push article
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
mode="outlined"
|
||||||
|
onPress={() => navigation.goBack()}
|
||||||
|
style={styles.button}
|
||||||
|
>
|
||||||
|
Go back
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
<View>
|
||||||
|
<Button
|
||||||
|
mode="contained"
|
||||||
|
onPress={() => navigation.push('Albums')}
|
||||||
|
style={styles.button}
|
||||||
|
>
|
||||||
|
Push album
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<Article
|
||||||
|
author={{ name: route.params.author }}
|
||||||
|
scrollEnabled={scrollEnabled}
|
||||||
|
/>
|
||||||
|
</ScrollView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const AlbumsScreen = ({ navigation }: StackScreenProps<MixedStackParams>) => {
|
||||||
|
return (
|
||||||
|
<ScrollView>
|
||||||
|
<View style={styles.buttons}>
|
||||||
|
<View>
|
||||||
|
<Button
|
||||||
|
mode="contained"
|
||||||
|
onPress={() => navigation.push('Albums')}
|
||||||
|
style={styles.button}
|
||||||
|
>
|
||||||
|
Push album
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
mode="outlined"
|
||||||
|
onPress={() => navigation.goBack()}
|
||||||
|
style={styles.button}
|
||||||
|
>
|
||||||
|
Go back
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
<View>
|
||||||
|
<Button
|
||||||
|
mode="contained"
|
||||||
|
onPress={() => navigation.push('Article', { author: 'The Doctor' })}
|
||||||
|
style={styles.button}
|
||||||
|
>
|
||||||
|
Push article
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
<Albums scrollEnabled={scrollEnabled} />
|
||||||
|
</ScrollView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const MixedStack = createStackNavigator<MixedStackParams>();
|
||||||
|
|
||||||
|
type Props = StackScreenProps<ParamListBase>;
|
||||||
|
|
||||||
|
export default function MixedStackScreen({ navigation }: Props) {
|
||||||
|
React.useLayoutEffect(() => {
|
||||||
|
navigation.setOptions({
|
||||||
|
headerShown: false,
|
||||||
|
});
|
||||||
|
}, [navigation]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MixedStack.Navigator>
|
||||||
|
<MixedStack.Screen
|
||||||
|
name="Article"
|
||||||
|
component={ArticleScreen}
|
||||||
|
options={({ route }) => ({
|
||||||
|
title: `Article by ${route.params.author}`,
|
||||||
|
})}
|
||||||
|
initialParams={{ author: 'Gandalf' }}
|
||||||
|
/>
|
||||||
|
<MixedStack.Screen
|
||||||
|
name="Albums"
|
||||||
|
component={AlbumsScreen}
|
||||||
|
options={{
|
||||||
|
title: 'Albums',
|
||||||
|
...TransitionPresets.ModalPresentationIOS,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</MixedStack.Navigator>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
buttons: {
|
||||||
|
flexDirection: 'row',
|
||||||
|
padding: 8,
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
margin: 8,
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -82,7 +82,7 @@ export default function ModalStackScreen({ navigation }: Props) {
|
|||||||
}, [navigation]);
|
}, [navigation]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ModalStack.Navigator mode="modal">
|
<ModalStack.Navigator screenOptions={{ animationPresentation: 'modal' }}>
|
||||||
<ModalStack.Screen
|
<ModalStack.Screen
|
||||||
name="Article"
|
name="Article"
|
||||||
component={ArticleScreen}
|
component={ArticleScreen}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
} from '@react-navigation/stack';
|
} from '@react-navigation/stack';
|
||||||
import Article from '../Shared/Article';
|
import Article from '../Shared/Article';
|
||||||
|
|
||||||
type SimpleStackParams = {
|
type TransparentStackParams = {
|
||||||
Article: { author: string };
|
Article: { author: string };
|
||||||
Dialog: undefined;
|
Dialog: undefined;
|
||||||
};
|
};
|
||||||
@@ -18,7 +18,7 @@ const scrollEnabled = Platform.select({ web: true, default: false });
|
|||||||
const ArticleScreen = ({
|
const ArticleScreen = ({
|
||||||
navigation,
|
navigation,
|
||||||
route,
|
route,
|
||||||
}: StackScreenProps<SimpleStackParams, 'Article'>) => {
|
}: StackScreenProps<TransparentStackParams, 'Article'>) => {
|
||||||
return (
|
return (
|
||||||
<ScrollView>
|
<ScrollView>
|
||||||
<View style={styles.buttons}>
|
<View style={styles.buttons}>
|
||||||
@@ -45,7 +45,9 @@ const ArticleScreen = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const DialogScreen = ({ navigation }: StackScreenProps<SimpleStackParams>) => {
|
const DialogScreen = ({
|
||||||
|
navigation,
|
||||||
|
}: StackScreenProps<TransparentStackParams>) => {
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -70,12 +72,11 @@ const DialogScreen = ({ navigation }: StackScreenProps<SimpleStackParams>) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const SimpleStack = createStackNavigator<SimpleStackParams>();
|
const TransparentStack = createStackNavigator<TransparentStackParams>();
|
||||||
|
|
||||||
type Props = Partial<React.ComponentProps<typeof SimpleStack.Navigator>> &
|
type Props = StackScreenProps<ParamListBase>;
|
||||||
StackScreenProps<ParamListBase>;
|
|
||||||
|
|
||||||
export default function SimpleStackScreen({ navigation, ...rest }: Props) {
|
export default function TransparentStackScreen({ navigation }: Props) {
|
||||||
React.useLayoutEffect(() => {
|
React.useLayoutEffect(() => {
|
||||||
navigation.setOptions({
|
navigation.setOptions({
|
||||||
headerShown: false,
|
headerShown: false,
|
||||||
@@ -83,13 +84,15 @@ export default function SimpleStackScreen({ navigation, ...rest }: Props) {
|
|||||||
}, [navigation]);
|
}, [navigation]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SimpleStack.Navigator mode="modal" {...rest}>
|
<TransparentStack.Navigator
|
||||||
<SimpleStack.Screen
|
screenOptions={{ animationPresentation: 'modal' }}
|
||||||
|
>
|
||||||
|
<TransparentStack.Screen
|
||||||
name="Article"
|
name="Article"
|
||||||
component={ArticleScreen}
|
component={ArticleScreen}
|
||||||
initialParams={{ author: 'Gandalf' }}
|
initialParams={{ author: 'Gandalf' }}
|
||||||
/>
|
/>
|
||||||
<SimpleStack.Screen
|
<TransparentStack.Screen
|
||||||
name="Dialog"
|
name="Dialog"
|
||||||
component={DialogScreen}
|
component={DialogScreen}
|
||||||
options={{
|
options={{
|
||||||
@@ -122,7 +125,7 @@ export default function SimpleStackScreen({ navigation, ...rest }: Props) {
|
|||||||
}),
|
}),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</SimpleStack.Navigator>
|
</TransparentStack.Navigator>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
// @ts-expect-error: there are no type definitions for deep imports
|
|
||||||
import TouchableBounce from 'react-native/Libraries/Components/Touchable/TouchableBounce';
|
|
||||||
|
|
||||||
export default TouchableBounce;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import { TouchableOpacity } from 'react-native';
|
|
||||||
|
|
||||||
export default TouchableOpacity;
|
|
||||||
@@ -28,13 +28,14 @@ import {
|
|||||||
DefaultTheme,
|
DefaultTheme,
|
||||||
DarkTheme,
|
DarkTheme,
|
||||||
PathConfigMap,
|
PathConfigMap,
|
||||||
NavigationContainerRef,
|
useNavigationContainerRef,
|
||||||
|
NavigatorScreenParams,
|
||||||
} from '@react-navigation/native';
|
} from '@react-navigation/native';
|
||||||
import { createDrawerNavigator } from '@react-navigation/drawer';
|
import { createDrawerNavigator } from '@react-navigation/drawer';
|
||||||
import {
|
import {
|
||||||
createStackNavigator,
|
createStackNavigator,
|
||||||
StackScreenProps,
|
|
||||||
HeaderStyleInterpolators,
|
HeaderStyleInterpolators,
|
||||||
|
StackNavigationProp,
|
||||||
} from '@react-navigation/stack';
|
} from '@react-navigation/stack';
|
||||||
import { useReduxDevToolsExtension } from '@react-navigation/devtools';
|
import { useReduxDevToolsExtension } from '@react-navigation/devtools';
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ import { restartApp } from './Restart';
|
|||||||
import SettingsItem from './Shared/SettingsItem';
|
import SettingsItem from './Shared/SettingsItem';
|
||||||
import SimpleStack from './Screens/SimpleStack';
|
import SimpleStack from './Screens/SimpleStack';
|
||||||
import ModalStack from './Screens/ModalStack';
|
import ModalStack from './Screens/ModalStack';
|
||||||
|
import MixedStack from './Screens/MixedStack';
|
||||||
import MixedHeaderMode from './Screens/MixedHeaderMode';
|
import MixedHeaderMode from './Screens/MixedHeaderMode';
|
||||||
import StackTransparent from './Screens/StackTransparent';
|
import StackTransparent from './Screens/StackTransparent';
|
||||||
import StackHeaderCustomization from './Screens/StackHeaderCustomization';
|
import StackHeaderCustomization from './Screens/StackHeaderCustomization';
|
||||||
@@ -61,6 +63,13 @@ if (Platform.OS !== 'web') {
|
|||||||
|
|
||||||
enableScreens();
|
enableScreens();
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
|
namespace ReactNavigation {
|
||||||
|
interface RootParamList extends RootStackParamList {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type RootDrawerParamList = {
|
type RootDrawerParamList = {
|
||||||
Examples: undefined;
|
Examples: undefined;
|
||||||
};
|
};
|
||||||
@@ -71,6 +80,10 @@ const SCREENS = {
|
|||||||
title: 'Modal Stack',
|
title: 'Modal Stack',
|
||||||
component: ModalStack,
|
component: ModalStack,
|
||||||
},
|
},
|
||||||
|
MixedStack: {
|
||||||
|
title: 'Regular + Modal Stack',
|
||||||
|
component: MixedStack,
|
||||||
|
},
|
||||||
MixedHeaderMode: {
|
MixedHeaderMode: {
|
||||||
title: 'Float + Screen Header Stack',
|
title: 'Float + Screen Header Stack',
|
||||||
component: MixedHeaderMode,
|
component: MixedHeaderMode,
|
||||||
@@ -115,7 +128,7 @@ const SCREENS = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type RootStackParamList = {
|
type RootStackParamList = {
|
||||||
Home: undefined;
|
Home: NavigatorScreenParams<RootDrawerParamList>;
|
||||||
NotFound: undefined;
|
NotFound: undefined;
|
||||||
} & {
|
} & {
|
||||||
[P in keyof typeof SCREENS]: undefined;
|
[P in keyof typeof SCREENS]: undefined;
|
||||||
@@ -193,7 +206,7 @@ export default function App() {
|
|||||||
return () => Dimensions.removeEventListener('change', onDimensionsChange);
|
return () => Dimensions.removeEventListener('change', onDimensionsChange);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const navigationRef = React.useRef<NavigationContainerRef>(null);
|
const navigationRef = useNavigationContainerRef<RootStackParamList>();
|
||||||
|
|
||||||
useReduxDevToolsExtension(navigationRef);
|
useReduxDevToolsExtension(navigationRef);
|
||||||
|
|
||||||
@@ -228,7 +241,9 @@ export default function App() {
|
|||||||
prefixes: [createURL('/')],
|
prefixes: [createURL('/')],
|
||||||
config: {
|
config: {
|
||||||
initialRouteName: 'Home',
|
initialRouteName: 'Home',
|
||||||
screens: Object.keys(SCREENS).reduce<PathConfigMap>(
|
screens: Object.keys(SCREENS).reduce<
|
||||||
|
PathConfigMap<RootStackParamList>
|
||||||
|
>(
|
||||||
(acc, name) => {
|
(acc, name) => {
|
||||||
// Convert screen names such as SimpleStack to kebab case (simple-stack)
|
// Convert screen names such as SimpleStack to kebab case (simple-stack)
|
||||||
const path = name
|
const path = name
|
||||||
@@ -236,13 +251,15 @@ export default function App() {
|
|||||||
.replace(/^-/, '')
|
.replace(/^-/, '')
|
||||||
.toLowerCase();
|
.toLowerCase();
|
||||||
|
|
||||||
|
// @ts-expect-error: these types aren't accurate
|
||||||
|
// But we aren't too concerned for now
|
||||||
acc[name] = {
|
acc[name] = {
|
||||||
path,
|
path,
|
||||||
screens: {
|
screens: {
|
||||||
Article: {
|
Article: {
|
||||||
path: 'article/:author?',
|
path: 'article/:author?',
|
||||||
parse: {
|
parse: {
|
||||||
author: (author) =>
|
author: (author: string) =>
|
||||||
author.charAt(0).toUpperCase() +
|
author.charAt(0).toUpperCase() +
|
||||||
author.slice(1).replace(/-/g, ' '),
|
author.slice(1).replace(/-/g, ' '),
|
||||||
},
|
},
|
||||||
@@ -304,7 +321,11 @@ export default function App() {
|
|||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{({ navigation }: StackScreenProps<RootStackParamList>) => (
|
{({
|
||||||
|
navigation,
|
||||||
|
}: {
|
||||||
|
navigation: StackNavigationProp<RootStackParamList>;
|
||||||
|
}) => (
|
||||||
<ScrollView
|
<ScrollView
|
||||||
style={{ backgroundColor: theme.colors.background }}
|
style={{ backgroundColor: theme.colors.background }}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -3,6 +3,26 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
# [6.0.0-next.7](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@6.0.0-next.6...@react-navigation/bottom-tabs@6.0.0-next.7) (2021-05-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* enable screens only on supported platforms ([#9494](https://github.com/react-navigation/react-navigation/issues/9494)) ([8da4c58](https://github.com/react-navigation/react-navigation/commit/8da4c58065607d44e9dc1ad8943e09537598dcd7))
|
||||||
|
* make sure disabling react-native-screens works ([a369ba3](https://github.com/react-navigation/react-navigation/commit/a369ba36451ddc2bb5b247e61b725bce1e3fb5e5))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [6.0.0-next.6](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@6.0.0-next.5...@react-navigation/bottom-tabs@6.0.0-next.6) (2021-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [6.0.0-next.5](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@6.0.0-next.4...@react-navigation/bottom-tabs@6.0.0-next.5) (2021-04-16)
|
# [6.0.0-next.5](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@6.0.0-next.4...@react-navigation/bottom-tabs@6.0.0-next.5) (2021-04-16)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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": "6.0.0-next.5",
|
"version": "6.0.0-next.7",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -36,16 +36,16 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/elements": "^1.0.0-next.4",
|
"@react-navigation/elements": "^1.0.0-next.6",
|
||||||
"color": "^3.1.3",
|
"color": "^3.1.3",
|
||||||
"warn-once": "^0.0.1"
|
"warn-once": "^0.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-navigation/native": "^6.0.0-next.2",
|
"@react-navigation/native": "^6.0.0-next.4",
|
||||||
"@testing-library/react-native": "^7.2.0",
|
"@testing-library/react-native": "^7.2.0",
|
||||||
"@types/color": "^3.0.1",
|
"@types/color": "^3.0.1",
|
||||||
"@types/react": "^16.9.53",
|
"@types/react": "^16.9.53",
|
||||||
"@types/react-native": "~0.63.51",
|
"@types/react-native": "~0.64.4",
|
||||||
"del-cli": "^3.0.1",
|
"del-cli": "^3.0.1",
|
||||||
"react": "~16.13.1",
|
"react": "~16.13.1",
|
||||||
"react-native": "~0.63.4",
|
"react-native": "~0.63.4",
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export type BottomTabNavigationHelpers = NavigationHelpers<
|
|||||||
|
|
||||||
export type BottomTabNavigationProp<
|
export type BottomTabNavigationProp<
|
||||||
ParamList extends ParamListBase,
|
ParamList extends ParamListBase,
|
||||||
RouteName extends keyof ParamList = string
|
RouteName extends keyof ParamList = keyof ParamList
|
||||||
> = NavigationProp<
|
> = NavigationProp<
|
||||||
ParamList,
|
ParamList,
|
||||||
RouteName,
|
RouteName,
|
||||||
@@ -54,7 +54,7 @@ export type BottomTabNavigationProp<
|
|||||||
|
|
||||||
export type BottomTabScreenProps<
|
export type BottomTabScreenProps<
|
||||||
ParamList extends ParamListBase,
|
ParamList extends ParamListBase,
|
||||||
RouteName extends keyof ParamList = string
|
RouteName extends keyof ParamList = keyof ParamList
|
||||||
> = {
|
> = {
|
||||||
navigation: BottomTabNavigationProp<ParamList, RouteName>;
|
navigation: BottomTabNavigationProp<ParamList, RouteName>;
|
||||||
route: RouteProp<ParamList, RouteName>;
|
route: RouteProp<ParamList, RouteName>;
|
||||||
@@ -239,7 +239,7 @@ export type BottomTabNavigationOptions = HeaderOptions & {
|
|||||||
export type BottomTabDescriptor = Descriptor<
|
export type BottomTabDescriptor = Descriptor<
|
||||||
BottomTabNavigationOptions,
|
BottomTabNavigationOptions,
|
||||||
BottomTabNavigationProp<ParamListBase>,
|
BottomTabNavigationProp<ParamListBase>,
|
||||||
RouteProp<ParamListBase, string>
|
RouteProp<ParamListBase>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type BottomTabDescriptorMap = Record<string, BottomTabDescriptor>;
|
export type BottomTabDescriptorMap = Record<string, BottomTabDescriptor>;
|
||||||
@@ -283,7 +283,7 @@ export type BottomTabHeaderProps = {
|
|||||||
/**
|
/**
|
||||||
* Route object for the current screen.
|
* Route object for the current screen.
|
||||||
*/
|
*/
|
||||||
route: RouteProp<ParamListBase, string>;
|
route: RouteProp<ParamListBase>;
|
||||||
/**
|
/**
|
||||||
* Navigation prop for the header.
|
* Navigation prop for the header.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { StyleSheet } from 'react-native';
|
import { StyleSheet, Platform } from 'react-native';
|
||||||
import { ScreenContainer } from 'react-native-screens';
|
|
||||||
import { SafeAreaInsetsContext } from 'react-native-safe-area-context';
|
import { SafeAreaInsetsContext } from 'react-native-safe-area-context';
|
||||||
import {
|
import {
|
||||||
NavigationHelpersContext,
|
NavigationHelpersContext,
|
||||||
@@ -13,8 +12,7 @@ import {
|
|||||||
SafeAreaProviderCompat,
|
SafeAreaProviderCompat,
|
||||||
getHeaderTitle,
|
getHeaderTitle,
|
||||||
} from '@react-navigation/elements';
|
} from '@react-navigation/elements';
|
||||||
|
import { MaybeScreenContainer, MaybeScreen } from './ScreenFallback';
|
||||||
import ScreenFallback from './ScreenFallback';
|
|
||||||
import BottomTabBar, { getTabBarHeight } from './BottomTabBar';
|
import BottomTabBar, { getTabBarHeight } from './BottomTabBar';
|
||||||
import BottomTabBarHeightCallbackContext from '../utils/BottomTabBarHeightCallbackContext';
|
import BottomTabBarHeightCallbackContext from '../utils/BottomTabBarHeightCallbackContext';
|
||||||
import BottomTabBarHeightContext from '../utils/BottomTabBarHeightContext';
|
import BottomTabBarHeightContext from '../utils/BottomTabBarHeightContext';
|
||||||
@@ -40,7 +38,9 @@ export default function BottomTabView(props: Props) {
|
|||||||
navigation,
|
navigation,
|
||||||
descriptors,
|
descriptors,
|
||||||
safeAreaInsets,
|
safeAreaInsets,
|
||||||
detachInactiveScreens = true,
|
detachInactiveScreens = Platform.OS === 'web' ||
|
||||||
|
Platform.OS === 'android' ||
|
||||||
|
Platform.OS === 'ios',
|
||||||
sceneContainerStyle,
|
sceneContainerStyle,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
@@ -91,8 +91,7 @@ export default function BottomTabView(props: Props) {
|
|||||||
return (
|
return (
|
||||||
<NavigationHelpersContext.Provider value={navigation}>
|
<NavigationHelpersContext.Provider value={navigation}>
|
||||||
<SafeAreaProviderCompat>
|
<SafeAreaProviderCompat>
|
||||||
<ScreenContainer
|
<MaybeScreenContainer
|
||||||
// @ts-ignore
|
|
||||||
enabled={detachInactiveScreens}
|
enabled={detachInactiveScreens}
|
||||||
style={styles.container}
|
style={styles.container}
|
||||||
>
|
>
|
||||||
@@ -121,7 +120,7 @@ export default function BottomTabView(props: Props) {
|
|||||||
} = descriptor.options;
|
} = descriptor.options;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScreenFallback
|
<MaybeScreen
|
||||||
key={route.key}
|
key={route.key}
|
||||||
style={StyleSheet.absoluteFill}
|
style={StyleSheet.absoluteFill}
|
||||||
visible={isFocused}
|
visible={isFocused}
|
||||||
@@ -147,10 +146,10 @@ export default function BottomTabView(props: Props) {
|
|||||||
{descriptor.render()}
|
{descriptor.render()}
|
||||||
</Screen>
|
</Screen>
|
||||||
</BottomTabBarHeightContext.Provider>
|
</BottomTabBarHeightContext.Provider>
|
||||||
</ScreenFallback>
|
</MaybeScreen>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ScreenContainer>
|
</MaybeScreenContainer>
|
||||||
<BottomTabBarHeightCallbackContext.Provider value={setTabBarHeight}>
|
<BottomTabBarHeightCallbackContext.Provider value={setTabBarHeight}>
|
||||||
{renderTabBar()}
|
{renderTabBar()}
|
||||||
</BottomTabBarHeightCallbackContext.Provider>
|
</BottomTabBarHeightCallbackContext.Provider>
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Platform, StyleProp, ViewStyle } from 'react-native';
|
import { StyleProp, View, ViewProps, ViewStyle } from 'react-native';
|
||||||
import {
|
|
||||||
Screen,
|
|
||||||
screensEnabled,
|
|
||||||
// @ts-ignore
|
|
||||||
shouldUseActivityState,
|
|
||||||
} from 'react-native-screens';
|
|
||||||
import { ResourceSavingView } from '@react-navigation/elements';
|
import { ResourceSavingView } from '@react-navigation/elements';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -15,22 +9,35 @@ type Props = {
|
|||||||
style?: StyleProp<ViewStyle>;
|
style?: StyleProp<ViewStyle>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ScreenFallback({ visible, children, ...rest }: Props) {
|
let Screens: typeof import('react-native-screens') | undefined;
|
||||||
// react-native-screens is buggy on web
|
|
||||||
if (screensEnabled?.() && Platform.OS !== 'web') {
|
try {
|
||||||
if (shouldUseActivityState) {
|
Screens = require('react-native-screens');
|
||||||
return (
|
} catch (e) {
|
||||||
<Screen activityState={visible ? 2 : 0} {...rest}>
|
// Ignore
|
||||||
{children}
|
}
|
||||||
</Screen>
|
|
||||||
);
|
export const MaybeScreenContainer = ({
|
||||||
} else {
|
enabled,
|
||||||
return (
|
...rest
|
||||||
<Screen active={visible ? 1 : 0} {...rest}>
|
}: ViewProps & {
|
||||||
{children}
|
enabled: boolean;
|
||||||
</Screen>
|
children: React.ReactNode;
|
||||||
);
|
}) => {
|
||||||
}
|
if (Screens?.screensEnabled?.()) {
|
||||||
|
return <Screens.ScreenContainer enabled={enabled} {...rest} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <View {...rest} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function MaybeScreen({ visible, children, ...rest }: Props) {
|
||||||
|
if (Screens?.screensEnabled?.()) {
|
||||||
|
return (
|
||||||
|
<Screens.Screen activityState={visible ? 2 : 0} {...rest}>
|
||||||
|
{children}
|
||||||
|
</Screens.Screen>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,6 +3,30 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
# [6.0.0-next.4](https://github.com/react-navigation/react-navigation/compare/@react-navigation/core@6.0.0-next.3...@react-navigation/core@6.0.0-next.4) (2021-05-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add a new component to group multiple screens with common options ([1a6aebe](https://github.com/react-navigation/react-navigation/commit/1a6aebefcb77ea708687475c55742407d69808ce))
|
||||||
|
* add ability to specify root param list ([b28bfdd](https://github.com/react-navigation/react-navigation/commit/b28bfddc17cbf3996fac04a34b2a7085ecf88be5))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [6.0.0-next.3](https://github.com/react-navigation/react-navigation/compare/@react-navigation/core@6.0.0-next.2...@react-navigation/core@6.0.0-next.3) (2021-05-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add a CompositeScreenProps type ([def7c03](https://github.com/react-navigation/react-navigation/commit/def7c03d7d7b42cf322f4e277f8f76858717654e))
|
||||||
|
* add helper and hook for container ref ([0ecd112](https://github.com/react-navigation/react-navigation/commit/0ecd112ec9786a26261ada3d33ef44dc1ec84da0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [6.0.0-next.2](https://github.com/react-navigation/react-navigation/compare/@react-navigation/core@6.0.0-next.1...@react-navigation/core@6.0.0-next.2) (2021-04-08)
|
# [6.0.0-next.2](https://github.com/react-navigation/react-navigation/compare/@react-navigation/core@6.0.0-next.1...@react-navigation/core@6.0.0-next.2) (2021-04-08)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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": "6.0.0-next.2",
|
"version": "6.0.0-next.4",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react",
|
"react",
|
||||||
"react-native",
|
"react-native",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
InitialState,
|
InitialState,
|
||||||
PartialState,
|
PartialState,
|
||||||
NavigationAction,
|
NavigationAction,
|
||||||
|
ParamListBase,
|
||||||
} from '@react-navigation/routers';
|
} from '@react-navigation/routers';
|
||||||
import EnsureSingleNavigator from './EnsureSingleNavigator';
|
import EnsureSingleNavigator from './EnsureSingleNavigator';
|
||||||
import UnhandledActionContext from './UnhandledActionContext';
|
import UnhandledActionContext from './UnhandledActionContext';
|
||||||
@@ -22,6 +23,7 @@ import useSyncState from './useSyncState';
|
|||||||
import checkSerializable from './checkSerializable';
|
import checkSerializable from './checkSerializable';
|
||||||
import checkDuplicateRouteNames from './checkDuplicateRouteNames';
|
import checkDuplicateRouteNames from './checkDuplicateRouteNames';
|
||||||
import findFocusedRoute from './findFocusedRoute';
|
import findFocusedRoute from './findFocusedRoute';
|
||||||
|
import { NOT_INITIALIZED_ERROR } from './createNavigationContainerRef';
|
||||||
import type {
|
import type {
|
||||||
NavigationContainerEventMap,
|
NavigationContainerEventMap,
|
||||||
NavigationContainerRef,
|
NavigationContainerRef,
|
||||||
@@ -30,9 +32,6 @@ import type {
|
|||||||
|
|
||||||
type State = NavigationState | PartialState<NavigationState> | undefined;
|
type State = NavigationState | PartialState<NavigationState> | undefined;
|
||||||
|
|
||||||
const NOT_INITIALIZED_ERROR =
|
|
||||||
"The 'navigation' object hasn't been initialized yet. This might happen if you don't have a navigator mounted, or if the navigator hasn't finished mounting. See https://reactnavigation.org/docs/navigating-without-navigation-prop#handling-initialization for more details.";
|
|
||||||
|
|
||||||
const serializableWarnings: string[] = [];
|
const serializableWarnings: string[] = [];
|
||||||
const duplicateNameWarnings: string[] = [];
|
const duplicateNameWarnings: string[] = [];
|
||||||
|
|
||||||
@@ -103,7 +102,7 @@ const BaseNavigationContainer = React.forwardRef(
|
|||||||
independent,
|
independent,
|
||||||
children,
|
children,
|
||||||
}: NavigationContainerProps,
|
}: NavigationContainerProps,
|
||||||
ref?: React.Ref<NavigationContainerRef>
|
ref?: React.Ref<NavigationContainerRef<ParamListBase>>
|
||||||
) {
|
) {
|
||||||
const parent = React.useContext(NavigationStateContext);
|
const parent = React.useContext(NavigationStateContext);
|
||||||
|
|
||||||
@@ -202,16 +201,10 @@ const BaseNavigationContainer = React.forwardRef(
|
|||||||
const { addOptionsGetter, getCurrentOptions } = useOptionsGetters({});
|
const { addOptionsGetter, getCurrentOptions } = useOptionsGetters({});
|
||||||
|
|
||||||
React.useImperativeHandle(ref, () => ({
|
React.useImperativeHandle(ref, () => ({
|
||||||
...(Object.keys(
|
...Object.keys(CommonActions).reduce<any>((acc, name) => {
|
||||||
CommonActions
|
|
||||||
) as (keyof typeof CommonActions)[]).reduce<any>((acc, name) => {
|
|
||||||
acc[name] = (...args: any[]) =>
|
acc[name] = (...args: any[]) =>
|
||||||
dispatch(
|
// @ts-expect-error: this is ok
|
||||||
CommonActions[name](
|
dispatch(CommonActions[name](...args));
|
||||||
// @ts-expect-error: we can't know the type statically
|
|
||||||
...args
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {}),
|
}, {}),
|
||||||
...emitter.create('root'),
|
...emitter.create('root'),
|
||||||
@@ -223,6 +216,7 @@ const BaseNavigationContainer = React.forwardRef(
|
|||||||
getParent: () => undefined,
|
getParent: () => undefined,
|
||||||
getCurrentRoute,
|
getCurrentRoute,
|
||||||
getCurrentOptions,
|
getCurrentOptions,
|
||||||
|
isReady: () => listeners.focus[0] != null,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const onDispatchAction = React.useCallback(
|
const onDispatchAction = React.useCallback(
|
||||||
|
|||||||
13
packages/core/src/Group.tsx
Normal file
13
packages/core/src/Group.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import type { ParamListBase } from '@react-navigation/routers';
|
||||||
|
import type { RouteGroupConfig } from './types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty component used for grouping screen configs.
|
||||||
|
*/
|
||||||
|
export default function Group<
|
||||||
|
ParamList extends ParamListBase,
|
||||||
|
ScreenOptions extends {}
|
||||||
|
>(_: RouteGroupConfig<ParamList, ScreenOptions>) {
|
||||||
|
/* istanbul ignore next */
|
||||||
|
return null;
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ import type { NavigationProp } from './types';
|
|||||||
* Context which holds the navigation prop for a screen.
|
* Context which holds the navigation prop for a screen.
|
||||||
*/
|
*/
|
||||||
const NavigationContext = React.createContext<
|
const NavigationContext = React.createContext<
|
||||||
NavigationProp<ParamListBase, string, any, any> | undefined
|
NavigationProp<ParamListBase> | undefined
|
||||||
>(undefined);
|
>(undefined);
|
||||||
|
|
||||||
export default NavigationContext;
|
export default NavigationContext;
|
||||||
|
|||||||
@@ -9,14 +9,10 @@ import NavigationStateContext from './NavigationStateContext';
|
|||||||
import StaticContainer from './StaticContainer';
|
import StaticContainer from './StaticContainer';
|
||||||
import EnsureSingleNavigator from './EnsureSingleNavigator';
|
import EnsureSingleNavigator from './EnsureSingleNavigator';
|
||||||
import useOptionsGetters from './useOptionsGetters';
|
import useOptionsGetters from './useOptionsGetters';
|
||||||
import type { NavigationProp, RouteConfig, EventMapBase } from './types';
|
import type { NavigationProp, RouteConfigComponent } from './types';
|
||||||
|
|
||||||
type Props<
|
type Props<State extends NavigationState, ScreenOptions extends {}> = {
|
||||||
State extends NavigationState,
|
screen: RouteConfigComponent<ParamListBase, string> & { name: string };
|
||||||
ScreenOptions extends {},
|
|
||||||
EventMap extends EventMapBase
|
|
||||||
> = {
|
|
||||||
screen: RouteConfig<ParamListBase, string, State, ScreenOptions, EventMap>;
|
|
||||||
navigation: NavigationProp<ParamListBase, string, State, ScreenOptions>;
|
navigation: NavigationProp<ParamListBase, string, State, ScreenOptions>;
|
||||||
route: Route<string>;
|
route: Route<string>;
|
||||||
routeState: NavigationState | PartialState<NavigationState> | undefined;
|
routeState: NavigationState | PartialState<NavigationState> | undefined;
|
||||||
@@ -31,8 +27,7 @@ type Props<
|
|||||||
*/
|
*/
|
||||||
export default function SceneView<
|
export default function SceneView<
|
||||||
State extends NavigationState,
|
State extends NavigationState,
|
||||||
ScreenOptions extends {},
|
ScreenOptions extends {}
|
||||||
EventMap extends EventMapBase
|
|
||||||
>({
|
>({
|
||||||
screen,
|
screen,
|
||||||
route,
|
route,
|
||||||
@@ -41,7 +36,7 @@ export default function SceneView<
|
|||||||
getState,
|
getState,
|
||||||
setState,
|
setState,
|
||||||
options,
|
options,
|
||||||
}: Props<State, ScreenOptions, EventMap>) {
|
}: Props<State, ScreenOptions>) {
|
||||||
const navigatorKeyRef = React.useRef<string | undefined>();
|
const navigatorKeyRef = React.useRef<string | undefined>();
|
||||||
const getKey = React.useCallback(() => navigatorKeyRef.current, []);
|
const getKey = React.useCallback(() => navigatorKeyRef.current, []);
|
||||||
|
|
||||||
|
|||||||
@@ -3,16 +3,17 @@ import { act, render } from '@testing-library/react-native';
|
|||||||
import {
|
import {
|
||||||
DefaultRouterOptions,
|
DefaultRouterOptions,
|
||||||
NavigationState,
|
NavigationState,
|
||||||
|
ParamListBase,
|
||||||
Router,
|
Router,
|
||||||
StackRouter,
|
StackRouter,
|
||||||
TabRouter,
|
TabRouter,
|
||||||
} from '@react-navigation/routers';
|
} from '@react-navigation/routers';
|
||||||
import BaseNavigationContainer from '../BaseNavigationContainer';
|
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||||
import NavigationStateContext from '../NavigationStateContext';
|
import NavigationStateContext from '../NavigationStateContext';
|
||||||
|
import createNavigationContainerRef from '../createNavigationContainerRef';
|
||||||
import MockRouter, { MockActions } from './__fixtures__/MockRouter';
|
import MockRouter, { MockActions } from './__fixtures__/MockRouter';
|
||||||
import useNavigationBuilder from '../useNavigationBuilder';
|
import useNavigationBuilder from '../useNavigationBuilder';
|
||||||
import Screen from '../Screen';
|
import Screen from '../Screen';
|
||||||
import type { NavigationContainerRef } from '../types';
|
|
||||||
|
|
||||||
it('throws when getState is accessed without a container', () => {
|
it('throws when getState is accessed without a container', () => {
|
||||||
expect.assertions(1);
|
expect.assertions(1);
|
||||||
@@ -128,7 +129,7 @@ it('handle dispatching with ref', () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const onStateChange = jest.fn();
|
const onStateChange = jest.fn();
|
||||||
|
|
||||||
@@ -226,7 +227,7 @@ it('handle resetting state with ref', () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const onStateChange = jest.fn();
|
const onStateChange = jest.fn();
|
||||||
|
|
||||||
@@ -316,7 +317,7 @@ it('handles getRootState', () => {
|
|||||||
return descriptors[state.routes[state.index].key].render();
|
return descriptors[state.routes[state.index].key].render();
|
||||||
};
|
};
|
||||||
|
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const element = (
|
const element = (
|
||||||
<BaseNavigationContainer ref={ref}>
|
<BaseNavigationContainer ref={ref}>
|
||||||
@@ -378,7 +379,7 @@ it('emits state events when the state changes', () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const element = (
|
const element = (
|
||||||
<BaseNavigationContainer ref={ref}>
|
<BaseNavigationContainer ref={ref}>
|
||||||
@@ -448,7 +449,7 @@ it('emits state events when new navigator mounts', () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const NestedNavigator = () => {
|
const NestedNavigator = () => {
|
||||||
const [isRendered, setIsRendered] = React.useState(false);
|
const [isRendered, setIsRendered] = React.useState(false);
|
||||||
@@ -537,7 +538,7 @@ it('emits option events when options change with tab router', () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const element = (
|
const element = (
|
||||||
<BaseNavigationContainer ref={ref}>
|
<BaseNavigationContainer ref={ref}>
|
||||||
@@ -611,7 +612,7 @@ it('emits option events when options change with stack router', () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const element = (
|
const element = (
|
||||||
<BaseNavigationContainer ref={ref}>
|
<BaseNavigationContainer ref={ref}>
|
||||||
@@ -677,7 +678,7 @@ it('emits option events when options change with stack router', () => {
|
|||||||
it('throws if there is no navigator rendered', () => {
|
it('throws if there is no navigator rendered', () => {
|
||||||
expect.assertions(1);
|
expect.assertions(1);
|
||||||
|
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const element = <BaseNavigationContainer ref={ref} children={null} />;
|
const element = <BaseNavigationContainer ref={ref} children={null} />;
|
||||||
|
|
||||||
@@ -697,7 +698,7 @@ it('throws if there is no navigator rendered', () => {
|
|||||||
it("throws if the ref hasn't finished initializing", () => {
|
it("throws if the ref hasn't finished initializing", () => {
|
||||||
expect.assertions(1);
|
expect.assertions(1);
|
||||||
|
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const TestNavigator = (props: any) => {
|
const TestNavigator = (props: any) => {
|
||||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
@@ -733,7 +734,7 @@ it("throws if the ref hasn't finished initializing", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('invokes the unhandled action listener with the unhandled action', () => {
|
it('invokes the unhandled action listener with the unhandled action', () => {
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
const fn = jest.fn();
|
const fn = jest.fn();
|
||||||
|
|
||||||
const TestNavigator = (props: any) => {
|
const TestNavigator = (props: any) => {
|
||||||
@@ -779,7 +780,7 @@ it('works with state change events in independent nested container', () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const onStateChange = jest.fn();
|
const onStateChange = jest.fn();
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,10 @@ it('converts state to path string', () => {
|
|||||||
|
|
||||||
const path = '/foo/bar/baz%20qux?author=jane&valid=true';
|
const path = '/foo/bar/baz%20qux?author=jane&valid=true';
|
||||||
|
|
||||||
expect(getPathFromState(state)).toBe(path);
|
expect(getPathFromState<object>(state)).toBe(path);
|
||||||
expect(getPathFromState(getStateFromPath(path) as State)).toBe(path);
|
expect(
|
||||||
|
getPathFromState<object>(getStateFromPath<object>(path) as State)
|
||||||
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('converts state to path string with config', () => {
|
it('converts state to path string with config', () => {
|
||||||
@@ -97,9 +99,12 @@ it('converts state to path string with config', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -116,8 +121,10 @@ it('handles route without param', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state)).toBe(path);
|
expect(getPathFromState<object>(state)).toBe(path);
|
||||||
expect(getPathFromState(getStateFromPath(path) as State)).toBe(path);
|
expect(
|
||||||
|
getPathFromState<object>(getStateFromPath<object>(path) as State)
|
||||||
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("doesn't add query param for empty params", () => {
|
it("doesn't add query param for empty params", () => {
|
||||||
@@ -131,8 +138,10 @@ it("doesn't add query param for empty params", () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state)).toBe(path);
|
expect(getPathFromState<object>(state)).toBe(path);
|
||||||
expect(getPathFromState(getStateFromPath(path) as State)).toBe(path);
|
expect(
|
||||||
|
getPathFromState<object>(getStateFromPath<object>(path) as State)
|
||||||
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles state with config with nested screens', () => {
|
it('handles state with config with nested screens', () => {
|
||||||
@@ -208,9 +217,12 @@ it('handles state with config with nested screens', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -287,9 +299,12 @@ it('handles state with config with nested screens and exact', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -352,9 +367,12 @@ it('handles state with config with nested screens and unused configs', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -418,9 +436,12 @@ it('handles state with config with nested screens and unused configs with exact'
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -498,9 +519,12 @@ it('handles nested object with stringify in it', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -580,9 +604,12 @@ it('handles nested object with stringify in it with exact', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -623,9 +650,12 @@ it('handles nested object for second route depth', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -669,9 +699,12 @@ it('handles nested object for second route depth with exact', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -719,9 +752,12 @@ it('handles nested object for second route depth and path and stringify in roots
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -774,9 +810,12 @@ it('handles nested object for second route depth and path and stringify in roots
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -805,9 +844,12 @@ it('ignores empty string paths', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -850,9 +892,12 @@ it('keeps query params if path is empty', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toEqual(path);
|
).toEqual(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -894,9 +939,12 @@ it('cuts nested configs too', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -939,9 +987,12 @@ it('cuts nested configs too with exact', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -977,9 +1028,12 @@ it('handles empty path at the end', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1012,9 +1066,12 @@ it('returns "/" for empty path', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1042,9 +1099,12 @@ it('parses no path specified', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1121,9 +1181,12 @@ it('strips undefined query params', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1201,9 +1264,12 @@ it('strips undefined query params with exact', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1278,9 +1344,12 @@ it('handles stripping all query params', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1357,9 +1426,12 @@ it('handles stripping all query params with exact', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1380,9 +1452,12 @@ it('replaces undefined query params', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1405,9 +1480,12 @@ it('matches wildcard patterns at root', () => {
|
|||||||
routes: [{ name: '404' }],
|
routes: [{ name: '404' }],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe('/404');
|
expect(getPathFromState<object>(state, config)).toBe('/404');
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe('/404');
|
).toBe('/404');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1447,9 +1525,12 @@ it('matches wildcard patterns at nested level', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe('/bar/42/404');
|
expect(getPathFromState<object>(state, config)).toBe('/bar/42/404');
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe('/bar/42/404');
|
).toBe('/bar/42/404');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1492,9 +1573,12 @@ it('matches wildcard patterns at nested level with exact', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe('/404');
|
expect(getPathFromState<object>(state, config)).toBe('/404');
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe('/404');
|
).toBe('/404');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1535,9 +1619,12 @@ it('tries to match wildcard patterns at the end', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe(path);
|
expect(getPathFromState<object>(state, config)).toBe(path);
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe(path);
|
).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1570,8 +1657,11 @@ it('uses nearest parent wildcard match for unmatched paths', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getPathFromState(state, config)).toBe('/404');
|
expect(getPathFromState<object>(state, config)).toBe('/404');
|
||||||
expect(
|
expect(
|
||||||
getPathFromState(getStateFromPath(path, config) as State, config)
|
getPathFromState<object>(
|
||||||
|
getStateFromPath<object>(path, config) as State,
|
||||||
|
config
|
||||||
|
)
|
||||||
).toBe('/404');
|
).toBe('/404');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const changePath = <T extends InitialState>(state: T, path: string): T =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('returns undefined for invalid path', () => {
|
it('returns undefined for invalid path', () => {
|
||||||
expect(getStateFromPath('//')).toBe(undefined);
|
expect(getStateFromPath<object>('//')).toBe(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('converts path string to initial state', () => {
|
it('converts path string to initial state', () => {
|
||||||
@@ -41,8 +41,8 @@ it('converts path string to initial state', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path)).toEqual(state);
|
expect(getStateFromPath<object>(path)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state))).toEqual(
|
expect(getStateFromPath<object>(getPathFromState<object>(state))).toEqual(
|
||||||
changePath(state, '/foo/bar/baz%20qux?author=jane%20%26%20co&valid=true')
|
changePath(state, '/foo/bar/baz%20qux?author=jane%20%26%20co&valid=true')
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -106,16 +106,16 @@ it('converts path string to initial state with config', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles leading slash when converting', () => {
|
it('handles leading slash when converting', () => {
|
||||||
const path = '/foo/bar/?count=42';
|
const path = '/foo/bar/?count=42';
|
||||||
|
|
||||||
expect(getStateFromPath(path)).toEqual({
|
expect(getStateFromPath<object>(path)).toEqual({
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
name: 'foo',
|
name: 'foo',
|
||||||
@@ -136,7 +136,7 @@ it('handles leading slash when converting', () => {
|
|||||||
it('handles ending slash when converting', () => {
|
it('handles ending slash when converting', () => {
|
||||||
const path = 'foo/bar/?count=42';
|
const path = 'foo/bar/?count=42';
|
||||||
|
|
||||||
expect(getStateFromPath(path)).toEqual({
|
expect(getStateFromPath<object>(path)).toEqual({
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
name: 'foo',
|
name: 'foo',
|
||||||
@@ -167,8 +167,8 @@ it('handles route without param', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path)).toEqual(state);
|
expect(getStateFromPath<object>(path)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state))).toEqual(
|
expect(getStateFromPath<object>(getPathFromState<object>(state))).toEqual(
|
||||||
changePath(state, '/foo/bar')
|
changePath(state, '/foo/bar')
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -245,10 +245,10 @@ it('converts path string to initial state with config with nested screens', () =
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('converts path string to initial state with config with nested screens and unused parse functions', () => {
|
it('converts path string to initial state with config with nested screens and unused parse functions', () => {
|
||||||
@@ -308,10 +308,10 @@ it('converts path string to initial state with config with nested screens and un
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
changePath(state, '/foe/baz/Jane?count=10&answer=42&valid=true')
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(changePath(state, '/foe/baz/Jane?count=10&answer=42&valid=true'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles nested object with unused configs and with parse in it', () => {
|
it('handles nested object with unused configs and with parse in it', () => {
|
||||||
@@ -400,10 +400,10 @@ it('handles nested object with unused configs and with parse in it', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles parse in nested object for second route depth', () => {
|
it('handles parse in nested object for second route depth', () => {
|
||||||
@@ -450,10 +450,10 @@ it('handles parse in nested object for second route depth', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles parse in nested object for second route depth and and path and parse in roots', () => {
|
it('handles parse in nested object for second route depth and and path and parse in roots', () => {
|
||||||
@@ -501,10 +501,10 @@ it('handles parse in nested object for second route depth and and path and parse
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles initialRouteName at top level', () => {
|
it('handles initialRouteName at top level', () => {
|
||||||
@@ -545,10 +545,10 @@ it('handles initialRouteName at top level', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles initialRouteName inside a screen', () => {
|
it('handles initialRouteName inside a screen', () => {
|
||||||
@@ -591,10 +591,10 @@ it('handles initialRouteName inside a screen', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles initialRouteName included in path', () => {
|
it('handles initialRouteName included in path', () => {
|
||||||
@@ -633,10 +633,10 @@ it('handles initialRouteName included in path', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles two initialRouteNames', () => {
|
it('handles two initialRouteNames', () => {
|
||||||
@@ -728,10 +728,10 @@ it('handles two initialRouteNames', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('accepts initialRouteName without config for it', () => {
|
it('accepts initialRouteName without config for it', () => {
|
||||||
@@ -823,10 +823,10 @@ it('accepts initialRouteName without config for it', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns undefined if path is empty and no matching screen is present', () => {
|
it('returns undefined if path is empty and no matching screen is present', () => {
|
||||||
@@ -847,7 +847,7 @@ it('returns undefined if path is empty and no matching screen is present', () =>
|
|||||||
|
|
||||||
const path = '';
|
const path = '';
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(undefined);
|
expect(getStateFromPath<object>(path, config)).toEqual(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns matching screen if path is empty', () => {
|
it('returns matching screen if path is empty', () => {
|
||||||
@@ -886,10 +886,10 @@ it('returns matching screen if path is empty', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
changePath(state, '/')
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(changePath(state, '/'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns matching screen with params if path is empty', () => {
|
it('returns matching screen with params if path is empty', () => {
|
||||||
@@ -931,10 +931,10 @@ it('returns matching screen with params if path is empty', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
changePath(state, '/?foo=42')
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(changePath(state, '/?foo=42'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("doesn't match nested screen if path is empty", () => {
|
it("doesn't match nested screen if path is empty", () => {
|
||||||
@@ -959,7 +959,7 @@ it("doesn't match nested screen if path is empty", () => {
|
|||||||
|
|
||||||
const path = '';
|
const path = '';
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(undefined);
|
expect(getStateFromPath<object>(path, config)).toEqual(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('chooses more exhaustive pattern', () => {
|
it('chooses more exhaustive pattern', () => {
|
||||||
@@ -1004,10 +1004,10 @@ it('chooses more exhaustive pattern', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles same paths beginnings', () => {
|
it('handles same paths beginnings', () => {
|
||||||
@@ -1048,10 +1048,10 @@ it('handles same paths beginnings', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles same paths beginnings with params', () => {
|
it('handles same paths beginnings with params', () => {
|
||||||
@@ -1096,10 +1096,10 @@ it('handles same paths beginnings with params', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles not taking path with too many segments', () => {
|
it('handles not taking path with too many segments', () => {
|
||||||
@@ -1151,10 +1151,10 @@ it('handles not taking path with too many segments', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles differently ordered params v1', () => {
|
it('handles differently ordered params v1', () => {
|
||||||
@@ -1206,10 +1206,10 @@ it('handles differently ordered params v1', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles differently ordered params v2', () => {
|
it('handles differently ordered params v2', () => {
|
||||||
@@ -1261,10 +1261,10 @@ it('handles differently ordered params v2', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles differently ordered params v3', () => {
|
it('handles differently ordered params v3', () => {
|
||||||
@@ -1316,10 +1316,10 @@ it('handles differently ordered params v3', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles differently ordered params v4', () => {
|
it('handles differently ordered params v4', () => {
|
||||||
@@ -1371,10 +1371,10 @@ it('handles differently ordered params v4', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
changePath(state, '/5/foos/res/20')
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(changePath(state, '/5/foos/res/20'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles simple optional params', () => {
|
it('handles simple optional params', () => {
|
||||||
@@ -1426,10 +1426,10 @@ it('handles simple optional params', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handle 2 optional params at the end v1', () => {
|
it('handle 2 optional params at the end v1', () => {
|
||||||
@@ -1481,10 +1481,10 @@ it('handle 2 optional params at the end v1', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handle 2 optional params at the end v2', () => {
|
it('handle 2 optional params at the end v2', () => {
|
||||||
@@ -1536,10 +1536,10 @@ it('handle 2 optional params at the end v2', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handle 2 optional params at the end v3', () => {
|
it('handle 2 optional params at the end v3', () => {
|
||||||
@@ -1592,10 +1592,10 @@ it('handle 2 optional params at the end v3', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handle optional params in the middle v1', () => {
|
it('handle optional params in the middle v1', () => {
|
||||||
@@ -1648,10 +1648,10 @@ it('handle optional params in the middle v1', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handle optional params in the middle v2', () => {
|
it('handle optional params in the middle v2', () => {
|
||||||
@@ -1704,10 +1704,10 @@ it('handle optional params in the middle v2', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handle optional params in the middle v3', () => {
|
it('handle optional params in the middle v3', () => {
|
||||||
@@ -1761,10 +1761,10 @@ it('handle optional params in the middle v3', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handle optional params in the middle v4', () => {
|
it('handle optional params in the middle v4', () => {
|
||||||
@@ -1818,10 +1818,10 @@ it('handle optional params in the middle v4', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handle optional params in the middle v5', () => {
|
it('handle optional params in the middle v5', () => {
|
||||||
@@ -1875,10 +1875,10 @@ it('handle optional params in the middle v5', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handle optional params in the beginning v1', () => {
|
it('handle optional params in the beginning v1', () => {
|
||||||
@@ -1932,10 +1932,10 @@ it('handle optional params in the beginning v1', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
changePath(state, '/5/10/foos/15')
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(changePath(state, '/5/10/foos/15'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handle optional params in the beginning v2', () => {
|
it('handle optional params in the beginning v2', () => {
|
||||||
@@ -1989,10 +1989,10 @@ it('handle optional params in the beginning v2', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
changePath(state, '/5/10/foos/15')
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(changePath(state, '/5/10/foos/15'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('merges parent patterns if needed', () => {
|
it('merges parent patterns if needed', () => {
|
||||||
@@ -2030,10 +2030,10 @@ it('merges parent patterns if needed', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
changePath(state, '/foo/42/baz/babel')
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(changePath(state, '/foo/42/baz/babel'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('ignores extra slashes in the pattern', () => {
|
it('ignores extra slashes in the pattern', () => {
|
||||||
@@ -2067,10 +2067,10 @@ it('ignores extra slashes in the pattern', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('matches wildcard patterns at root', () => {
|
it('matches wildcard patterns at root', () => {
|
||||||
@@ -2092,10 +2092,10 @@ it('matches wildcard patterns at root', () => {
|
|||||||
routes: [{ name: '404', path }],
|
routes: [{ name: '404', path }],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
changePath(state, '/404')
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(changePath(state, '/404'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('matches wildcard patterns at nested level', () => {
|
it('matches wildcard patterns at nested level', () => {
|
||||||
@@ -2134,10 +2134,10 @@ it('matches wildcard patterns at nested level', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
changePath(state, '/bar/42/404')
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(changePath(state, '/bar/42/404'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('matches wildcard patterns at nested level with exact', () => {
|
it('matches wildcard patterns at nested level with exact', () => {
|
||||||
@@ -2179,10 +2179,10 @@ it('matches wildcard patterns at nested level with exact', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
changePath(state, '/404')
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(changePath(state, '/404'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('tries to match wildcard patterns at the end', () => {
|
it('tries to match wildcard patterns at the end', () => {
|
||||||
@@ -2222,10 +2222,10 @@ it('tries to match wildcard patterns at the end', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('uses nearest parent wildcard match for unmatched paths', () => {
|
it('uses nearest parent wildcard match for unmatched paths', () => {
|
||||||
@@ -2257,17 +2257,17 @@ it('uses nearest parent wildcard match for unmatched paths', () => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
changePath(state, '/404')
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(changePath(state, '/404'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws if two screens map to the same pattern', () => {
|
it('throws if two screens map to the same pattern', () => {
|
||||||
const path = '/bar/42/baz/test';
|
const path = '/bar/42/baz/test';
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
getStateFromPath(path, {
|
getStateFromPath<object>(path, {
|
||||||
screens: {
|
screens: {
|
||||||
Foo: {
|
Foo: {
|
||||||
screens: {
|
screens: {
|
||||||
@@ -2287,7 +2287,7 @@ it('throws if two screens map to the same pattern', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
getStateFromPath(path, {
|
getStateFromPath<object>(path, {
|
||||||
screens: {
|
screens: {
|
||||||
Foo: {
|
Foo: {
|
||||||
screens: {
|
screens: {
|
||||||
@@ -2354,10 +2354,10 @@ it('correctly applies initialRouteName for config with similar route names', ()
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('correctly applies initialRouteName for config with similar route names v2', () => {
|
it('correctly applies initialRouteName for config with similar route names v2', () => {
|
||||||
@@ -2414,8 +2414,8 @@ it('correctly applies initialRouteName for config with similar route names v2',
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(getStateFromPath(path, config)).toEqual(state);
|
expect(getStateFromPath<object>(path, config)).toEqual(state);
|
||||||
expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(
|
expect(
|
||||||
state
|
getStateFromPath<object>(getPathFromState<object>(state, config), config)
|
||||||
);
|
).toEqual(state);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { render, act } from '@testing-library/react-native';
|
import { render, act } from '@testing-library/react-native';
|
||||||
import type { NavigationState } from '@react-navigation/routers';
|
import type { NavigationState, ParamListBase } from '@react-navigation/routers';
|
||||||
|
import Group from '../Group';
|
||||||
import Screen from '../Screen';
|
import Screen from '../Screen';
|
||||||
import BaseNavigationContainer from '../BaseNavigationContainer';
|
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||||
import useNavigationBuilder from '../useNavigationBuilder';
|
import useNavigationBuilder from '../useNavigationBuilder';
|
||||||
|
import createNavigationContainerRef from '../createNavigationContainerRef';
|
||||||
import useNavigation from '../useNavigation';
|
import useNavigation from '../useNavigation';
|
||||||
import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter';
|
import MockRouter, { MockRouterKey } from './__fixtures__/MockRouter';
|
||||||
import type { NavigationContainerRef } from '../types';
|
|
||||||
|
|
||||||
beforeEach(() => (MockRouterKey.current = 0));
|
beforeEach(() => (MockRouterKey.current = 0));
|
||||||
|
|
||||||
@@ -248,6 +249,53 @@ it('initializes state for nested screens in React.Fragment', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('initializes state for nested screens in Group', () => {
|
||||||
|
const TestNavigator = (props: any) => {
|
||||||
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
|
return descriptors[state.routes[state.index].key].render();
|
||||||
|
};
|
||||||
|
|
||||||
|
const TestScreen = (props: any) => {
|
||||||
|
React.useEffect(() => {
|
||||||
|
props.navigation.dispatch({ type: 'UPDATE' });
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const onStateChange = jest.fn();
|
||||||
|
|
||||||
|
const element = (
|
||||||
|
<BaseNavigationContainer onStateChange={onStateChange}>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="foo" component={TestScreen} />
|
||||||
|
<Group>
|
||||||
|
<Screen name="bar" component={jest.fn()} />
|
||||||
|
<Screen name="baz" component={jest.fn()} />
|
||||||
|
</Group>
|
||||||
|
</TestNavigator>
|
||||||
|
</BaseNavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
render(element).update(element);
|
||||||
|
|
||||||
|
expect(onStateChange).toBeCalledTimes(1);
|
||||||
|
expect(onStateChange).toBeCalledWith({
|
||||||
|
stale: false,
|
||||||
|
type: 'test',
|
||||||
|
index: 0,
|
||||||
|
key: '0',
|
||||||
|
routeNames: ['foo', 'bar', 'baz'],
|
||||||
|
routes: [
|
||||||
|
{ key: 'foo', name: 'foo' },
|
||||||
|
{ key: 'bar', name: 'bar' },
|
||||||
|
{ key: 'baz', name: 'baz' },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('initializes state for nested navigator on navigation', () => {
|
it('initializes state for nested navigator on navigation', () => {
|
||||||
const TestNavigator = (props: any) => {
|
const TestNavigator = (props: any) => {
|
||||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
@@ -679,7 +727,7 @@ it('navigates to nested child in a navigator', () => {
|
|||||||
|
|
||||||
const onStateChange = jest.fn();
|
const onStateChange = jest.fn();
|
||||||
|
|
||||||
const navigation = React.createRef<NavigationContainerRef>();
|
const navigation = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const element = render(
|
const element = render(
|
||||||
<BaseNavigationContainer ref={navigation} onStateChange={onStateChange}>
|
<BaseNavigationContainer ref={navigation} onStateChange={onStateChange}>
|
||||||
@@ -715,7 +763,7 @@ it('navigates to nested child in a navigator', () => {
|
|||||||
expect(element).toMatchInlineSnapshot(`"[foo-a, undefined]"`);
|
expect(element).toMatchInlineSnapshot(`"[foo-a, undefined]"`);
|
||||||
|
|
||||||
act(() =>
|
act(() =>
|
||||||
navigation.current?.navigate('bar', {
|
navigation.navigate('bar', {
|
||||||
screen: 'bar-b',
|
screen: 'bar-b',
|
||||||
params: { test: 42 },
|
params: { test: 42 },
|
||||||
})
|
})
|
||||||
@@ -726,7 +774,7 @@ it('navigates to nested child in a navigator', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
act(() =>
|
act(() =>
|
||||||
navigation.current?.navigate('bar', {
|
navigation.navigate('bar', {
|
||||||
screen: 'bar-a',
|
screen: 'bar-a',
|
||||||
params: { whoa: 'test' },
|
params: { whoa: 'test' },
|
||||||
})
|
})
|
||||||
@@ -736,15 +784,15 @@ it('navigates to nested child in a navigator', () => {
|
|||||||
`"[bar-a, {\\"lol\\":\\"why\\",\\"whoa\\":\\"test\\"}]"`
|
`"[bar-a, {\\"lol\\":\\"why\\",\\"whoa\\":\\"test\\"}]"`
|
||||||
);
|
);
|
||||||
|
|
||||||
act(() => navigation.current?.navigate('bar', { screen: 'bar-b' }));
|
act(() => navigation.navigate('bar', { screen: 'bar-b' }));
|
||||||
|
|
||||||
act(() => navigation.current?.goBack());
|
act(() => navigation.goBack());
|
||||||
|
|
||||||
expect(element).toMatchInlineSnapshot(
|
expect(element).toMatchInlineSnapshot(
|
||||||
`"[bar-a, {\\"lol\\":\\"why\\",\\"whoa\\":\\"test\\"}]"`
|
`"[bar-a, {\\"lol\\":\\"why\\",\\"whoa\\":\\"test\\"}]"`
|
||||||
);
|
);
|
||||||
|
|
||||||
act(() => navigation.current?.navigate('bar', { screen: 'bar-b' }));
|
act(() => navigation.navigate('bar', { screen: 'bar-b' }));
|
||||||
|
|
||||||
expect(element).toMatchInlineSnapshot(
|
expect(element).toMatchInlineSnapshot(
|
||||||
`"[bar-b, {\\"some\\":\\"stuff\\",\\"test\\":42,\\"whoa\\":\\"test\\"}]"`
|
`"[bar-b, {\\"some\\":\\"stuff\\",\\"test\\":42,\\"whoa\\":\\"test\\"}]"`
|
||||||
@@ -799,7 +847,7 @@ it('navigates to nested child in a navigator with initial: false', () => {
|
|||||||
|
|
||||||
const onStateChange = jest.fn();
|
const onStateChange = jest.fn();
|
||||||
|
|
||||||
const navigation = React.createRef<NavigationContainerRef>();
|
const navigation = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const first = render(
|
const first = render(
|
||||||
<BaseNavigationContainer ref={navigation} onStateChange={onStateChange}>
|
<BaseNavigationContainer ref={navigation} onStateChange={onStateChange}>
|
||||||
@@ -833,7 +881,7 @@ it('navigates to nested child in a navigator with initial: false', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(first).toMatchInlineSnapshot(`"[foo-a, undefined]"`);
|
expect(first).toMatchInlineSnapshot(`"[foo-a, undefined]"`);
|
||||||
expect(navigation.current?.getRootState()).toEqual({
|
expect(navigation.getRootState()).toEqual({
|
||||||
index: 0,
|
index: 0,
|
||||||
key: '0',
|
key: '0',
|
||||||
routeNames: ['foo', 'bar'],
|
routeNames: ['foo', 'bar'],
|
||||||
@@ -866,7 +914,7 @@ it('navigates to nested child in a navigator with initial: false', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
act(() =>
|
act(() =>
|
||||||
navigation.current?.navigate('bar', {
|
navigation.navigate('bar', {
|
||||||
screen: 'bar-b',
|
screen: 'bar-b',
|
||||||
params: { test: 42 },
|
params: { test: 42 },
|
||||||
})
|
})
|
||||||
@@ -876,7 +924,7 @@ it('navigates to nested child in a navigator with initial: false', () => {
|
|||||||
`"[bar-b, {\\"some\\":\\"stuff\\",\\"test\\":42}]"`
|
`"[bar-b, {\\"some\\":\\"stuff\\",\\"test\\":42}]"`
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(navigation.current?.getRootState()).toEqual({
|
expect(navigation.getRootState()).toEqual({
|
||||||
index: 2,
|
index: 2,
|
||||||
key: '0',
|
key: '0',
|
||||||
routeNames: ['foo', 'bar'],
|
routeNames: ['foo', 'bar'],
|
||||||
@@ -944,7 +992,7 @@ it('navigates to nested child in a navigator with initial: false', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(second).toMatchInlineSnapshot(`"[foo-a, undefined]"`);
|
expect(second).toMatchInlineSnapshot(`"[foo-a, undefined]"`);
|
||||||
expect(navigation.current?.getRootState()).toEqual({
|
expect(navigation.getRootState()).toEqual({
|
||||||
index: 0,
|
index: 0,
|
||||||
key: '4',
|
key: '4',
|
||||||
routeNames: ['foo', 'bar'],
|
routeNames: ['foo', 'bar'],
|
||||||
@@ -971,7 +1019,7 @@ it('navigates to nested child in a navigator with initial: false', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
act(() =>
|
act(() =>
|
||||||
navigation.current?.navigate('bar', {
|
navigation.navigate('bar', {
|
||||||
screen: 'bar-b',
|
screen: 'bar-b',
|
||||||
params: { test: 42 },
|
params: { test: 42 },
|
||||||
initial: false,
|
initial: false,
|
||||||
@@ -980,7 +1028,7 @@ it('navigates to nested child in a navigator with initial: false', () => {
|
|||||||
|
|
||||||
expect(second).toMatchInlineSnapshot(`"[bar-b, {\\"test\\":42}]"`);
|
expect(second).toMatchInlineSnapshot(`"[bar-b, {\\"test\\":42}]"`);
|
||||||
|
|
||||||
expect(navigation.current?.getRootState()).toEqual({
|
expect(navigation.getRootState()).toEqual({
|
||||||
index: 2,
|
index: 2,
|
||||||
key: '4',
|
key: '4',
|
||||||
routeNames: ['foo', 'bar'],
|
routeNames: ['foo', 'bar'],
|
||||||
@@ -1071,7 +1119,7 @@ it('navigates to nested child in a navigator with initial: false', () => {
|
|||||||
|
|
||||||
expect(third).toMatchInlineSnapshot(`"[bar-b, {\\"some\\":\\"stuff\\"}]"`);
|
expect(third).toMatchInlineSnapshot(`"[bar-b, {\\"some\\":\\"stuff\\"}]"`);
|
||||||
|
|
||||||
expect(navigation.current?.getRootState()).toEqual({
|
expect(navigation.getRootState()).toEqual({
|
||||||
index: 1,
|
index: 1,
|
||||||
key: '11',
|
key: '11',
|
||||||
routeNames: ['foo', 'bar'],
|
routeNames: ['foo', 'bar'],
|
||||||
@@ -1119,7 +1167,7 @@ it('resets state of a nested child in a navigator', () => {
|
|||||||
|
|
||||||
const onStateChange = jest.fn();
|
const onStateChange = jest.fn();
|
||||||
|
|
||||||
const navigation = React.createRef<NavigationContainerRef>();
|
const navigation = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const first = render(
|
const first = render(
|
||||||
<BaseNavigationContainer ref={navigation} onStateChange={onStateChange}>
|
<BaseNavigationContainer ref={navigation} onStateChange={onStateChange}>
|
||||||
@@ -1150,7 +1198,7 @@ it('resets state of a nested child in a navigator', () => {
|
|||||||
|
|
||||||
expect(first).toMatchInlineSnapshot(`"[foo-a, undefined]"`);
|
expect(first).toMatchInlineSnapshot(`"[foo-a, undefined]"`);
|
||||||
|
|
||||||
expect(navigation.current?.getRootState()).toEqual({
|
expect(navigation.getRootState()).toEqual({
|
||||||
index: 0,
|
index: 0,
|
||||||
key: '0',
|
key: '0',
|
||||||
routeNames: ['foo', 'bar'],
|
routeNames: ['foo', 'bar'],
|
||||||
@@ -1183,7 +1231,7 @@ it('resets state of a nested child in a navigator', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
act(() =>
|
act(() =>
|
||||||
navigation.current?.navigate('bar', {
|
navigation.navigate('bar', {
|
||||||
state: {
|
state: {
|
||||||
routes: [{ name: 'bar-a' }, { name: 'bar-b' }],
|
routes: [{ name: 'bar-a' }, { name: 'bar-b' }],
|
||||||
},
|
},
|
||||||
@@ -1192,7 +1240,7 @@ it('resets state of a nested child in a navigator', () => {
|
|||||||
|
|
||||||
expect(first).toMatchInlineSnapshot(`"[bar-a, undefined]"`);
|
expect(first).toMatchInlineSnapshot(`"[bar-a, undefined]"`);
|
||||||
|
|
||||||
expect(navigation.current?.getRootState()).toEqual({
|
expect(navigation.getRootState()).toEqual({
|
||||||
index: 1,
|
index: 1,
|
||||||
key: '0',
|
key: '0',
|
||||||
routeNames: ['foo', 'bar'],
|
routeNames: ['foo', 'bar'],
|
||||||
@@ -1231,7 +1279,7 @@ it('resets state of a nested child in a navigator', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
act(() =>
|
act(() =>
|
||||||
navigation.current?.navigate('bar', {
|
navigation.navigate('bar', {
|
||||||
state: {
|
state: {
|
||||||
index: 2,
|
index: 2,
|
||||||
routes: [
|
routes: [
|
||||||
@@ -1245,7 +1293,7 @@ it('resets state of a nested child in a navigator', () => {
|
|||||||
|
|
||||||
expect(first).toMatchInlineSnapshot(`"[bar-a, {\\"test\\":18}]"`);
|
expect(first).toMatchInlineSnapshot(`"[bar-a, {\\"test\\":18}]"`);
|
||||||
|
|
||||||
expect(navigation.current?.getRootState()).toEqual({
|
expect(navigation.getRootState()).toEqual({
|
||||||
index: 1,
|
index: 1,
|
||||||
key: '0',
|
key: '0',
|
||||||
routeNames: ['foo', 'bar'],
|
routeNames: ['foo', 'bar'],
|
||||||
@@ -1336,7 +1384,7 @@ it('preserves order of screens in state with non-numeric names', () => {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigation = React.createRef<NavigationContainerRef>();
|
const navigation = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const root = (
|
const root = (
|
||||||
<BaseNavigationContainer ref={navigation}>
|
<BaseNavigationContainer ref={navigation}>
|
||||||
@@ -1350,11 +1398,7 @@ it('preserves order of screens in state with non-numeric names', () => {
|
|||||||
|
|
||||||
render(root);
|
render(root);
|
||||||
|
|
||||||
expect(navigation.current?.getRootState().routeNames).toEqual([
|
expect(navigation.getRootState().routeNames).toEqual(['foo', 'bar', 'baz']);
|
||||||
'foo',
|
|
||||||
'bar',
|
|
||||||
'baz',
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('preserves order of screens in state with numeric names', () => {
|
it('preserves order of screens in state with numeric names', () => {
|
||||||
@@ -1363,7 +1407,7 @@ it('preserves order of screens in state with numeric names', () => {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigation = React.createRef<NavigationContainerRef>();
|
const navigation = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const root = (
|
const root = (
|
||||||
<BaseNavigationContainer ref={navigation}>
|
<BaseNavigationContainer ref={navigation}>
|
||||||
@@ -1377,11 +1421,7 @@ it('preserves order of screens in state with numeric names', () => {
|
|||||||
|
|
||||||
render(root);
|
render(root);
|
||||||
|
|
||||||
expect(navigation.current?.getRootState().routeNames).toEqual([
|
expect(navigation.getRootState().routeNames).toEqual(['4', '7', '1']);
|
||||||
'4',
|
|
||||||
'7',
|
|
||||||
'1',
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("throws if navigator doesn't have any screens", () => {
|
it("throws if navigator doesn't have any screens", () => {
|
||||||
@@ -1458,7 +1498,7 @@ it('throws when Screen is not the direct children', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(() => render(element).update(element)).toThrowError(
|
expect(() => render(element).update(element)).toThrowError(
|
||||||
"A navigator can only contain 'Screen' components as its direct children (found 'Bar')"
|
"A navigator can only contain 'Screen', 'Group' or 'React.Fragment' as its direct children (found 'Bar')"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1483,7 +1523,7 @@ it('throws when undefined component is a direct children', () => {
|
|||||||
spy.mockRestore();
|
spy.mockRestore();
|
||||||
|
|
||||||
expect(() => render(element).update(element)).toThrowError(
|
expect(() => render(element).update(element)).toThrowError(
|
||||||
"A navigator can only contain 'Screen' components as its direct children (found 'undefined' for the screen 'foo')"
|
"A navigator can only contain 'Screen', 'Group' or 'React.Fragment' as its direct children (found 'undefined' for the screen 'foo')"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1503,7 +1543,7 @@ it('throws when a tag is a direct children', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(() => render(element).update(element)).toThrowError(
|
expect(() => render(element).update(element)).toThrowError(
|
||||||
"A navigator can only contain 'Screen' components as its direct children (found 'screen' for the screen 'foo')"
|
"A navigator can only contain 'Screen', 'Group' or 'React.Fragment' as its direct children (found 'screen' for the screen 'foo')"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1523,7 +1563,7 @@ it('throws when a React Element is not the direct children', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(() => render(element).update(element)).toThrowError(
|
expect(() => render(element).update(element)).toThrowError(
|
||||||
"A navigator can only contain 'Screen' components as its direct children (found 'Hello world')"
|
"A navigator can only contain 'Screen', 'Group' or 'React.Fragment' as its direct children (found 'Hello world')"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1801,7 +1841,7 @@ it('returns currently focused route with getCurrentRoute', () => {
|
|||||||
|
|
||||||
const TestScreen = () => null;
|
const TestScreen = () => null;
|
||||||
|
|
||||||
const navigation = React.createRef<NavigationContainerRef>();
|
const navigation = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const container = (
|
const container = (
|
||||||
<BaseNavigationContainer ref={navigation}>
|
<BaseNavigationContainer ref={navigation}>
|
||||||
@@ -1824,7 +1864,7 @@ it('returns currently focused route with getCurrentRoute', () => {
|
|||||||
|
|
||||||
render(container).update(container);
|
render(container).update(container);
|
||||||
|
|
||||||
expect(navigation.current?.getCurrentRoute()).toEqual({
|
expect(navigation.getCurrentRoute()).toEqual({
|
||||||
key: 'bar-a',
|
key: 'bar-a',
|
||||||
name: 'bar-a',
|
name: 'bar-a',
|
||||||
});
|
});
|
||||||
@@ -1839,26 +1879,23 @@ it("returns focused screen's options with getCurrentOptions when focused screen
|
|||||||
|
|
||||||
const TestScreen = () => null;
|
const TestScreen = () => null;
|
||||||
|
|
||||||
const navigation = React.createRef<NavigationContainerRef>();
|
const navigation = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const container = (
|
const container = (
|
||||||
<BaseNavigationContainer ref={navigation}>
|
<BaseNavigationContainer ref={navigation}>
|
||||||
<TestNavigator>
|
<TestNavigator>
|
||||||
<Screen name="bar" options={{ a: 'b' }}>
|
<Screen name="bar" options={{ a: 'b' }}>
|
||||||
{() => (
|
{() => (
|
||||||
<TestNavigator
|
<TestNavigator initialRouteName="bar-a">
|
||||||
initialRouteName="bar-a"
|
|
||||||
screenOptions={() => ({ sample2: 'data' })}
|
|
||||||
>
|
|
||||||
<Screen
|
<Screen
|
||||||
name="bar-a"
|
name="bar-a"
|
||||||
component={TestScreen}
|
component={TestScreen}
|
||||||
options={{ sample: 'data' }}
|
options={{ sample: '1' }}
|
||||||
/>
|
/>
|
||||||
<Screen
|
<Screen
|
||||||
name="bar-b"
|
name="bar-b"
|
||||||
component={TestScreen}
|
component={TestScreen}
|
||||||
options={{ sample3: 'data' }}
|
options={{ sample2: '2' }}
|
||||||
/>
|
/>
|
||||||
</TestNavigator>
|
</TestNavigator>
|
||||||
)}
|
)}
|
||||||
@@ -1870,16 +1907,123 @@ it("returns focused screen's options with getCurrentOptions when focused screen
|
|||||||
|
|
||||||
render(container).update(container);
|
render(container).update(container);
|
||||||
|
|
||||||
expect(navigation.current?.getCurrentOptions()).toEqual({
|
expect(navigation.getCurrentOptions()).toEqual({
|
||||||
sample: 'data',
|
sample: '1',
|
||||||
sample2: 'data',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
act(() => navigation.current?.navigate('bar-b'));
|
act(() => navigation.navigate('bar-b'));
|
||||||
|
|
||||||
expect(navigation.current?.getCurrentOptions()).toEqual({
|
expect(navigation.getCurrentOptions()).toEqual({
|
||||||
sample2: 'data',
|
sample2: '2',
|
||||||
sample3: 'data',
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns focused screen's options with getCurrentOptions when focused screen is rendered when using screenOptions", () => {
|
||||||
|
const TestNavigator = (props: any): any => {
|
||||||
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
|
return descriptors[state.routes[state.index].key].render();
|
||||||
|
};
|
||||||
|
|
||||||
|
const TestScreen = () => null;
|
||||||
|
|
||||||
|
const navigation = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
|
const container = (
|
||||||
|
<BaseNavigationContainer ref={navigation}>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="bar" options={{ a: 'b' }}>
|
||||||
|
{() => (
|
||||||
|
<TestNavigator
|
||||||
|
initialRouteName="bar-a"
|
||||||
|
screenOptions={() => ({ sample2: '2' })}
|
||||||
|
>
|
||||||
|
<Screen
|
||||||
|
name="bar-a"
|
||||||
|
component={TestScreen}
|
||||||
|
options={{ sample: '1' }}
|
||||||
|
/>
|
||||||
|
<Screen
|
||||||
|
name="bar-b"
|
||||||
|
component={TestScreen}
|
||||||
|
options={{ sample3: '3' }}
|
||||||
|
/>
|
||||||
|
</TestNavigator>
|
||||||
|
)}
|
||||||
|
</Screen>
|
||||||
|
<Screen name="xux" component={TestScreen} />
|
||||||
|
</TestNavigator>
|
||||||
|
</BaseNavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
render(container).update(container);
|
||||||
|
|
||||||
|
expect(navigation.getCurrentOptions()).toEqual({
|
||||||
|
sample: '1',
|
||||||
|
sample2: '2',
|
||||||
|
});
|
||||||
|
|
||||||
|
act(() => navigation.navigate('bar-b'));
|
||||||
|
|
||||||
|
expect(navigation.getCurrentOptions()).toEqual({
|
||||||
|
sample2: '2',
|
||||||
|
sample3: '3',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns focused screen's options with getCurrentOptions when focused screen is rendered when using Group", () => {
|
||||||
|
const TestNavigator = (props: any): any => {
|
||||||
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
|
return descriptors[state.routes[state.index].key].render();
|
||||||
|
};
|
||||||
|
|
||||||
|
const TestScreen = () => null;
|
||||||
|
|
||||||
|
const navigation = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
|
const container = (
|
||||||
|
<BaseNavigationContainer ref={navigation}>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="bar" options={{ a: 'b' }}>
|
||||||
|
{() => (
|
||||||
|
<TestNavigator
|
||||||
|
initialRouteName="bar-a"
|
||||||
|
screenOptions={() => ({ sample2: '2' })}
|
||||||
|
>
|
||||||
|
<Screen
|
||||||
|
name="bar-a"
|
||||||
|
component={TestScreen}
|
||||||
|
options={{ sample: '1' }}
|
||||||
|
/>
|
||||||
|
<Group screenOptions={{ sample4: '4' }}>
|
||||||
|
<Screen
|
||||||
|
name="bar-b"
|
||||||
|
component={TestScreen}
|
||||||
|
options={{ sample3: '3' }}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
</TestNavigator>
|
||||||
|
)}
|
||||||
|
</Screen>
|
||||||
|
<Screen name="xux" component={TestScreen} />
|
||||||
|
</TestNavigator>
|
||||||
|
</BaseNavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
render(container).update(container);
|
||||||
|
|
||||||
|
expect(navigation.getCurrentOptions()).toEqual({
|
||||||
|
sample: '1',
|
||||||
|
sample2: '2',
|
||||||
|
});
|
||||||
|
|
||||||
|
act(() => navigation.navigate('bar-b'));
|
||||||
|
|
||||||
|
expect(navigation.getCurrentOptions()).toEqual({
|
||||||
|
sample2: '2',
|
||||||
|
sample3: '3',
|
||||||
|
sample4: '4',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1892,26 +2036,23 @@ it("returns focused screen's options with getCurrentOptions when all screens are
|
|||||||
|
|
||||||
const TestScreen = () => null;
|
const TestScreen = () => null;
|
||||||
|
|
||||||
const navigation = React.createRef<NavigationContainerRef>();
|
const navigation = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const container = (
|
const container = (
|
||||||
<BaseNavigationContainer ref={navigation}>
|
<BaseNavigationContainer ref={navigation}>
|
||||||
<TestNavigator>
|
<TestNavigator>
|
||||||
<Screen name="bar" options={{ a: 'b' }}>
|
<Screen name="bar" options={{ a: 'b' }}>
|
||||||
{() => (
|
{() => (
|
||||||
<TestNavigator
|
<TestNavigator initialRouteName="bar-a">
|
||||||
initialRouteName="bar-a"
|
|
||||||
screenOptions={() => ({ sample2: 'data' })}
|
|
||||||
>
|
|
||||||
<Screen
|
<Screen
|
||||||
name="bar-a"
|
name="bar-a"
|
||||||
component={TestScreen}
|
component={TestScreen}
|
||||||
options={{ sample: 'data' }}
|
options={{ sample: '1' }}
|
||||||
/>
|
/>
|
||||||
<Screen
|
<Screen
|
||||||
name="bar-b"
|
name="bar-b"
|
||||||
component={TestScreen}
|
component={TestScreen}
|
||||||
options={{ sample3: 'data' }}
|
options={{ sample2: '2' }}
|
||||||
/>
|
/>
|
||||||
</TestNavigator>
|
</TestNavigator>
|
||||||
)}
|
)}
|
||||||
@@ -1923,16 +2064,123 @@ it("returns focused screen's options with getCurrentOptions when all screens are
|
|||||||
|
|
||||||
render(container).update(container);
|
render(container).update(container);
|
||||||
|
|
||||||
expect(navigation.current?.getCurrentOptions()).toEqual({
|
expect(navigation.getCurrentOptions()).toEqual({
|
||||||
sample: 'data',
|
sample: '1',
|
||||||
sample2: 'data',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
act(() => navigation.current?.navigate('bar-b'));
|
act(() => navigation.navigate('bar-b'));
|
||||||
|
|
||||||
expect(navigation.current?.getCurrentOptions()).toEqual({
|
expect(navigation.getCurrentOptions()).toEqual({
|
||||||
sample2: 'data',
|
sample2: '2',
|
||||||
sample3: 'data',
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns focused screen's options with getCurrentOptions when all screens are rendered with screenOptions", () => {
|
||||||
|
const TestNavigator = (props: any): any => {
|
||||||
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
|
return <>{state.routes.map((route) => descriptors[route.key].render())}</>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const TestScreen = () => null;
|
||||||
|
|
||||||
|
const navigation = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
|
const container = (
|
||||||
|
<BaseNavigationContainer ref={navigation}>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="bar" options={{ a: 'b' }}>
|
||||||
|
{() => (
|
||||||
|
<TestNavigator
|
||||||
|
initialRouteName="bar-a"
|
||||||
|
screenOptions={() => ({ sample2: '2' })}
|
||||||
|
>
|
||||||
|
<Screen
|
||||||
|
name="bar-a"
|
||||||
|
component={TestScreen}
|
||||||
|
options={{ sample: '1' }}
|
||||||
|
/>
|
||||||
|
<Screen
|
||||||
|
name="bar-b"
|
||||||
|
component={TestScreen}
|
||||||
|
options={{ sample3: '3' }}
|
||||||
|
/>
|
||||||
|
</TestNavigator>
|
||||||
|
)}
|
||||||
|
</Screen>
|
||||||
|
<Screen name="xux" component={TestScreen} />
|
||||||
|
</TestNavigator>
|
||||||
|
</BaseNavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
render(container).update(container);
|
||||||
|
|
||||||
|
expect(navigation.getCurrentOptions()).toEqual({
|
||||||
|
sample: '1',
|
||||||
|
sample2: '2',
|
||||||
|
});
|
||||||
|
|
||||||
|
act(() => navigation.navigate('bar-b'));
|
||||||
|
|
||||||
|
expect(navigation.getCurrentOptions()).toEqual({
|
||||||
|
sample2: '2',
|
||||||
|
sample3: '3',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns focused screen's options with getCurrentOptions when all screens are rendered with Group", () => {
|
||||||
|
const TestNavigator = (props: any): any => {
|
||||||
|
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||||
|
|
||||||
|
return <>{state.routes.map((route) => descriptors[route.key].render())}</>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const TestScreen = () => null;
|
||||||
|
|
||||||
|
const navigation = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
|
const container = (
|
||||||
|
<BaseNavigationContainer ref={navigation}>
|
||||||
|
<TestNavigator>
|
||||||
|
<Screen name="bar" options={{ a: 'b' }}>
|
||||||
|
{() => (
|
||||||
|
<TestNavigator
|
||||||
|
initialRouteName="bar-a"
|
||||||
|
screenOptions={() => ({ sample2: '2' })}
|
||||||
|
>
|
||||||
|
<Screen
|
||||||
|
name="bar-a"
|
||||||
|
component={TestScreen}
|
||||||
|
options={{ sample: '1' }}
|
||||||
|
/>
|
||||||
|
<Group screenOptions={{ sample4: '4' }}>
|
||||||
|
<Screen
|
||||||
|
name="bar-b"
|
||||||
|
component={TestScreen}
|
||||||
|
options={{ sample3: '3' }}
|
||||||
|
/>
|
||||||
|
</Group>
|
||||||
|
</TestNavigator>
|
||||||
|
)}
|
||||||
|
</Screen>
|
||||||
|
<Screen name="xux" component={TestScreen} />
|
||||||
|
</TestNavigator>
|
||||||
|
</BaseNavigationContainer>
|
||||||
|
);
|
||||||
|
|
||||||
|
render(container).update(container);
|
||||||
|
|
||||||
|
expect(navigation.getCurrentOptions()).toEqual({
|
||||||
|
sample: '1',
|
||||||
|
sample2: '2',
|
||||||
|
});
|
||||||
|
|
||||||
|
act(() => navigation.navigate('bar-b'));
|
||||||
|
|
||||||
|
expect(navigation.getCurrentOptions()).toEqual({
|
||||||
|
sample2: '2',
|
||||||
|
sample3: '3',
|
||||||
|
sample4: '4',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1945,7 +2193,7 @@ it('does not throw if while getting current options with no options defined', ()
|
|||||||
|
|
||||||
const TestScreen = () => null;
|
const TestScreen = () => null;
|
||||||
|
|
||||||
const navigation = React.createRef<NavigationContainerRef>();
|
const navigation = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const container = (
|
const container = (
|
||||||
<BaseNavigationContainer ref={navigation}>
|
<BaseNavigationContainer ref={navigation}>
|
||||||
@@ -1968,11 +2216,11 @@ it('does not throw if while getting current options with no options defined', ()
|
|||||||
|
|
||||||
render(container).update(container);
|
render(container).update(container);
|
||||||
|
|
||||||
expect(navigation.current?.getCurrentOptions()).toEqual({});
|
expect(navigation.getCurrentOptions()).toEqual({});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not throw if while getting current options with empty container', () => {
|
it('does not throw if while getting current options with empty container', () => {
|
||||||
const navigation = React.createRef<NavigationContainerRef>();
|
const navigation = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const container = (
|
const container = (
|
||||||
<BaseNavigationContainer ref={navigation} children={null} />
|
<BaseNavigationContainer ref={navigation} children={null} />
|
||||||
@@ -1980,5 +2228,5 @@ it('does not throw if while getting current options with empty container', () =>
|
|||||||
|
|
||||||
render(container).update(container);
|
render(container).update(container);
|
||||||
|
|
||||||
expect(navigation.current?.getCurrentOptions()).toEqual(undefined);
|
expect(navigation.getCurrentOptions()).toEqual(undefined);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,15 +5,16 @@ import {
|
|||||||
DefaultRouterOptions,
|
DefaultRouterOptions,
|
||||||
NavigationState,
|
NavigationState,
|
||||||
StackRouter,
|
StackRouter,
|
||||||
|
ParamListBase,
|
||||||
} from '@react-navigation/routers';
|
} from '@react-navigation/routers';
|
||||||
import useNavigationBuilder from '../useNavigationBuilder';
|
import useNavigationBuilder from '../useNavigationBuilder';
|
||||||
import BaseNavigationContainer from '../BaseNavigationContainer';
|
import BaseNavigationContainer from '../BaseNavigationContainer';
|
||||||
import Screen from '../Screen';
|
import Screen from '../Screen';
|
||||||
|
import createNavigationContainerRef from '../createNavigationContainerRef';
|
||||||
import MockRouter, {
|
import MockRouter, {
|
||||||
MockActions,
|
MockActions,
|
||||||
MockRouterKey,
|
MockRouterKey,
|
||||||
} from './__fixtures__/MockRouter';
|
} from './__fixtures__/MockRouter';
|
||||||
import type { NavigationContainerRef } from '../types';
|
|
||||||
|
|
||||||
jest.mock('nanoid/non-secure', () => {
|
jest.mock('nanoid/non-secure', () => {
|
||||||
const m = { nanoid: () => String(++m.__key), __key: 0 };
|
const m = { nanoid: () => String(++m.__key), __key: 0 };
|
||||||
@@ -571,7 +572,7 @@ it("prevents removing a screen with 'beforeRemove' event", () => {
|
|||||||
|
|
||||||
const onStateChange = jest.fn();
|
const onStateChange = jest.fn();
|
||||||
|
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const element = (
|
const element = (
|
||||||
<BaseNavigationContainer ref={ref} onStateChange={onStateChange}>
|
<BaseNavigationContainer ref={ref} onStateChange={onStateChange}>
|
||||||
@@ -706,7 +707,7 @@ it("prevents removing a child screen with 'beforeRemove' event", () => {
|
|||||||
|
|
||||||
const onStateChange = jest.fn();
|
const onStateChange = jest.fn();
|
||||||
|
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const element = (
|
const element = (
|
||||||
<BaseNavigationContainer ref={ref} onStateChange={onStateChange}>
|
<BaseNavigationContainer ref={ref} onStateChange={onStateChange}>
|
||||||
@@ -867,7 +868,7 @@ it("prevents removing a grand child screen with 'beforeRemove' event", () => {
|
|||||||
|
|
||||||
const onStateChange = jest.fn();
|
const onStateChange = jest.fn();
|
||||||
|
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const element = (
|
const element = (
|
||||||
<BaseNavigationContainer ref={ref} onStateChange={onStateChange}>
|
<BaseNavigationContainer ref={ref} onStateChange={onStateChange}>
|
||||||
@@ -1065,7 +1066,7 @@ it("prevents removing by multiple screens with 'beforeRemove' event", () => {
|
|||||||
|
|
||||||
const onStateChange = jest.fn();
|
const onStateChange = jest.fn();
|
||||||
|
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const element = (
|
const element = (
|
||||||
<BaseNavigationContainer ref={ref} onStateChange={onStateChange}>
|
<BaseNavigationContainer ref={ref} onStateChange={onStateChange}>
|
||||||
@@ -1217,7 +1218,7 @@ it("prevents removing a child screen with 'beforeRemove' event with 'resetRoot'"
|
|||||||
|
|
||||||
const onStateChange = jest.fn();
|
const onStateChange = jest.fn();
|
||||||
|
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const element = (
|
const element = (
|
||||||
<BaseNavigationContainer ref={ref} onStateChange={onStateChange}>
|
<BaseNavigationContainer ref={ref} onStateChange={onStateChange}>
|
||||||
|
|||||||
47
packages/core/src/createNavigationContainerRef.tsx
Normal file
47
packages/core/src/createNavigationContainerRef.tsx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import { CommonActions } from '@react-navigation/routers';
|
||||||
|
import type { NavigationContainerRefWithCurrent } from './types';
|
||||||
|
|
||||||
|
export const NOT_INITIALIZED_ERROR =
|
||||||
|
"The 'navigation' object hasn't been initialized yet. This might happen if you don't have a navigator mounted, or if the navigator hasn't finished mounting. See https://reactnavigation.org/docs/navigating-without-navigation-prop#handling-initialization for more details.";
|
||||||
|
|
||||||
|
export default function createNavigationContainerRef<
|
||||||
|
ParamList extends {} = ReactNavigation.RootParamList
|
||||||
|
>(): NavigationContainerRefWithCurrent<ParamList> {
|
||||||
|
const methods = [
|
||||||
|
...Object.keys(CommonActions),
|
||||||
|
'addListener',
|
||||||
|
'removeListener',
|
||||||
|
'resetRoot',
|
||||||
|
'dispatch',
|
||||||
|
'canGoBack',
|
||||||
|
'getRootState',
|
||||||
|
'getState',
|
||||||
|
'getParent',
|
||||||
|
'getCurrentRoute',
|
||||||
|
'getCurrentOptions',
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
const ref: NavigationContainerRefWithCurrent<ParamList> = {
|
||||||
|
...methods.reduce<any>((acc, name) => {
|
||||||
|
acc[name] = (...args: any[]) => {
|
||||||
|
if (ref.current == null) {
|
||||||
|
console.error(NOT_INITIALIZED_ERROR);
|
||||||
|
} else {
|
||||||
|
// @ts-expect-error: this is ok
|
||||||
|
return ref.current[name](...args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return acc;
|
||||||
|
}, {}),
|
||||||
|
isReady: () => {
|
||||||
|
if (ref.current == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ref.current.isReady();
|
||||||
|
},
|
||||||
|
current: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import type * as React from 'react';
|
import type * as React from 'react';
|
||||||
import type { ParamListBase, NavigationState } from '@react-navigation/routers';
|
import type { ParamListBase, NavigationState } from '@react-navigation/routers';
|
||||||
|
import Group from './Group';
|
||||||
import Screen from './Screen';
|
import Screen from './Screen';
|
||||||
import type { TypedNavigator, EventMapBase } from './types';
|
import type { TypedNavigator, EventMapBase } from './types';
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ export default function createNavigatorFactory<
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
Navigator,
|
Navigator,
|
||||||
|
Group,
|
||||||
Screen,
|
Screen,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ type ConfigItem = {
|
|||||||
screens?: Record<string, ConfigItem>;
|
screens?: Record<string, ConfigItem>;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Options = { initialRouteName?: string; screens: PathConfigMap };
|
type Options = {
|
||||||
|
initialRouteName?: string;
|
||||||
|
screens: PathConfigMap<object>;
|
||||||
|
};
|
||||||
|
|
||||||
type NavigateAction<State extends NavigationState> = {
|
type NavigateAction<State extends NavigationState> = {
|
||||||
type: 'NAVIGATE';
|
type: 'NAVIGATE';
|
||||||
@@ -29,7 +32,9 @@ export default function getActionFromState(
|
|||||||
options?: Options
|
options?: Options
|
||||||
): NavigateAction<NavigationState> | CommonActions.Action | undefined {
|
): NavigateAction<NavigationState> | CommonActions.Action | undefined {
|
||||||
// Create a normalized configs object which will be easier to use
|
// Create a normalized configs object which will be easier to use
|
||||||
const normalizedConfig = options ? createNormalizedConfigItem(options) : {};
|
const normalizedConfig = options
|
||||||
|
? createNormalizedConfigItem(options as PathConfig<object> | string)
|
||||||
|
: {};
|
||||||
|
|
||||||
const routes =
|
const routes =
|
||||||
state.index != null ? state.routes.slice(0, state.index + 1) : state.routes;
|
state.index != null ? state.routes.slice(0, state.index + 1) : state.routes;
|
||||||
@@ -130,7 +135,7 @@ export default function getActionFromState(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const createNormalizedConfigItem = (config: PathConfig | string) =>
|
const createNormalizedConfigItem = (config: PathConfig<object> | string) =>
|
||||||
typeof config === 'object' && config != null
|
typeof config === 'object' && config != null
|
||||||
? {
|
? {
|
||||||
initialRouteName: config.initialRouteName,
|
initialRouteName: config.initialRouteName,
|
||||||
@@ -141,7 +146,7 @@ const createNormalizedConfigItem = (config: PathConfig | string) =>
|
|||||||
}
|
}
|
||||||
: {};
|
: {};
|
||||||
|
|
||||||
const createNormalizedConfigs = (options: PathConfigMap) =>
|
const createNormalizedConfigs = (options: PathConfigMap<object>) =>
|
||||||
Object.entries(options).reduce<Record<string, ConfigItem>>((acc, [k, v]) => {
|
Object.entries(options).reduce<Record<string, ConfigItem>>((acc, [k, v]) => {
|
||||||
acc[k] = createNormalizedConfigItem(v);
|
acc[k] = createNormalizedConfigItem(v);
|
||||||
return acc;
|
return acc;
|
||||||
|
|||||||
@@ -7,7 +7,10 @@ import type {
|
|||||||
import fromEntries from './fromEntries';
|
import fromEntries from './fromEntries';
|
||||||
import type { PathConfig, PathConfigMap } from './types';
|
import type { PathConfig, PathConfigMap } from './types';
|
||||||
|
|
||||||
type Options = { initialRouteName?: string; screens: PathConfigMap };
|
type Options<ParamList> = {
|
||||||
|
initialRouteName?: string;
|
||||||
|
screens: PathConfigMap<ParamList>;
|
||||||
|
};
|
||||||
|
|
||||||
type State = NavigationState | Omit<PartialState<NavigationState>, 'stale'>;
|
type State = NavigationState | Omit<PartialState<NavigationState>, 'stale'>;
|
||||||
|
|
||||||
@@ -61,9 +64,9 @@ const getActiveRoute = (state: State): { name: string; params?: object } => {
|
|||||||
* @param options Extra options to fine-tune how to serialize the path.
|
* @param options Extra options to fine-tune how to serialize the path.
|
||||||
* @returns Path representing the state, e.g. /foo/bar?count=42.
|
* @returns Path representing the state, e.g. /foo/bar?count=42.
|
||||||
*/
|
*/
|
||||||
export default function getPathFromState(
|
export default function getPathFromState<ParamList extends {}>(
|
||||||
state: State,
|
state: State,
|
||||||
options?: Options
|
options?: Options<ParamList>
|
||||||
): string {
|
): string {
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
throw Error(
|
throw Error(
|
||||||
@@ -238,7 +241,7 @@ const joinPaths = (...paths: string[]): string =>
|
|||||||
.join('/');
|
.join('/');
|
||||||
|
|
||||||
const createConfigItem = (
|
const createConfigItem = (
|
||||||
config: PathConfig | string,
|
config: PathConfig<object> | string,
|
||||||
parentPattern?: string
|
parentPattern?: string
|
||||||
): ConfigItem => {
|
): ConfigItem => {
|
||||||
if (typeof config === 'string') {
|
if (typeof config === 'string') {
|
||||||
@@ -276,7 +279,7 @@ const createConfigItem = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const createNormalizedConfigs = (
|
const createNormalizedConfigs = (
|
||||||
options: PathConfigMap,
|
options: PathConfigMap<object>,
|
||||||
pattern?: string
|
pattern?: string
|
||||||
): Record<string, ConfigItem> =>
|
): Record<string, ConfigItem> =>
|
||||||
fromEntries(
|
fromEntries(
|
||||||
|
|||||||
@@ -8,9 +8,9 @@ import type {
|
|||||||
import findFocusedRoute from './findFocusedRoute';
|
import findFocusedRoute from './findFocusedRoute';
|
||||||
import type { PathConfigMap } from './types';
|
import type { PathConfigMap } from './types';
|
||||||
|
|
||||||
type Options = {
|
type Options<ParamList extends {}> = {
|
||||||
initialRouteName?: string;
|
initialRouteName?: string;
|
||||||
screens: PathConfigMap;
|
screens: PathConfigMap<ParamList>;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ParseConfig = Record<string, (value: string) => any>;
|
type ParseConfig = Record<string, (value: string) => any>;
|
||||||
@@ -60,9 +60,9 @@ type ParsedRoute = {
|
|||||||
* @param path Path string to parse and convert, e.g. /foo/bar?count=42.
|
* @param path Path string to parse and convert, e.g. /foo/bar?count=42.
|
||||||
* @param options Extra options to fine-tune how to parse the path.
|
* @param options Extra options to fine-tune how to parse the path.
|
||||||
*/
|
*/
|
||||||
export default function getStateFromPath(
|
export default function getStateFromPath<ParamList extends {}>(
|
||||||
path: string,
|
path: string,
|
||||||
options?: Options
|
options?: Options<ParamList>
|
||||||
): ResultState | undefined {
|
): ResultState | undefined {
|
||||||
let initialRoutes: InitialRouteConfig[] = [];
|
let initialRoutes: InitialRouteConfig[] = [];
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ export default function getStateFromPath(
|
|||||||
...Object.keys(screens).map((key) =>
|
...Object.keys(screens).map((key) =>
|
||||||
createNormalizedConfigs(
|
createNormalizedConfigs(
|
||||||
key,
|
key,
|
||||||
screens as PathConfigMap,
|
screens as PathConfigMap<object>,
|
||||||
[],
|
[],
|
||||||
initialRoutes,
|
initialRoutes,
|
||||||
[]
|
[]
|
||||||
@@ -307,7 +307,7 @@ const matchAgainstConfigs = (remaining: string, configs: RouteConfig[]) => {
|
|||||||
|
|
||||||
const createNormalizedConfigs = (
|
const createNormalizedConfigs = (
|
||||||
screen: string,
|
screen: string,
|
||||||
routeConfig: PathConfigMap,
|
routeConfig: PathConfigMap<object>,
|
||||||
routeNames: string[] = [],
|
routeNames: string[] = [],
|
||||||
initials: InitialRouteConfig[],
|
initials: InitialRouteConfig[],
|
||||||
parentScreens: string[],
|
parentScreens: string[],
|
||||||
@@ -319,6 +319,7 @@ const createNormalizedConfigs = (
|
|||||||
|
|
||||||
parentScreens.push(screen);
|
parentScreens.push(screen);
|
||||||
|
|
||||||
|
// @ts-expect-error: we can't strongly typecheck this for now
|
||||||
const config = routeConfig[screen];
|
const config = routeConfig[screen];
|
||||||
|
|
||||||
if (typeof config === 'string') {
|
if (typeof config === 'string') {
|
||||||
@@ -345,7 +346,13 @@ const createNormalizedConfigs = (
|
|||||||
: config.path || '';
|
: config.path || '';
|
||||||
|
|
||||||
configs.push(
|
configs.push(
|
||||||
createConfigItem(screen, routeNames, pattern, config.path, config.parse)
|
createConfigItem(
|
||||||
|
screen,
|
||||||
|
routeNames,
|
||||||
|
pattern!,
|
||||||
|
config.path,
|
||||||
|
config.parse
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,7 +368,7 @@ const createNormalizedConfigs = (
|
|||||||
Object.keys(config.screens).forEach((nestedConfig) => {
|
Object.keys(config.screens).forEach((nestedConfig) => {
|
||||||
const result = createNormalizedConfigs(
|
const result = createNormalizedConfigs(
|
||||||
nestedConfig,
|
nestedConfig,
|
||||||
config.screens as PathConfigMap,
|
config.screens as PathConfigMap<object>,
|
||||||
routeNames,
|
routeNames,
|
||||||
initials,
|
initials,
|
||||||
[...parentScreens],
|
[...parentScreens],
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ export * from '@react-navigation/routers';
|
|||||||
export { default as BaseNavigationContainer } from './BaseNavigationContainer';
|
export { default as BaseNavigationContainer } from './BaseNavigationContainer';
|
||||||
export { default as createNavigatorFactory } from './createNavigatorFactory';
|
export { default as createNavigatorFactory } from './createNavigatorFactory';
|
||||||
|
|
||||||
|
export { default as createNavigationContainerRef } from './createNavigationContainerRef';
|
||||||
|
export { default as useNavigationContainerRef } from './useNavigationContainerRef';
|
||||||
|
|
||||||
export { default as NavigationHelpersContext } from './NavigationHelpersContext';
|
export { default as NavigationHelpersContext } from './NavigationHelpersContext';
|
||||||
export { default as NavigationContext } from './NavigationContext';
|
export { default as NavigationContext } from './NavigationContext';
|
||||||
export { default as NavigationRouteContext } from './NavigationRouteContext';
|
export { default as NavigationRouteContext } from './NavigationRouteContext';
|
||||||
|
|||||||
@@ -9,13 +9,23 @@ import type {
|
|||||||
ParamListBase,
|
ParamListBase,
|
||||||
} from '@react-navigation/routers';
|
} from '@react-navigation/routers';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||||
|
namespace ReactNavigation {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||||
|
interface RootParamList {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Keyof<T extends {}> = Extract<keyof T, string>;
|
||||||
|
|
||||||
export type DefaultNavigatorOptions<
|
export type DefaultNavigatorOptions<
|
||||||
ScreenOptions extends {},
|
ScreenOptions extends {},
|
||||||
ParamList extends ParamListBase = ParamListBase
|
ParamList extends ParamListBase = ParamListBase
|
||||||
> = DefaultRouterOptions<Extract<keyof ParamList, string>> & {
|
> = DefaultRouterOptions<Keyof<ParamList>> & {
|
||||||
/**
|
/**
|
||||||
* Children React Elements to extract the route configuration from.
|
* Children React Elements to extract the route configuration from.
|
||||||
* Only `Screen` components are supported as children.
|
* Only `Screen`, `Group` and `React.Fragment` are supported as children.
|
||||||
*/
|
*/
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
/**
|
/**
|
||||||
@@ -24,7 +34,7 @@ export type DefaultNavigatorOptions<
|
|||||||
screenOptions?:
|
screenOptions?:
|
||||||
| ScreenOptions
|
| ScreenOptions
|
||||||
| ((props: {
|
| ((props: {
|
||||||
route: RouteProp<ParamList, keyof ParamList>;
|
route: RouteProp<ParamList>;
|
||||||
navigation: any;
|
navigation: any;
|
||||||
}) => ScreenOptions);
|
}) => ScreenOptions);
|
||||||
/**
|
/**
|
||||||
@@ -34,7 +44,7 @@ export type DefaultNavigatorOptions<
|
|||||||
defaultScreenOptions?:
|
defaultScreenOptions?:
|
||||||
| ScreenOptions
|
| ScreenOptions
|
||||||
| ((props: {
|
| ((props: {
|
||||||
route: RouteProp<ParamList, keyof ParamList>;
|
route: RouteProp<ParamList>;
|
||||||
navigation: any;
|
navigation: any;
|
||||||
options: ScreenOptions;
|
options: ScreenOptions;
|
||||||
}) => ScreenOptions);
|
}) => ScreenOptions);
|
||||||
@@ -96,11 +106,11 @@ export type EventConsumer<EventMap extends EventMapBase> = {
|
|||||||
* @param type Type of the event (e.g. `focus`, `blur`)
|
* @param type Type of the event (e.g. `focus`, `blur`)
|
||||||
* @param callback Callback listener which is executed upon receiving the event.
|
* @param callback Callback listener which is executed upon receiving the event.
|
||||||
*/
|
*/
|
||||||
addListener<EventName extends Extract<keyof EventMap, string>>(
|
addListener<EventName extends Keyof<EventMap>>(
|
||||||
type: EventName,
|
type: EventName,
|
||||||
callback: EventListenerCallback<EventMap, EventName>
|
callback: EventListenerCallback<EventMap, EventName>
|
||||||
): () => void;
|
): () => void;
|
||||||
removeListener<EventName extends Extract<keyof EventMap, string>>(
|
removeListener<EventName extends Keyof<EventMap>>(
|
||||||
type: EventName,
|
type: EventName,
|
||||||
callback: EventListenerCallback<EventMap, EventName>
|
callback: EventListenerCallback<EventMap, EventName>
|
||||||
): void;
|
): void;
|
||||||
@@ -115,7 +125,7 @@ export type EventEmitter<EventMap extends EventMapBase> = {
|
|||||||
* @param [options.target] Key of the target route which should receive the event.
|
* @param [options.target] Key of the target route which should receive the event.
|
||||||
* If not specified, all routes receive the event.
|
* If not specified, all routes receive the event.
|
||||||
*/
|
*/
|
||||||
emit<EventName extends Extract<keyof EventMap, string>>(
|
emit<EventName extends Keyof<EventMap>>(
|
||||||
options: {
|
options: {
|
||||||
type: EventName;
|
type: EventName;
|
||||||
target?: string;
|
target?: string;
|
||||||
@@ -263,8 +273,8 @@ export type NavigationContainerProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type NavigationProp<
|
export type NavigationProp<
|
||||||
ParamList extends ParamListBase,
|
ParamList extends {},
|
||||||
RouteName extends keyof ParamList = string,
|
RouteName extends keyof ParamList = Keyof<ParamList>,
|
||||||
State extends NavigationState = NavigationState<ParamList>,
|
State extends NavigationState = NavigationState<ParamList>,
|
||||||
ScreenOptions extends {} = {},
|
ScreenOptions extends {} = {},
|
||||||
EventMap extends EventMapBase = {}
|
EventMap extends EventMapBase = {}
|
||||||
@@ -289,7 +299,7 @@ export type NavigationProp<
|
|||||||
|
|
||||||
export type RouteProp<
|
export type RouteProp<
|
||||||
ParamList extends ParamListBase,
|
ParamList extends ParamListBase,
|
||||||
RouteName extends keyof ParamList
|
RouteName extends keyof ParamList = Keyof<ParamList>
|
||||||
> = Route<Extract<RouteName, string>, ParamList[RouteName]>;
|
> = Route<Extract<RouteName, string>, ParamList[RouteName]>;
|
||||||
|
|
||||||
export type CompositeNavigationProp<
|
export type CompositeNavigationProp<
|
||||||
@@ -325,6 +335,19 @@ export type CompositeNavigationProp<
|
|||||||
A extends NavigationProp<any, any, any, any, infer E> ? E : {}
|
A extends NavigationProp<any, any, any, any, infer E> ? E : {}
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
export type CompositeScreenProps<
|
||||||
|
A extends {
|
||||||
|
navigation: NavigationProp<ParamListBase, string, any, any>;
|
||||||
|
route: RouteProp<ParamListBase>;
|
||||||
|
},
|
||||||
|
B extends {
|
||||||
|
navigation: NavigationHelpersCommon<ParamListBase, any>;
|
||||||
|
}
|
||||||
|
> = {
|
||||||
|
navigation: CompositeNavigationProp<A['navigation'], B['navigation']>;
|
||||||
|
route: A['route'];
|
||||||
|
};
|
||||||
|
|
||||||
export type Descriptor<
|
export type Descriptor<
|
||||||
ScreenOptions extends {},
|
ScreenOptions extends {},
|
||||||
Navigation extends NavigationProp<any, any, any, any, any>,
|
Navigation extends NavigationProp<any, any, any, any, any>,
|
||||||
@@ -361,6 +384,38 @@ export type ScreenListeners<
|
|||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
export type RouteConfigComponent<
|
||||||
|
ParamList extends ParamListBase,
|
||||||
|
RouteName extends keyof ParamList
|
||||||
|
> =
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* React component to render for this screen.
|
||||||
|
*/
|
||||||
|
component: React.ComponentType<any>;
|
||||||
|
getComponent?: never;
|
||||||
|
children?: never;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* Lazily get a React component to render for this screen.
|
||||||
|
*/
|
||||||
|
getComponent: () => React.ComponentType<any>;
|
||||||
|
component?: never;
|
||||||
|
children?: never;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
/**
|
||||||
|
* Render callback to render content of this screen.
|
||||||
|
*/
|
||||||
|
children: (props: {
|
||||||
|
route: RouteProp<ParamList, RouteName>;
|
||||||
|
navigation: any;
|
||||||
|
}) => React.ReactNode;
|
||||||
|
component?: never;
|
||||||
|
getComponent?: never;
|
||||||
|
};
|
||||||
|
|
||||||
export type RouteConfig<
|
export type RouteConfig<
|
||||||
ParamList extends ParamListBase,
|
ParamList extends ParamListBase,
|
||||||
RouteName extends keyof ParamList,
|
RouteName extends keyof ParamList,
|
||||||
@@ -405,35 +460,27 @@ export type RouteConfig<
|
|||||||
* Initial params object for the route.
|
* Initial params object for the route.
|
||||||
*/
|
*/
|
||||||
initialParams?: Partial<ParamList[RouteName]>;
|
initialParams?: Partial<ParamList[RouteName]>;
|
||||||
} & (
|
} & RouteConfigComponent<ParamList, RouteName>;
|
||||||
| {
|
|
||||||
/**
|
export type RouteGroupConfig<
|
||||||
* React component to render for this screen.
|
ParamList extends ParamListBase,
|
||||||
*/
|
ScreenOptions extends {}
|
||||||
component: React.ComponentType<any>;
|
> = {
|
||||||
getComponent?: never;
|
/**
|
||||||
children?: never;
|
* Navigator options for this screen.
|
||||||
}
|
*/
|
||||||
| {
|
screenOptions?:
|
||||||
/**
|
| ScreenOptions
|
||||||
* Lazily get a React component to render for this screen.
|
| ((props: {
|
||||||
*/
|
route: RouteProp<ParamList, keyof ParamList>;
|
||||||
getComponent: () => React.ComponentType<any>;
|
|
||||||
component?: never;
|
|
||||||
children?: never;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* Render callback to render content of this screen.
|
|
||||||
*/
|
|
||||||
children: (props: {
|
|
||||||
route: RouteProp<ParamList, RouteName>;
|
|
||||||
navigation: any;
|
navigation: any;
|
||||||
}) => React.ReactNode;
|
}) => ScreenOptions);
|
||||||
component?: never;
|
/**
|
||||||
getComponent?: never;
|
* Children React Elements to extract the route configuration from.
|
||||||
}
|
* Only `Screen`, `Group` and `React.Fragment` are supported as children.
|
||||||
);
|
*/
|
||||||
|
children: React.ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
export type NavigationContainerEventMap = {
|
export type NavigationContainerEventMap = {
|
||||||
/**
|
/**
|
||||||
@@ -470,7 +517,9 @@ export type NavigationContainerEventMap = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type NavigationContainerRef = NavigationHelpers<ParamListBase> &
|
export type NavigationContainerRef<
|
||||||
|
ParamList extends {}
|
||||||
|
> = NavigationHelpers<ParamList> &
|
||||||
EventConsumer<NavigationContainerEventMap> & {
|
EventConsumer<NavigationContainerEventMap> & {
|
||||||
/**
|
/**
|
||||||
* Reset the navigation state of the root navigator to the provided state.
|
* Reset the navigation state of the root navigator to the provided state.
|
||||||
@@ -490,8 +539,18 @@ export type NavigationContainerRef = NavigationHelpers<ParamListBase> &
|
|||||||
* Get the currently focused route's options.
|
* Get the currently focused route's options.
|
||||||
*/
|
*/
|
||||||
getCurrentOptions(): object | undefined;
|
getCurrentOptions(): object | undefined;
|
||||||
|
/**
|
||||||
|
* Whether the navigation container is ready to handle actions.
|
||||||
|
*/
|
||||||
|
isReady(): boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type NavigationContainerRefWithCurrent<
|
||||||
|
ParamList extends {}
|
||||||
|
> = NavigationContainerRef<ParamList> & {
|
||||||
|
current: NavigationContainerRef<ParamList> | null;
|
||||||
|
};
|
||||||
|
|
||||||
export type TypedNavigator<
|
export type TypedNavigator<
|
||||||
ParamList extends ParamListBase,
|
ParamList extends ParamListBase,
|
||||||
State extends NavigationState,
|
State extends NavigationState,
|
||||||
@@ -509,6 +568,10 @@ export type TypedNavigator<
|
|||||||
> &
|
> &
|
||||||
DefaultNavigatorOptions<ScreenOptions, ParamList>
|
DefaultNavigatorOptions<ScreenOptions, ParamList>
|
||||||
>;
|
>;
|
||||||
|
/**
|
||||||
|
* Component used for grouping multiple route configuration.
|
||||||
|
*/
|
||||||
|
Group: React.ComponentType<RouteGroupConfig<ParamList, ScreenOptions>>;
|
||||||
/**
|
/**
|
||||||
* Component used for specifying route configuration.
|
* Component used for specifying route configuration.
|
||||||
*/
|
*/
|
||||||
@@ -546,15 +609,20 @@ export type NavigatorScreenParams<
|
|||||||
};
|
};
|
||||||
}[keyof ParamList];
|
}[keyof ParamList];
|
||||||
|
|
||||||
export type PathConfig = {
|
export type PathConfig<ParamList extends {}> = {
|
||||||
path?: string;
|
path?: string;
|
||||||
exact?: boolean;
|
exact?: boolean;
|
||||||
parse?: Record<string, (value: string) => any>;
|
parse?: Record<string, (value: string) => any>;
|
||||||
stringify?: Record<string, (value: any) => string>;
|
stringify?: Record<string, (value: any) => string>;
|
||||||
screens?: PathConfigMap;
|
screens?: PathConfigMap<ParamList>;
|
||||||
initialRouteName?: string;
|
initialRouteName?: keyof ParamList;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PathConfigMap = {
|
export type PathConfigMap<ParamList extends {}> = {
|
||||||
[routeName: string]: string | PathConfig;
|
[RouteName in keyof ParamList]?: ParamList[RouteName] extends NavigatorScreenParams<
|
||||||
|
infer T,
|
||||||
|
any
|
||||||
|
>
|
||||||
|
? string | PathConfig<T>
|
||||||
|
: string | Omit<PathConfig<{}>, 'screens' | 'initialRouteName'>;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,11 +13,7 @@ type Options = {
|
|||||||
navigation: NavigationHelpers<ParamListBase>;
|
navigation: NavigationHelpers<ParamListBase>;
|
||||||
descriptors: Record<
|
descriptors: Record<
|
||||||
string,
|
string,
|
||||||
Descriptor<
|
Descriptor<object, NavigationProp<ParamListBase>, RouteProp<ParamListBase>>
|
||||||
object,
|
|
||||||
NavigationProp<ParamListBase>,
|
|
||||||
RouteProp<ParamListBase, string>
|
|
||||||
>
|
|
||||||
>;
|
>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,22 @@ import type {
|
|||||||
NavigationProp,
|
NavigationProp,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
|
export type ScreenConfigWithParent<
|
||||||
|
State extends NavigationState,
|
||||||
|
ScreenOptions extends {},
|
||||||
|
EventMap extends EventMapBase
|
||||||
|
> = [
|
||||||
|
(ScreenOptionsOrCallback<ScreenOptions> | undefined)[] | undefined,
|
||||||
|
RouteConfig<ParamListBase, string, State, ScreenOptions, EventMap>
|
||||||
|
];
|
||||||
|
|
||||||
|
type ScreenOptionsOrCallback<ScreenOptions extends {}> =
|
||||||
|
| ScreenOptions
|
||||||
|
| ((props: {
|
||||||
|
route: RouteProp<ParamListBase, string>;
|
||||||
|
navigation: any;
|
||||||
|
}) => ScreenOptions);
|
||||||
|
|
||||||
type Options<
|
type Options<
|
||||||
State extends NavigationState,
|
State extends NavigationState,
|
||||||
ScreenOptions extends {},
|
ScreenOptions extends {},
|
||||||
@@ -32,19 +48,14 @@ type Options<
|
|||||||
state: State;
|
state: State;
|
||||||
screens: Record<
|
screens: Record<
|
||||||
string,
|
string,
|
||||||
RouteConfig<ParamListBase, string, State, ScreenOptions, EventMap>
|
ScreenConfigWithParent<State, ScreenOptions, EventMap>
|
||||||
>;
|
>;
|
||||||
navigation: NavigationHelpers<ParamListBase>;
|
navigation: NavigationHelpers<ParamListBase>;
|
||||||
screenOptions?:
|
screenOptions?: ScreenOptionsOrCallback<ScreenOptions>;
|
||||||
| ScreenOptions
|
|
||||||
| ((props: {
|
|
||||||
route: RouteProp<ParamListBase, string>;
|
|
||||||
navigation: any;
|
|
||||||
}) => ScreenOptions);
|
|
||||||
defaultScreenOptions?:
|
defaultScreenOptions?:
|
||||||
| ScreenOptions
|
| ScreenOptions
|
||||||
| ((props: {
|
| ((props: {
|
||||||
route: RouteProp<ParamListBase, string>;
|
route: RouteProp<ParamListBase>;
|
||||||
navigation: any;
|
navigation: any;
|
||||||
options: ScreenOptions;
|
options: ScreenOptions;
|
||||||
}) => ScreenOptions);
|
}) => ScreenOptions);
|
||||||
@@ -133,33 +144,35 @@ export default function useDescriptors<
|
|||||||
ScreenOptions,
|
ScreenOptions,
|
||||||
NavigationProp<ParamListBase, string, State, ScreenOptions, EventMap> &
|
NavigationProp<ParamListBase, string, State, ScreenOptions, EventMap> &
|
||||||
ActionHelpers,
|
ActionHelpers,
|
||||||
RouteProp<ParamListBase, string>
|
RouteProp<ParamListBase>
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
>((acc, route, i) => {
|
>((acc, route, i) => {
|
||||||
const screen = screens[route.name];
|
const config = screens[route.name];
|
||||||
|
const screen = config[1];
|
||||||
const navigation = navigations[route.key];
|
const navigation = navigations[route.key];
|
||||||
|
|
||||||
const customOptions = {
|
const optionsList = [
|
||||||
// The default `screenOptions` passed to the navigator
|
// The default `screenOptions` passed to the navigator
|
||||||
...(typeof screenOptions === 'object' || screenOptions == null
|
screenOptions,
|
||||||
? screenOptions
|
// The `screenOptions` props passed to `Group` elements
|
||||||
: // @ts-expect-error: this is a function, but typescript doesn't think so
|
...((config[0]
|
||||||
screenOptions({
|
? config[0].filter(Boolean)
|
||||||
route,
|
: []) as ScreenOptionsOrCallback<ScreenOptions>[]),
|
||||||
navigation,
|
// The `options` prop passed to `Screen` elements,
|
||||||
})),
|
screen.options,
|
||||||
// The `options` prop passed to `Screen` elements
|
|
||||||
...(typeof screen.options === 'object' || screen.options == null
|
|
||||||
? screen.options
|
|
||||||
: // @ts-expect-error: this is a function, but typescript doesn't think so
|
|
||||||
screen.options({
|
|
||||||
route,
|
|
||||||
navigation,
|
|
||||||
})),
|
|
||||||
// The options set via `navigation.setOptions`
|
// The options set via `navigation.setOptions`
|
||||||
...options[route.key],
|
options[route.key],
|
||||||
};
|
];
|
||||||
|
|
||||||
|
const customOptions = optionsList.reduce<ScreenOptions>(
|
||||||
|
(acc, curr) =>
|
||||||
|
Object.assign(
|
||||||
|
acc,
|
||||||
|
typeof curr !== 'function' ? curr : curr({ route, navigation })
|
||||||
|
),
|
||||||
|
{} as ScreenOptions
|
||||||
|
);
|
||||||
|
|
||||||
const mergedOptions = {
|
const mergedOptions = {
|
||||||
...(typeof defaultScreenOptions === 'function'
|
...(typeof defaultScreenOptions === 'function'
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import type { ParamListBase } from '@react-navigation/routers';
|
|
||||||
import NavigationContext from './NavigationContext';
|
import NavigationContext from './NavigationContext';
|
||||||
import type { NavigationProp } from './types';
|
import type { NavigationProp } from './types';
|
||||||
|
|
||||||
@@ -9,7 +8,7 @@ import type { NavigationProp } from './types';
|
|||||||
* @returns Navigation prop of the parent screen.
|
* @returns Navigation prop of the parent screen.
|
||||||
*/
|
*/
|
||||||
export default function useNavigation<
|
export default function useNavigation<
|
||||||
T extends NavigationProp<ParamListBase>
|
T extends NavigationProp<any> = NavigationProp<ReactNavigation.RootParamList>
|
||||||
>(): T {
|
>(): T {
|
||||||
const navigation = React.useContext(NavigationContext);
|
const navigation = React.useContext(NavigationContext);
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,11 @@ import {
|
|||||||
} from '@react-navigation/routers';
|
} from '@react-navigation/routers';
|
||||||
import NavigationStateContext from './NavigationStateContext';
|
import NavigationStateContext from './NavigationStateContext';
|
||||||
import NavigationRouteContext from './NavigationRouteContext';
|
import NavigationRouteContext from './NavigationRouteContext';
|
||||||
|
import Group from './Group';
|
||||||
import Screen from './Screen';
|
import Screen from './Screen';
|
||||||
import useEventEmitter from './useEventEmitter';
|
import useEventEmitter from './useEventEmitter';
|
||||||
import useRegisterNavigator from './useRegisterNavigator';
|
import useRegisterNavigator from './useRegisterNavigator';
|
||||||
import useDescriptors from './useDescriptors';
|
import useDescriptors, { ScreenConfigWithParent } from './useDescriptors';
|
||||||
import useNavigationHelpers from './useNavigationHelpers';
|
import useNavigationHelpers from './useNavigationHelpers';
|
||||||
import useOnAction from './useOnAction';
|
import useOnAction from './useOnAction';
|
||||||
import useFocusEvents from './useFocusEvents';
|
import useFocusEvents from './useFocusEvents';
|
||||||
@@ -57,33 +58,40 @@ const getRouteConfigsFromChildren = <
|
|||||||
ScreenOptions extends {},
|
ScreenOptions extends {},
|
||||||
EventMap extends EventMapBase
|
EventMap extends EventMapBase
|
||||||
>(
|
>(
|
||||||
children: React.ReactNode
|
children: React.ReactNode,
|
||||||
|
options?: ScreenConfigWithParent<State, ScreenOptions, EventMap>[0]
|
||||||
) => {
|
) => {
|
||||||
const configs = React.Children.toArray(children).reduce<
|
const configs = React.Children.toArray(children).reduce<
|
||||||
RouteConfig<ParamListBase, string, State, ScreenOptions, EventMap>[]
|
ScreenConfigWithParent<State, ScreenOptions, EventMap>[]
|
||||||
>((acc, child) => {
|
>((acc, child) => {
|
||||||
if (React.isValidElement(child)) {
|
if (React.isValidElement(child)) {
|
||||||
if (child.type === Screen) {
|
if (child.type === Screen) {
|
||||||
// We can only extract the config from `Screen` elements
|
// We can only extract the config from `Screen` elements
|
||||||
// If something else was rendered, it's probably a bug
|
// If something else was rendered, it's probably a bug
|
||||||
acc.push(
|
acc.push([
|
||||||
|
options,
|
||||||
child.props as RouteConfig<
|
child.props as RouteConfig<
|
||||||
ParamListBase,
|
ParamListBase,
|
||||||
string,
|
string,
|
||||||
State,
|
State,
|
||||||
ScreenOptions,
|
ScreenOptions,
|
||||||
EventMap
|
EventMap
|
||||||
>
|
>,
|
||||||
);
|
]);
|
||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child.type === React.Fragment) {
|
if (child.type === React.Fragment || child.type === Group) {
|
||||||
// When we encounter a fragment, we need to dive into its children to extract the configs
|
// When we encounter a fragment or group, we need to dive into its children to extract the configs
|
||||||
// This is handy to conditionally define a group of screens
|
// This is handy to conditionally define a group of screens
|
||||||
acc.push(
|
acc.push(
|
||||||
...getRouteConfigsFromChildren<State, ScreenOptions, EventMap>(
|
...getRouteConfigsFromChildren<State, ScreenOptions, EventMap>(
|
||||||
child.props.children
|
child.props.children,
|
||||||
|
child.type !== Group
|
||||||
|
? options
|
||||||
|
: options != null
|
||||||
|
? [...options, child.props.screenOptions]
|
||||||
|
: [child.props.screenOptions]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return acc;
|
return acc;
|
||||||
@@ -91,7 +99,7 @@ const getRouteConfigsFromChildren = <
|
|||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`A navigator can only contain 'Screen' components as its direct children (found ${
|
`A navigator can only contain 'Screen', 'Group' or 'React.Fragment' as its direct children (found ${
|
||||||
React.isValidElement(child)
|
React.isValidElement(child)
|
||||||
? `'${
|
? `'${
|
||||||
typeof child.type === 'string' ? child.type : child.type?.name
|
typeof child.type === 'string' ? child.type : child.type?.name
|
||||||
@@ -107,7 +115,7 @@ const getRouteConfigsFromChildren = <
|
|||||||
|
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
configs.forEach((config) => {
|
configs.forEach((config) => {
|
||||||
const { name, children, component, getComponent } = config;
|
const { name, children, component, getComponent } = config[1];
|
||||||
|
|
||||||
if (typeof name !== 'string' || !name) {
|
if (typeof name !== 'string' || !name) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@@ -220,25 +228,22 @@ export default function useNavigationBuilder<
|
|||||||
>(children);
|
>(children);
|
||||||
|
|
||||||
const screens = routeConfigs.reduce<
|
const screens = routeConfigs.reduce<
|
||||||
Record<
|
Record<string, ScreenConfigWithParent<State, ScreenOptions, EventMap>>
|
||||||
string,
|
|
||||||
RouteConfig<ParamListBase, string, State, ScreenOptions, EventMap>
|
|
||||||
>
|
|
||||||
>((acc, config) => {
|
>((acc, config) => {
|
||||||
if (config.name in acc) {
|
if (config[1].name in acc) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`A navigator cannot contain multiple 'Screen' components with the same name (found duplicate screen named '${config.name}')`
|
`A navigator cannot contain multiple 'Screen' components with the same name (found duplicate screen named '${config[1].name}')`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
acc[config.name] = config;
|
acc[config[1].name] = config;
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
||||||
const routeNames = routeConfigs.map((config) => config.name);
|
const routeNames = routeConfigs.map((config) => config[1].name);
|
||||||
const routeParamList = routeNames.reduce<Record<string, object | undefined>>(
|
const routeParamList = routeNames.reduce<Record<string, object | undefined>>(
|
||||||
(acc, curr) => {
|
(acc, curr) => {
|
||||||
const { initialParams } = screens[curr];
|
const { initialParams } = screens[curr][1];
|
||||||
const initialParamsFromParams =
|
const initialParamsFromParams =
|
||||||
route?.params?.state == null &&
|
route?.params?.state == null &&
|
||||||
route?.params?.initial !== false &&
|
route?.params?.initial !== false &&
|
||||||
@@ -263,7 +268,7 @@ export default function useNavigationBuilder<
|
|||||||
>(
|
>(
|
||||||
(acc, curr) =>
|
(acc, curr) =>
|
||||||
Object.assign(acc, {
|
Object.assign(acc, {
|
||||||
[curr]: screens[curr].getId,
|
[curr]: screens[curr][1].getId,
|
||||||
}),
|
}),
|
||||||
{}
|
{}
|
||||||
);
|
);
|
||||||
@@ -481,7 +486,7 @@ export default function useNavigationBuilder<
|
|||||||
const listeners = ([] as (((e: any) => void) | undefined)[])
|
const listeners = ([] as (((e: any) => void) | undefined)[])
|
||||||
.concat(
|
.concat(
|
||||||
...routeNames.map((name) => {
|
...routeNames.map((name) => {
|
||||||
const { listeners } = screens[name];
|
const { listeners } = screens[name][1];
|
||||||
const map =
|
const map =
|
||||||
typeof listeners === 'function'
|
typeof listeners === 'function'
|
||||||
? listeners({ route: route as any, navigation })
|
? listeners({ route: route as any, navigation })
|
||||||
|
|||||||
18
packages/core/src/useNavigationContainerRef.tsx
Normal file
18
packages/core/src/useNavigationContainerRef.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import type { ParamListBase } from '@react-navigation/routers';
|
||||||
|
import createNavigationContainerRef from './createNavigationContainerRef';
|
||||||
|
import type { NavigationContainerRefWithCurrent } from './types';
|
||||||
|
|
||||||
|
export default function useNavigationContainerRef<
|
||||||
|
ParamList extends ParamListBase
|
||||||
|
>(): NavigationContainerRefWithCurrent<ParamList> {
|
||||||
|
const navigation = React.useRef<NavigationContainerRefWithCurrent<ParamList> | null>(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
if (navigation.current == null) {
|
||||||
|
navigation.current = createNavigationContainerRef<ParamList>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return navigation.current;
|
||||||
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import type { ParamListBase, NavigationState } from '@react-navigation/routers';
|
import type { ParamListBase } from '@react-navigation/routers';
|
||||||
import NavigationStateContext from './NavigationStateContext';
|
import NavigationStateContext from './NavigationStateContext';
|
||||||
import NavigationBuilderContext from './NavigationBuilderContext';
|
import NavigationBuilderContext from './NavigationBuilderContext';
|
||||||
import type { NavigationProp } from './types';
|
import type { NavigationProp } from './types';
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
key?: string;
|
key?: string;
|
||||||
navigation?: NavigationProp<ParamListBase, string, NavigationState, object>;
|
navigation?: NavigationProp<ParamListBase>;
|
||||||
options?: object | undefined;
|
options?: object | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,7 @@ import type { RouteProp } from './types';
|
|||||||
*
|
*
|
||||||
* @returns Route prop of the parent screen.
|
* @returns Route prop of the parent screen.
|
||||||
*/
|
*/
|
||||||
export default function useRoute<
|
export default function useRoute<T extends RouteProp<ParamListBase>>(): T {
|
||||||
T extends RouteProp<ParamListBase, string>
|
|
||||||
>(): T {
|
|
||||||
const route = React.useContext(NavigationRouteContext);
|
const route = React.useContext(NavigationRouteContext);
|
||||||
|
|
||||||
if (route === undefined) {
|
if (route === undefined) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type {
|
|||||||
} from '@react-navigation/routers';
|
} from '@react-navigation/routers';
|
||||||
import type { RouteProp } from './types';
|
import type { RouteProp } from './types';
|
||||||
|
|
||||||
type RouteCache = Map<Route<string>, RouteProp<ParamListBase, string>>;
|
type RouteCache = Map<Route<string>, RouteProp<ParamListBase>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utilites such as `getFocusedRouteNameFromRoute` need to access state.
|
* Utilites such as `getFocusedRouteNameFromRoute` need to access state.
|
||||||
|
|||||||
@@ -3,6 +3,25 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
# [6.0.0-next.4](https://github.com/react-navigation/react-navigation/compare/@react-navigation/devtools@6.0.0-next.3...@react-navigation/devtools@6.0.0-next.4) (2021-05-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/devtools
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [6.0.0-next.3](https://github.com/react-navigation/react-navigation/compare/@react-navigation/devtools@6.0.0-next.2...@react-navigation/devtools@6.0.0-next.3) (2021-05-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add helper and hook for container ref ([0ecd112](https://github.com/react-navigation/react-navigation/commit/0ecd112ec9786a26261ada3d33ef44dc1ec84da0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [6.0.0-next.2](https://github.com/react-navigation/react-navigation/compare/@react-navigation/devtools@6.0.0-next.1...@react-navigation/devtools@6.0.0-next.2) (2021-04-08)
|
# [6.0.0-next.2](https://github.com/react-navigation/react-navigation/compare/@react-navigation/devtools@6.0.0-next.1...@react-navigation/devtools@6.0.0-next.2) (2021-04-08)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/devtools
|
**Note:** Version bump only for package @react-navigation/devtools
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/devtools",
|
"name": "@react-navigation/devtools",
|
||||||
"description": "Developer tools for React Navigation",
|
"description": "Developer tools for React Navigation",
|
||||||
"version": "6.0.0-next.2",
|
"version": "6.0.0-next.4",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react",
|
"react",
|
||||||
"react-native",
|
"react-native",
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/core": "^6.0.0-next.2",
|
"@react-navigation/core": "^6.0.0-next.4",
|
||||||
"deep-equal": "^2.0.5"
|
"deep-equal": "^2.0.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type {
|
|||||||
NavigationContainerRef,
|
NavigationContainerRef,
|
||||||
NavigationState,
|
NavigationState,
|
||||||
NavigationAction,
|
NavigationAction,
|
||||||
|
ParamListBase,
|
||||||
} from '@react-navigation/core';
|
} from '@react-navigation/core';
|
||||||
import deepEqual from 'deep-equal';
|
import deepEqual from 'deep-equal';
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ type DevToolsExtension = {
|
|||||||
declare const __REDUX_DEVTOOLS_EXTENSION__: DevToolsExtension | undefined;
|
declare const __REDUX_DEVTOOLS_EXTENSION__: DevToolsExtension | undefined;
|
||||||
|
|
||||||
export default function useReduxDevToolsExtension(
|
export default function useReduxDevToolsExtension(
|
||||||
ref: React.RefObject<NavigationContainerRef>
|
ref: React.RefObject<NavigationContainerRef<ParamListBase>>
|
||||||
) {
|
) {
|
||||||
const devToolsRef = React.useRef<DevToolsConnection>();
|
const devToolsRef = React.useRef<DevToolsConnection>();
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,26 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
# [6.0.0-next.6](https://github.com/react-navigation/react-navigation/compare/@react-navigation/drawer@6.0.0-next.5...@react-navigation/drawer@6.0.0-next.6) (2021-05-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* enable screens only on supported platforms ([#9494](https://github.com/react-navigation/react-navigation/issues/9494)) ([8da4c58](https://github.com/react-navigation/react-navigation/commit/8da4c58065607d44e9dc1ad8943e09537598dcd7))
|
||||||
|
* make sure disabling react-native-screens works ([a369ba3](https://github.com/react-navigation/react-navigation/commit/a369ba36451ddc2bb5b247e61b725bce1e3fb5e5))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [6.0.0-next.5](https://github.com/react-navigation/react-navigation/compare/@react-navigation/drawer@6.0.0-next.4...@react-navigation/drawer@6.0.0-next.5) (2021-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [6.0.0-next.4](https://github.com/react-navigation/react-navigation/compare/@react-navigation/drawer@6.0.0-next.3...@react-navigation/drawer@6.0.0-next.4) (2021-04-08)
|
# [6.0.0-next.4](https://github.com/react-navigation/react-navigation/compare/@react-navigation/drawer@6.0.0-next.3...@react-navigation/drawer@6.0.0-next.4) (2021-04-08)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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": "6.0.0-next.4",
|
"version": "6.0.0-next.6",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -41,15 +41,15 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/elements": "^1.0.0-next.4",
|
"@react-navigation/elements": "^1.0.0-next.6",
|
||||||
"color": "^3.1.3",
|
"color": "^3.1.3",
|
||||||
"warn-once": "^0.0.1"
|
"warn-once": "^0.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-navigation/native": "^6.0.0-next.2",
|
"@react-navigation/native": "^6.0.0-next.4",
|
||||||
"@testing-library/react-native": "^7.2.0",
|
"@testing-library/react-native": "^7.2.0",
|
||||||
"@types/react": "^16.9.53",
|
"@types/react": "^16.9.53",
|
||||||
"@types/react-native": "~0.63.51",
|
"@types/react-native": "~0.64.4",
|
||||||
"del-cli": "^3.0.1",
|
"del-cli": "^3.0.1",
|
||||||
"react": "~16.13.1",
|
"react": "~16.13.1",
|
||||||
"react-native": "~0.63.4",
|
"react-native": "~0.63.4",
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ export type DrawerHeaderProps = {
|
|||||||
/**
|
/**
|
||||||
* Route object for the current screen.
|
* Route object for the current screen.
|
||||||
*/
|
*/
|
||||||
route: RouteProp<ParamListBase, string>;
|
route: RouteProp<ParamListBase>;
|
||||||
/**
|
/**
|
||||||
* Navigation prop for the header.
|
* Navigation prop for the header.
|
||||||
*/
|
*/
|
||||||
@@ -252,7 +252,7 @@ export type DrawerNavigationHelpers = NavigationHelpers<
|
|||||||
|
|
||||||
export type DrawerNavigationProp<
|
export type DrawerNavigationProp<
|
||||||
ParamList extends ParamListBase,
|
ParamList extends ParamListBase,
|
||||||
RouteName extends keyof ParamList = string
|
RouteName extends keyof ParamList = keyof ParamList
|
||||||
> = NavigationProp<
|
> = NavigationProp<
|
||||||
ParamList,
|
ParamList,
|
||||||
RouteName,
|
RouteName,
|
||||||
@@ -264,7 +264,7 @@ export type DrawerNavigationProp<
|
|||||||
|
|
||||||
export type DrawerScreenProps<
|
export type DrawerScreenProps<
|
||||||
ParamList extends ParamListBase,
|
ParamList extends ParamListBase,
|
||||||
RouteName extends keyof ParamList = string
|
RouteName extends keyof ParamList = keyof ParamList
|
||||||
> = {
|
> = {
|
||||||
navigation: DrawerNavigationProp<ParamList, RouteName>;
|
navigation: DrawerNavigationProp<ParamList, RouteName>;
|
||||||
route: RouteProp<ParamList, RouteName>;
|
route: RouteProp<ParamList, RouteName>;
|
||||||
@@ -273,7 +273,7 @@ export type DrawerScreenProps<
|
|||||||
export type DrawerDescriptor = Descriptor<
|
export type DrawerDescriptor = Descriptor<
|
||||||
DrawerNavigationOptions,
|
DrawerNavigationOptions,
|
||||||
DrawerNavigationProp<ParamListBase>,
|
DrawerNavigationProp<ParamListBase>,
|
||||||
RouteProp<ParamListBase, string>
|
RouteProp<ParamListBase>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type DrawerDescriptorMap = Record<string, DrawerDescriptor>;
|
export type DrawerDescriptorMap = Record<string, DrawerDescriptor>;
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import {
|
|||||||
Platform,
|
Platform,
|
||||||
BackHandler,
|
BackHandler,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { ScreenContainer } from 'react-native-screens';
|
|
||||||
import { useSafeAreaFrame } from 'react-native-safe-area-context';
|
import { useSafeAreaFrame } from 'react-native-safe-area-context';
|
||||||
import Animated from 'react-native-reanimated';
|
import Animated from 'react-native-reanimated';
|
||||||
import {
|
import {
|
||||||
@@ -22,9 +21,8 @@ import {
|
|||||||
SafeAreaProviderCompat,
|
SafeAreaProviderCompat,
|
||||||
getHeaderTitle,
|
getHeaderTitle,
|
||||||
} from '@react-navigation/elements';
|
} from '@react-navigation/elements';
|
||||||
|
import { MaybeScreenContainer, MaybeScreen } from './ScreenFallback';
|
||||||
import { GestureHandlerRootView } from './GestureHandler';
|
import { GestureHandlerRootView } from './GestureHandler';
|
||||||
import ScreenFallback from './ScreenFallback';
|
|
||||||
import DrawerToggleButton from './DrawerToggleButton';
|
import DrawerToggleButton from './DrawerToggleButton';
|
||||||
import DrawerContent from './DrawerContent';
|
import DrawerContent from './DrawerContent';
|
||||||
import DrawerStatusContext from '../utils/DrawerStatusContext';
|
import DrawerStatusContext from '../utils/DrawerStatusContext';
|
||||||
@@ -76,7 +74,9 @@ function DrawerViewBase({
|
|||||||
drawerContent = (props: DrawerContentComponentProps) => (
|
drawerContent = (props: DrawerContentComponentProps) => (
|
||||||
<DrawerContent {...props} />
|
<DrawerContent {...props} />
|
||||||
),
|
),
|
||||||
detachInactiveScreens = true,
|
detachInactiveScreens = Platform.OS === 'web' ||
|
||||||
|
Platform.OS === 'android' ||
|
||||||
|
Platform.OS === 'ios',
|
||||||
// Running in chrome debugger
|
// Running in chrome debugger
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
useLegacyImplementation = !global.nativeCallSyncHook ||
|
useLegacyImplementation = !global.nativeCallSyncHook ||
|
||||||
@@ -189,8 +189,10 @@ function DrawerViewBase({
|
|||||||
|
|
||||||
const renderSceneContent = () => {
|
const renderSceneContent = () => {
|
||||||
return (
|
return (
|
||||||
// @ts-ignore
|
<MaybeScreenContainer
|
||||||
<ScreenContainer enabled={detachInactiveScreens} style={styles.content}>
|
enabled={detachInactiveScreens}
|
||||||
|
style={styles.content}
|
||||||
|
>
|
||||||
{state.routes.map((route, index) => {
|
{state.routes.map((route, index) => {
|
||||||
const descriptor = descriptors[route.key];
|
const descriptor = descriptors[route.key];
|
||||||
const { lazy = true, unmountOnBlur } = descriptor.options;
|
const { lazy = true, unmountOnBlur } = descriptor.options;
|
||||||
@@ -221,7 +223,7 @@ function DrawerViewBase({
|
|||||||
} = descriptor.options;
|
} = descriptor.options;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScreenFallback
|
<MaybeScreen
|
||||||
key={route.key}
|
key={route.key}
|
||||||
style={[StyleSheet.absoluteFill, { opacity: isFocused ? 1 : 0 }]}
|
style={[StyleSheet.absoluteFill, { opacity: isFocused ? 1 : 0 }]}
|
||||||
visible={isFocused}
|
visible={isFocused}
|
||||||
@@ -243,10 +245,10 @@ function DrawerViewBase({
|
|||||||
>
|
>
|
||||||
{descriptor.render()}
|
{descriptor.render()}
|
||||||
</Screen>
|
</Screen>
|
||||||
</ScreenFallback>
|
</MaybeScreen>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ScreenContainer>
|
</MaybeScreenContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Platform, StyleProp, ViewStyle } from 'react-native';
|
import { StyleProp, View, ViewProps, ViewStyle } from 'react-native';
|
||||||
import {
|
|
||||||
Screen,
|
|
||||||
screensEnabled,
|
|
||||||
// @ts-ignore
|
|
||||||
shouldUseActivityState,
|
|
||||||
} from 'react-native-screens';
|
|
||||||
import { ResourceSavingView } from '@react-navigation/elements';
|
import { ResourceSavingView } from '@react-navigation/elements';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -15,22 +9,35 @@ type Props = {
|
|||||||
style?: StyleProp<ViewStyle>;
|
style?: StyleProp<ViewStyle>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function ScreenFallback({ visible, children, ...rest }: Props) {
|
let Screens: typeof import('react-native-screens') | undefined;
|
||||||
// react-native-screens is buggy on web
|
|
||||||
if (screensEnabled?.() && Platform.OS !== 'web') {
|
try {
|
||||||
if (shouldUseActivityState) {
|
Screens = require('react-native-screens');
|
||||||
return (
|
} catch (e) {
|
||||||
<Screen activityState={visible ? 2 : 0} {...rest}>
|
// Ignore
|
||||||
{children}
|
}
|
||||||
</Screen>
|
|
||||||
);
|
export const MaybeScreenContainer = ({
|
||||||
} else {
|
enabled,
|
||||||
return (
|
...rest
|
||||||
<Screen active={visible ? 1 : 0} {...rest}>
|
}: ViewProps & {
|
||||||
{children}
|
enabled: boolean;
|
||||||
</Screen>
|
children: React.ReactNode;
|
||||||
);
|
}) => {
|
||||||
}
|
if (Screens?.screensEnabled?.()) {
|
||||||
|
return <Screens.ScreenContainer enabled={enabled} {...rest} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <View {...rest} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function MaybeScreen({ visible, children, ...rest }: Props) {
|
||||||
|
if (Screens?.screensEnabled?.()) {
|
||||||
|
return (
|
||||||
|
<Screens.Screen activityState={visible ? 2 : 0} {...rest}>
|
||||||
|
{children}
|
||||||
|
</Screens.Screen>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,6 +3,25 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
# [1.0.0-next.6](https://github.com/react-navigation/react-navigation/compare/@react-navigation/elements@1.0.0-next.5...@react-navigation/elements@1.0.0-next.6) (2021-05-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* animate pressable opacity ([459fd27](https://github.com/react-navigation/react-navigation/commit/459fd270503075343b71ad446efdc2517eedcf21))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [1.0.0-next.5](https://github.com/react-navigation/react-navigation/compare/@react-navigation/elements@1.0.0-next.4...@react-navigation/elements@1.0.0-next.5) (2021-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/elements
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [1.0.0-next.4](https://github.com/react-navigation/react-navigation/compare/@react-navigation/elements@1.0.0-next.3...@react-navigation/elements@1.0.0-next.4) (2021-04-08)
|
# [1.0.0-next.4](https://github.com/react-navigation/react-navigation/compare/@react-navigation/elements@1.0.0-next.3...@react-navigation/elements@1.0.0-next.4) (2021-04-08)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/elements
|
**Note:** Version bump only for package @react-navigation/elements
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@react-navigation/elements",
|
"name": "@react-navigation/elements",
|
||||||
"description": "UI Components for React Navigation",
|
"description": "UI Components for React Navigation",
|
||||||
"version": "1.0.0-next.4",
|
"version": "1.0.0-next.6",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native",
|
"react-native",
|
||||||
"react-navigation",
|
"react-navigation",
|
||||||
@@ -38,10 +38,10 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-native-masked-view/masked-view": "^0.2.3",
|
"@react-native-masked-view/masked-view": "^0.2.3",
|
||||||
"@react-navigation/native": "^6.0.0-next.2",
|
"@react-navigation/native": "^6.0.0-next.4",
|
||||||
"@testing-library/react-native": "^7.2.0",
|
"@testing-library/react-native": "^7.2.0",
|
||||||
"@types/react": "^16.9.53",
|
"@types/react": "^16.9.53",
|
||||||
"@types/react-native": "~0.63.51",
|
"@types/react-native": "~0.64.4",
|
||||||
"del-cli": "^3.0.1",
|
"del-cli": "^3.0.1",
|
||||||
"react": "~16.13.1",
|
"react": "~16.13.1",
|
||||||
"react-native": "~0.63.4",
|
"react-native": "~0.63.4",
|
||||||
|
|||||||
@@ -1,13 +1,25 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Platform, Pressable, PressableProps } from 'react-native';
|
import {
|
||||||
|
Animated,
|
||||||
|
Easing,
|
||||||
|
GestureResponderEvent,
|
||||||
|
Platform,
|
||||||
|
Pressable,
|
||||||
|
PressableProps,
|
||||||
|
StyleProp,
|
||||||
|
ViewStyle,
|
||||||
|
} from 'react-native';
|
||||||
import { useTheme } from '@react-navigation/native';
|
import { useTheme } from '@react-navigation/native';
|
||||||
|
|
||||||
export type Props = PressableProps & {
|
export type Props = Omit<PressableProps, 'style'> & {
|
||||||
pressColor?: string;
|
pressColor?: string;
|
||||||
pressOpacity?: number;
|
pressOpacity?: number;
|
||||||
|
style?: Animated.WithAnimatedValue<StyleProp<ViewStyle>>;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
|
||||||
|
|
||||||
const ANDROID_VERSION_LOLLIPOP = 21;
|
const ANDROID_VERSION_LOLLIPOP = 21;
|
||||||
const ANDROID_SUPPORTS_RIPPLE =
|
const ANDROID_SUPPORTS_RIPPLE =
|
||||||
Platform.OS === 'android' && Platform.Version >= ANDROID_VERSION_LOLLIPOP;
|
Platform.OS === 'android' && Platform.Version >= ANDROID_VERSION_LOLLIPOP;
|
||||||
@@ -16,16 +28,44 @@ const ANDROID_SUPPORTS_RIPPLE =
|
|||||||
* PlatformPressable provides an abstraction on top of Pressable to handle platform differences.
|
* PlatformPressable provides an abstraction on top of Pressable to handle platform differences.
|
||||||
*/
|
*/
|
||||||
export default function PlatformPressable({
|
export default function PlatformPressable({
|
||||||
|
onPressIn,
|
||||||
|
onPressOut,
|
||||||
android_ripple,
|
android_ripple,
|
||||||
pressColor,
|
pressColor,
|
||||||
pressOpacity,
|
pressOpacity = 0.3,
|
||||||
style,
|
style,
|
||||||
...rest
|
...rest
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const { dark } = useTheme();
|
const { dark } = useTheme();
|
||||||
|
const [opacity] = React.useState(() => new Animated.Value(1));
|
||||||
|
|
||||||
|
const animateTo = (toValue: number, duration: number) => {
|
||||||
|
if (ANDROID_SUPPORTS_RIPPLE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Animated.timing(opacity, {
|
||||||
|
toValue,
|
||||||
|
duration,
|
||||||
|
easing: Easing.inOut(Easing.quad),
|
||||||
|
useNativeDriver: true,
|
||||||
|
}).start();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePressIn = (e: GestureResponderEvent) => {
|
||||||
|
animateTo(pressOpacity, 150);
|
||||||
|
onPressIn?.(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePressOut = (e: GestureResponderEvent) => {
|
||||||
|
animateTo(1, 200);
|
||||||
|
onPressOut?.(e);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Pressable
|
<AnimatedPressable
|
||||||
|
onPressIn={handlePressIn}
|
||||||
|
onPressOut={handlePressOut}
|
||||||
android_ripple={
|
android_ripple={
|
||||||
ANDROID_SUPPORTS_RIPPLE
|
ANDROID_SUPPORTS_RIPPLE
|
||||||
? {
|
? {
|
||||||
@@ -39,10 +79,7 @@ export default function PlatformPressable({
|
|||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
style={({ pressed }) => [
|
style={[{ opacity: !ANDROID_SUPPORTS_RIPPLE ? opacity : 1 }, style]}
|
||||||
{ opacity: pressed && !ANDROID_SUPPORTS_RIPPLE ? pressOpacity : 1 },
|
|
||||||
typeof style === 'function' ? style({ pressed }) : style,
|
|
||||||
]}
|
|
||||||
{...rest}
|
{...rest}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import getDefaultHeaderHeight from './Header/getDefaultHeaderHeight';
|
|||||||
type Props = {
|
type Props = {
|
||||||
focused: boolean;
|
focused: boolean;
|
||||||
navigation: NavigationProp<ParamListBase>;
|
navigation: NavigationProp<ParamListBase>;
|
||||||
route: RouteProp<ParamListBase, string>;
|
route: RouteProp<ParamListBase>;
|
||||||
header: React.ReactNode;
|
header: React.ReactNode;
|
||||||
headerShown?: boolean;
|
headerShown?: boolean;
|
||||||
headerStatusBarHeight?: number;
|
headerStatusBarHeight?: number;
|
||||||
|
|||||||
@@ -3,6 +3,22 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
# [6.0.0-next.4](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-bottom-tabs@6.0.0-next.3...@react-navigation/material-bottom-tabs@6.0.0-next.4) (2021-05-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [6.0.0-next.3](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-bottom-tabs@6.0.0-next.2...@react-navigation/material-bottom-tabs@6.0.0-next.3) (2021-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [6.0.0-next.2](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-bottom-tabs@6.0.0-next.1...@react-navigation/material-bottom-tabs@6.0.0-next.2) (2021-04-08)
|
# [6.0.0-next.2](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-bottom-tabs@6.0.0-next.1...@react-navigation/material-bottom-tabs@6.0.0-next.2) (2021-04-08)
|
||||||
|
|
||||||
**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": "6.0.0-next.2",
|
"version": "6.0.0-next.4",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -41,10 +41,10 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-navigation/native": "^6.0.0-next.2",
|
"@react-navigation/native": "^6.0.0-next.4",
|
||||||
"@testing-library/react-native": "^7.2.0",
|
"@testing-library/react-native": "^7.2.0",
|
||||||
"@types/react": "^16.9.53",
|
"@types/react": "^16.9.53",
|
||||||
"@types/react-native": "~0.63.51",
|
"@types/react-native": "~0.64.4",
|
||||||
"@types/react-native-vector-icons": "^6.4.6",
|
"@types/react-native-vector-icons": "^6.4.6",
|
||||||
"del-cli": "^3.0.1",
|
"del-cli": "^3.0.1",
|
||||||
"react": "~16.13.1",
|
"react": "~16.13.1",
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export type MaterialBottomTabNavigationHelpers = NavigationHelpers<
|
|||||||
|
|
||||||
export type MaterialBottomTabNavigationProp<
|
export type MaterialBottomTabNavigationProp<
|
||||||
ParamList extends ParamListBase,
|
ParamList extends ParamListBase,
|
||||||
RouteName extends keyof ParamList = string
|
RouteName extends keyof ParamList = keyof ParamList
|
||||||
> = NavigationProp<
|
> = NavigationProp<
|
||||||
ParamList,
|
ParamList,
|
||||||
RouteName,
|
RouteName,
|
||||||
@@ -36,7 +36,7 @@ export type MaterialBottomTabNavigationProp<
|
|||||||
|
|
||||||
export type MaterialBottomTabScreenProps<
|
export type MaterialBottomTabScreenProps<
|
||||||
ParamList extends ParamListBase,
|
ParamList extends ParamListBase,
|
||||||
RouteName extends keyof ParamList = string
|
RouteName extends keyof ParamList = keyof ParamList
|
||||||
> = {
|
> = {
|
||||||
navigation: MaterialBottomTabNavigationProp<ParamList, RouteName>;
|
navigation: MaterialBottomTabNavigationProp<ParamList, RouteName>;
|
||||||
route: RouteProp<ParamList, RouteName>;
|
route: RouteProp<ParamList, RouteName>;
|
||||||
@@ -85,7 +85,7 @@ export type MaterialBottomTabNavigationOptions = {
|
|||||||
export type MaterialBottomTabDescriptor = Descriptor<
|
export type MaterialBottomTabDescriptor = Descriptor<
|
||||||
MaterialBottomTabNavigationOptions,
|
MaterialBottomTabNavigationOptions,
|
||||||
MaterialBottomTabNavigationProp<ParamListBase>,
|
MaterialBottomTabNavigationProp<ParamListBase>,
|
||||||
RouteProp<ParamListBase, string>
|
RouteProp<ParamListBase>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type MaterialBottomTabDescriptorMap = Record<
|
export type MaterialBottomTabDescriptorMap = Record<
|
||||||
|
|||||||
@@ -3,6 +3,22 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
# [6.0.0-next.5](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-top-tabs@6.0.0-next.4...@react-navigation/material-top-tabs@6.0.0-next.5) (2021-05-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [6.0.0-next.4](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-top-tabs@6.0.0-next.3...@react-navigation/material-top-tabs@6.0.0-next.4) (2021-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [6.0.0-next.3](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-top-tabs@6.0.0-next.2...@react-navigation/material-top-tabs@6.0.0-next.3) (2021-04-08)
|
# [6.0.0-next.3](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-top-tabs@6.0.0-next.2...@react-navigation/material-top-tabs@6.0.0-next.3) (2021-04-08)
|
||||||
|
|
||||||
**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": "6.0.0-next.3",
|
"version": "6.0.0-next.5",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -45,10 +45,10 @@
|
|||||||
"warn-once": "^0.0.1"
|
"warn-once": "^0.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-navigation/native": "^6.0.0-next.2",
|
"@react-navigation/native": "^6.0.0-next.4",
|
||||||
"@testing-library/react-native": "^7.2.0",
|
"@testing-library/react-native": "^7.2.0",
|
||||||
"@types/react": "^16.9.53",
|
"@types/react": "^16.9.53",
|
||||||
"@types/react-native": "~0.63.51",
|
"@types/react-native": "~0.64.4",
|
||||||
"del-cli": "^3.0.1",
|
"del-cli": "^3.0.1",
|
||||||
"react": "~16.13.1",
|
"react": "~16.13.1",
|
||||||
"react-native": "~0.63.4",
|
"react-native": "~0.63.4",
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export type MaterialTopTabNavigationHelpers = NavigationHelpers<
|
|||||||
|
|
||||||
export type MaterialTopTabNavigationProp<
|
export type MaterialTopTabNavigationProp<
|
||||||
ParamList extends ParamListBase,
|
ParamList extends ParamListBase,
|
||||||
RouteName extends keyof ParamList = string
|
RouteName extends keyof ParamList = keyof ParamList
|
||||||
> = NavigationProp<
|
> = NavigationProp<
|
||||||
ParamList,
|
ParamList,
|
||||||
RouteName,
|
RouteName,
|
||||||
@@ -50,7 +50,7 @@ export type MaterialTopTabNavigationProp<
|
|||||||
|
|
||||||
export type MaterialTopTabScreenProps<
|
export type MaterialTopTabScreenProps<
|
||||||
ParamList extends ParamListBase,
|
ParamList extends ParamListBase,
|
||||||
RouteName extends keyof ParamList = string
|
RouteName extends keyof ParamList = keyof ParamList
|
||||||
> = {
|
> = {
|
||||||
navigation: MaterialTopTabNavigationProp<ParamList, RouteName>;
|
navigation: MaterialTopTabNavigationProp<ParamList, RouteName>;
|
||||||
route: RouteProp<ParamList, RouteName>;
|
route: RouteProp<ParamList, RouteName>;
|
||||||
@@ -189,7 +189,7 @@ export type MaterialTopTabNavigationOptions = {
|
|||||||
export type MaterialTopTabDescriptor = Descriptor<
|
export type MaterialTopTabDescriptor = Descriptor<
|
||||||
MaterialTopTabNavigationOptions,
|
MaterialTopTabNavigationOptions,
|
||||||
MaterialTopTabNavigationProp<ParamListBase>,
|
MaterialTopTabNavigationProp<ParamListBase>,
|
||||||
RouteProp<ParamListBase, string>
|
RouteProp<ParamListBase>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type MaterialTopTabDescriptorMap = Record<
|
export type MaterialTopTabDescriptorMap = Record<
|
||||||
|
|||||||
@@ -3,6 +3,29 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
# [6.0.0-next.4](https://github.com/react-navigation/react-navigation/compare/@react-navigation/native@6.0.0-next.3...@react-navigation/native@6.0.0-next.4) (2021-05-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add ability to specify root param list ([b28bfdd](https://github.com/react-navigation/react-navigation/commit/b28bfddc17cbf3996fac04a34b2a7085ecf88be5))
|
||||||
|
* support navigate-like object in Link ([1478659](https://github.com/react-navigation/react-navigation/commit/14786594c004d8176570f1a4ab013b57b3180665))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [6.0.0-next.3](https://github.com/react-navigation/react-navigation/compare/@react-navigation/native@6.0.0-next.2...@react-navigation/native@6.0.0-next.3) (2021-05-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add helper and hook for container ref ([0ecd112](https://github.com/react-navigation/react-navigation/commit/0ecd112ec9786a26261ada3d33ef44dc1ec84da0))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [6.0.0-next.2](https://github.com/react-navigation/react-navigation/compare/@react-navigation/native@6.0.0-next.1...@react-navigation/native@6.0.0-next.2) (2021-04-08)
|
# [6.0.0-next.2](https://github.com/react-navigation/react-navigation/compare/@react-navigation/native@6.0.0-next.1...@react-navigation/native@6.0.0-next.2) (2021-04-08)
|
||||||
|
|
||||||
**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": "6.0.0-next.2",
|
"version": "6.0.0-next.4",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native",
|
"react-native",
|
||||||
"react-navigation",
|
"react-navigation",
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/core": "^6.0.0-next.2",
|
"@react-navigation/core": "^6.0.0-next.4",
|
||||||
"escape-string-regexp": "^4.0.0",
|
"escape-string-regexp": "^4.0.0",
|
||||||
"nanoid": "^3.1.22"
|
"nanoid": "^3.1.22"
|
||||||
},
|
},
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
"@testing-library/react-native": "^7.2.0",
|
"@testing-library/react-native": "^7.2.0",
|
||||||
"@types/react": "^16.9.53",
|
"@types/react": "^16.9.53",
|
||||||
"@types/react-dom": "^16.9.8",
|
"@types/react-dom": "^16.9.8",
|
||||||
"@types/react-native": "~0.63.51",
|
"@types/react-native": "~0.64.4",
|
||||||
"del-cli": "^3.0.1",
|
"del-cli": "^3.0.1",
|
||||||
"react": "~16.13.1",
|
"react": "~16.13.1",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ import * as React from 'react';
|
|||||||
import { Text, TextProps, GestureResponderEvent, Platform } from 'react-native';
|
import { Text, TextProps, GestureResponderEvent, Platform } from 'react-native';
|
||||||
import type { NavigationAction } from '@react-navigation/core';
|
import type { NavigationAction } from '@react-navigation/core';
|
||||||
import useLinkProps from './useLinkProps';
|
import useLinkProps from './useLinkProps';
|
||||||
|
import type { To } from './useLinkTo';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
to: string;
|
to: To;
|
||||||
action?: NavigationAction;
|
action?: NavigationAction;
|
||||||
target?: string;
|
target?: string;
|
||||||
onPress?: (
|
onPress?: (
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import type { ParamListBase } from '@react-navigation/core';
|
||||||
import type { LinkingOptions } from './types';
|
import type { LinkingOptions } from './types';
|
||||||
|
|
||||||
const LinkingContext = React.createContext<{
|
const LinkingContext = React.createContext<{
|
||||||
options: LinkingOptions | undefined;
|
options: LinkingOptions<ParamListBase> | undefined;
|
||||||
}>({ options: undefined });
|
}>({ options: undefined });
|
||||||
|
|
||||||
LinkingContext.displayName = 'LinkingContext';
|
LinkingContext.displayName = 'LinkingContext';
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
BaseNavigationContainer,
|
BaseNavigationContainer,
|
||||||
NavigationContainerProps,
|
NavigationContainerProps,
|
||||||
NavigationContainerRef,
|
NavigationContainerRef,
|
||||||
|
ParamListBase,
|
||||||
} from '@react-navigation/core';
|
} from '@react-navigation/core';
|
||||||
import ThemeProvider from './theming/ThemeProvider';
|
import ThemeProvider from './theming/ThemeProvider';
|
||||||
import DefaultTheme from './theming/DefaultTheme';
|
import DefaultTheme from './theming/DefaultTheme';
|
||||||
@@ -13,9 +14,9 @@ import useDocumentTitle from './useDocumentTitle';
|
|||||||
import useBackButton from './useBackButton';
|
import useBackButton from './useBackButton';
|
||||||
import type { Theme, LinkingOptions, DocumentTitleOptions } from './types';
|
import type { Theme, LinkingOptions, DocumentTitleOptions } from './types';
|
||||||
|
|
||||||
type Props = NavigationContainerProps & {
|
type Props<ParamList extends {}> = NavigationContainerProps & {
|
||||||
theme?: Theme;
|
theme?: Theme;
|
||||||
linking?: LinkingOptions;
|
linking?: LinkingOptions<ParamList>;
|
||||||
fallback?: React.ReactNode;
|
fallback?: React.ReactNode;
|
||||||
documentTitle?: DocumentTitleOptions;
|
documentTitle?: DocumentTitleOptions;
|
||||||
onReady?: () => void;
|
onReady?: () => void;
|
||||||
@@ -35,7 +36,7 @@ type Props = NavigationContainerProps & {
|
|||||||
* @param props.children Child elements to render the content.
|
* @param props.children Child elements to render the content.
|
||||||
* @param props.ref Ref object which refers to the navigation object containing helper methods.
|
* @param props.ref Ref object which refers to the navigation object containing helper methods.
|
||||||
*/
|
*/
|
||||||
const NavigationContainer = React.forwardRef(function NavigationContainer(
|
function NavigationContainerInner(
|
||||||
{
|
{
|
||||||
theme = DefaultTheme,
|
theme = DefaultTheme,
|
||||||
linking,
|
linking,
|
||||||
@@ -43,12 +44,14 @@ const NavigationContainer = React.forwardRef(function NavigationContainer(
|
|||||||
documentTitle,
|
documentTitle,
|
||||||
onReady,
|
onReady,
|
||||||
...rest
|
...rest
|
||||||
}: Props,
|
}: Props<ParamListBase>,
|
||||||
ref?: React.Ref<NavigationContainerRef | null>
|
ref?: React.Ref<NavigationContainerRef<ParamListBase> | null>
|
||||||
) {
|
) {
|
||||||
const isLinkingEnabled = linking ? linking.enabled !== false : false;
|
const isLinkingEnabled = linking ? linking.enabled !== false : false;
|
||||||
|
|
||||||
const refContainer = React.useRef<NavigationContainerRef>(null);
|
const refContainer = React.useRef<NavigationContainerRef<ParamListBase>>(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
useBackButton(refContainer);
|
useBackButton(refContainer);
|
||||||
useDocumentTitle(refContainer, documentTitle);
|
useDocumentTitle(refContainer, documentTitle);
|
||||||
@@ -98,6 +101,14 @@ const NavigationContainer = React.forwardRef(function NavigationContainer(
|
|||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</LinkingContext.Provider>
|
</LinkingContext.Provider>
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
const NavigationContainer = React.forwardRef(NavigationContainerInner) as <
|
||||||
|
RootParamList extends {} = ReactNavigation.RootParamList
|
||||||
|
>(
|
||||||
|
props: Props<RootParamList> & {
|
||||||
|
ref?: React.Ref<NavigationContainerRef<RootParamList>>;
|
||||||
|
}
|
||||||
|
) => React.ReactElement;
|
||||||
|
|
||||||
export default NavigationContainer;
|
export default NavigationContainer;
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import {
|
|||||||
StackRouter,
|
StackRouter,
|
||||||
TabRouter,
|
TabRouter,
|
||||||
NavigationHelpersContext,
|
NavigationHelpersContext,
|
||||||
NavigationContainerRef,
|
createNavigationContainerRef,
|
||||||
|
ParamListBase,
|
||||||
} from '@react-navigation/core';
|
} from '@react-navigation/core';
|
||||||
import { act, render } from '@testing-library/react-native';
|
import { act, render } from '@testing-library/react-native';
|
||||||
import NavigationContainer from '../NavigationContainer';
|
import NavigationContainer from '../NavigationContainer';
|
||||||
@@ -79,7 +80,7 @@ it('integrates with the history API', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigation = React.createRef<NavigationContainerRef>();
|
const navigation = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<NavigationContainer ref={navigation} linking={linking}>
|
<NavigationContainer ref={navigation} linking={linking}>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
StackRouter,
|
StackRouter,
|
||||||
TabRouter,
|
TabRouter,
|
||||||
NavigationHelpersContext,
|
NavigationHelpersContext,
|
||||||
|
NavigatorScreenParams,
|
||||||
} from '@react-navigation/core';
|
} from '@react-navigation/core';
|
||||||
import { renderToString } from 'react-dom/server';
|
import { renderToString } from 'react-dom/server';
|
||||||
import NavigationContainer from '../NavigationContainer';
|
import NavigationContainer from '../NavigationContainer';
|
||||||
@@ -36,24 +37,37 @@ it('renders correct state with location', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const Stack = createStackNavigator();
|
type StackAParamList = {
|
||||||
|
Home: NavigatorScreenParams<StackBParamList>;
|
||||||
|
Chat: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
type StackBParamList = {
|
||||||
|
Profile: undefined;
|
||||||
|
Settings: undefined;
|
||||||
|
Feed: undefined;
|
||||||
|
Updates: undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StackA = createStackNavigator<StackAParamList>();
|
||||||
|
const StackB = createStackNavigator<StackBParamList>();
|
||||||
|
|
||||||
const TestScreen = ({ route }: any): any =>
|
const TestScreen = ({ route }: any): any =>
|
||||||
`${route.name} ${JSON.stringify(route.params)}`;
|
`${route.name} ${JSON.stringify(route.params)}`;
|
||||||
|
|
||||||
const NestedStack = () => {
|
const NestedStack = () => {
|
||||||
return (
|
return (
|
||||||
<Stack.Navigator initialRouteName="Feed">
|
<StackB.Navigator initialRouteName="Feed">
|
||||||
<Stack.Screen name="Profile" component={TestScreen} />
|
<StackB.Screen name="Profile" component={TestScreen} />
|
||||||
<Stack.Screen name="Settings" component={TestScreen} />
|
<StackB.Screen name="Settings" component={TestScreen} />
|
||||||
<Stack.Screen name="Feed" component={TestScreen} />
|
<StackB.Screen name="Feed" component={TestScreen} />
|
||||||
<Stack.Screen name="Updates" component={TestScreen} />
|
<StackB.Screen name="Updates" component={TestScreen} />
|
||||||
</Stack.Navigator>
|
</StackB.Navigator>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const element = (
|
const element = (
|
||||||
<NavigationContainer
|
<NavigationContainer<StackAParamList>
|
||||||
linking={{
|
linking={{
|
||||||
prefixes: [],
|
prefixes: [],
|
||||||
config: {
|
config: {
|
||||||
@@ -73,10 +87,10 @@ it('renders correct state with location', () => {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Stack.Navigator>
|
<StackA.Navigator>
|
||||||
<Stack.Screen name="Home" component={NestedStack} />
|
<StackA.Screen name="Home" component={NestedStack} />
|
||||||
<Stack.Screen name="Chat" component={TestScreen} />
|
<StackA.Screen name="Chat" component={TestScreen} />
|
||||||
</Stack.Navigator>
|
</StackA.Navigator>
|
||||||
</NavigationContainer>
|
</NavigationContainer>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { render, RenderAPI } from '@testing-library/react-native';
|
import { render, RenderAPI } from '@testing-library/react-native';
|
||||||
import type { NavigationContainerRef } from '@react-navigation/core';
|
import {
|
||||||
|
createNavigationContainerRef,
|
||||||
|
ParamListBase,
|
||||||
|
} from '@react-navigation/core';
|
||||||
import useLinking from '../useLinking';
|
import useLinking from '../useLinking';
|
||||||
|
|
||||||
it('throws if multiple instances of useLinking are used', () => {
|
it('throws if multiple instances of useLinking are used', () => {
|
||||||
const ref = React.createRef<NavigationContainerRef>();
|
const ref = createNavigationContainerRef<ParamListBase>();
|
||||||
|
|
||||||
const options = { prefixes: [] };
|
const options = { prefixes: [] };
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export type Theme = {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LinkingOptions = {
|
export type LinkingOptions<ParamList extends {}> = {
|
||||||
/**
|
/**
|
||||||
* Whether deep link handling should be enabled.
|
* Whether deep link handling should be enabled.
|
||||||
* Defaults to true.
|
* Defaults to true.
|
||||||
@@ -53,7 +53,10 @@ export type LinkingOptions = {
|
|||||||
* }
|
* }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
config?: { initialRouteName?: string; screens: PathConfigMap };
|
config?: {
|
||||||
|
initialRouteName?: keyof ParamList;
|
||||||
|
screens: PathConfigMap<ParamList>;
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* Custom function to get the initial URL used for linking.
|
* Custom function to get the initial URL used for linking.
|
||||||
* Uses `Linking.getInitialURL()` by default.
|
* Uses `Linking.getInitialURL()` by default.
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { BackHandler } from 'react-native';
|
import { BackHandler } from 'react-native';
|
||||||
import type { NavigationContainerRef } from '@react-navigation/core';
|
import type {
|
||||||
|
NavigationContainerRef,
|
||||||
|
ParamListBase,
|
||||||
|
} from '@react-navigation/core';
|
||||||
|
|
||||||
export default function useBackButton(
|
export default function useBackButton(
|
||||||
ref: React.RefObject<NavigationContainerRef>
|
ref: React.RefObject<NavigationContainerRef<ParamListBase>>
|
||||||
) {
|
) {
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const subscription = BackHandler.addEventListener(
|
const subscription = BackHandler.addEventListener(
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import type { NavigationContainerRef } from '@react-navigation/core';
|
import type {
|
||||||
|
NavigationContainerRef,
|
||||||
|
ParamListBase,
|
||||||
|
} from '@react-navigation/core';
|
||||||
import type { DocumentTitleOptions } from './types';
|
import type { DocumentTitleOptions } from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the document title for the active screen
|
* Set the document title for the active screen
|
||||||
*/
|
*/
|
||||||
export default function useDocumentTitle(
|
export default function useDocumentTitle(
|
||||||
ref: React.RefObject<NavigationContainerRef>,
|
ref: React.RefObject<NavigationContainerRef<ParamListBase>>,
|
||||||
{
|
{
|
||||||
enabled = true,
|
enabled = true,
|
||||||
formatter = (options, route) => options?.title ?? route?.name,
|
formatter = (options, route) => options?.title ?? route?.name,
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import {
|
|||||||
NavigationAction,
|
NavigationAction,
|
||||||
NavigationHelpersContext,
|
NavigationHelpersContext,
|
||||||
} from '@react-navigation/core';
|
} from '@react-navigation/core';
|
||||||
import useLinkTo from './useLinkTo';
|
import useLinkTo, { To } from './useLinkTo';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
to: string;
|
to: To;
|
||||||
action?: NavigationAction;
|
action?: NavigationAction;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -49,14 +49,6 @@ 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,37 +6,57 @@ import {
|
|||||||
} from '@react-navigation/core';
|
} from '@react-navigation/core';
|
||||||
import LinkingContext from './LinkingContext';
|
import LinkingContext from './LinkingContext';
|
||||||
|
|
||||||
|
export type To<
|
||||||
|
ParamList extends ReactNavigation.RootParamList = ReactNavigation.RootParamList,
|
||||||
|
RouteName extends keyof ParamList = keyof ParamList
|
||||||
|
> =
|
||||||
|
| string
|
||||||
|
| (undefined extends ParamList[RouteName]
|
||||||
|
? {
|
||||||
|
screen: RouteName;
|
||||||
|
params?: ParamList[RouteName];
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
screen: RouteName;
|
||||||
|
params: ParamList[RouteName];
|
||||||
|
});
|
||||||
|
|
||||||
export default function useLinkTo() {
|
export default function useLinkTo() {
|
||||||
const navigation = React.useContext(NavigationContext);
|
const navigation = React.useContext(NavigationContext);
|
||||||
const linking = React.useContext(LinkingContext);
|
const linking = React.useContext(LinkingContext);
|
||||||
|
|
||||||
const linkTo = React.useCallback(
|
const linkTo = React.useCallback(
|
||||||
(path: string) => {
|
(to: To) => {
|
||||||
if (!path.startsWith('/')) {
|
|
||||||
throw new Error(`The path must start with '/' (${path}).`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (navigation === undefined) {
|
if (navigation === undefined) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
"Couldn't find a navigation object. Is your component inside a screen in a navigator?"
|
"Couldn't find a navigation object. Is your component inside a screen in a navigator?"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let root = navigation;
|
||||||
|
let current;
|
||||||
|
|
||||||
|
// Traverse up to get the root navigation
|
||||||
|
while ((current = root.getParent())) {
|
||||||
|
root = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof to !== 'string') {
|
||||||
|
root.navigate(to.screen, to.params);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!to.startsWith('/')) {
|
||||||
|
throw new Error(`The path must start with '/' (${to}).`);
|
||||||
|
}
|
||||||
|
|
||||||
const { options } = linking;
|
const { options } = linking;
|
||||||
|
|
||||||
const state = options?.getStateFromPath
|
const state = options?.getStateFromPath
|
||||||
? options.getStateFromPath(path, options.config)
|
? options.getStateFromPath(to, options.config)
|
||||||
: getStateFromPath(path, options?.config);
|
: getStateFromPath(to, options?.config);
|
||||||
|
|
||||||
if (state) {
|
if (state) {
|
||||||
let root = navigation;
|
|
||||||
let current;
|
|
||||||
|
|
||||||
// Traverse up to get the root navigation
|
|
||||||
while ((current = root.getParent())) {
|
|
||||||
root = current;
|
|
||||||
}
|
|
||||||
|
|
||||||
const action = getActionFromState(state, options?.config);
|
const action = getActionFromState(state, options?.config);
|
||||||
|
|
||||||
if (action !== undefined) {
|
if (action !== undefined) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
getActionFromState,
|
getActionFromState,
|
||||||
getStateFromPath as getStateFromPathDefault,
|
getStateFromPath as getStateFromPathDefault,
|
||||||
NavigationContainerRef,
|
NavigationContainerRef,
|
||||||
|
ParamListBase,
|
||||||
} from '@react-navigation/core';
|
} from '@react-navigation/core';
|
||||||
import extractPathFromURL from './extractPathFromURL';
|
import extractPathFromURL from './extractPathFromURL';
|
||||||
import type { LinkingOptions } from './types';
|
import type { LinkingOptions } from './types';
|
||||||
@@ -13,7 +14,7 @@ type ResultState = ReturnType<typeof getStateFromPathDefault>;
|
|||||||
let isUsingLinking = false;
|
let isUsingLinking = false;
|
||||||
|
|
||||||
export default function useLinking(
|
export default function useLinking(
|
||||||
ref: React.RefObject<NavigationContainerRef>,
|
ref: React.RefObject<NavigationContainerRef<ParamListBase>>,
|
||||||
{
|
{
|
||||||
enabled = true,
|
enabled = true,
|
||||||
prefixes,
|
prefixes,
|
||||||
@@ -44,7 +45,7 @@ export default function useLinking(
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
getStateFromPath = getStateFromPathDefault,
|
getStateFromPath = getStateFromPathDefault,
|
||||||
}: LinkingOptions
|
}: LinkingOptions<ParamListBase>
|
||||||
) {
|
) {
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (enabled !== false && isUsingLinking) {
|
if (enabled !== false && isUsingLinking) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
NavigationState,
|
NavigationState,
|
||||||
getActionFromState,
|
getActionFromState,
|
||||||
findFocusedRoute,
|
findFocusedRoute,
|
||||||
|
ParamListBase,
|
||||||
} from '@react-navigation/core';
|
} from '@react-navigation/core';
|
||||||
import { nanoid } from 'nanoid/non-secure';
|
import { nanoid } from 'nanoid/non-secure';
|
||||||
import ServerContext from './ServerContext';
|
import ServerContext from './ServerContext';
|
||||||
@@ -288,13 +289,13 @@ const series = (cb: () => Promise<void>) => {
|
|||||||
let isUsingLinking = false;
|
let isUsingLinking = false;
|
||||||
|
|
||||||
export default function useLinking(
|
export default function useLinking(
|
||||||
ref: React.RefObject<NavigationContainerRef>,
|
ref: React.RefObject<NavigationContainerRef<ParamListBase>>,
|
||||||
{
|
{
|
||||||
enabled = true,
|
enabled = true,
|
||||||
config,
|
config,
|
||||||
getStateFromPath = getStateFromPathDefault,
|
getStateFromPath = getStateFromPathDefault,
|
||||||
getPathFromState = getPathFromStateDefault,
|
getPathFromState = getPathFromStateDefault,
|
||||||
}: LinkingOptions
|
}: LinkingOptions<ParamListBase>
|
||||||
) {
|
) {
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (enabled !== false && isUsingLinking) {
|
if (enabled !== false && isUsingLinking) {
|
||||||
|
|||||||
@@ -3,6 +3,42 @@
|
|||||||
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.
|
||||||
|
|
||||||
|
# [6.0.0-next.11](https://github.com/react-navigation/react-navigation/compare/@react-navigation/stack@6.0.0-next.10...@react-navigation/stack@6.0.0-next.11) (2021-05-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* enable screens only on supported platforms ([#9494](https://github.com/react-navigation/react-navigation/issues/9494)) ([8da4c58](https://github.com/react-navigation/react-navigation/commit/8da4c58065607d44e9dc1ad8943e09537598dcd7))
|
||||||
|
* make sure disabling react-native-screens works ([a369ba3](https://github.com/react-navigation/react-navigation/commit/a369ba36451ddc2bb5b247e61b725bce1e3fb5e5))
|
||||||
|
|
||||||
|
|
||||||
|
### Code Refactoring
|
||||||
|
|
||||||
|
* drop mode prop in favor of animationPresentation option ([9ac709e](https://github.com/react-navigation/react-navigation/commit/9ac709ea1e5a63c3a48abfa334ff6a6925095a72))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* automatically set headerMode if it's modal presentation style ([4bb0b43](https://github.com/react-navigation/react-navigation/commit/4bb0b43f1a0f27c96843415de6eaa37edebfb561))
|
||||||
|
* support mixing regular and modal presentation in same stack ([60fa3b9](https://github.com/react-navigation/react-navigation/commit/60fa3b9be976a73a5b04b632b4b37672674c956b))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* This drops the mode prop on the navigator in favor of a per-screen option animationPresentation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [6.0.0-next.10](https://github.com/react-navigation/react-navigation/compare/@react-navigation/stack@6.0.0-next.9...@react-navigation/stack@6.0.0-next.10) (2021-05-01)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [6.0.0-next.9](https://github.com/react-navigation/react-navigation/compare/@react-navigation/stack@6.0.0-next.8...@react-navigation/stack@6.0.0-next.9) (2021-04-08)
|
# [6.0.0-next.9](https://github.com/react-navigation/react-navigation/compare/@react-navigation/stack@6.0.0-next.8...@react-navigation/stack@6.0.0-next.9) (2021-04-08)
|
||||||
|
|
||||||
**Note:** Version bump only for package @react-navigation/stack
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|||||||
@@ -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": "6.0.0-next.9",
|
"version": "6.0.0-next.11",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"react-native-component",
|
"react-native-component",
|
||||||
"react-component",
|
"react-component",
|
||||||
@@ -40,17 +40,17 @@
|
|||||||
"clean": "del lib"
|
"clean": "del lib"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@react-navigation/elements": "^1.0.0-next.4",
|
"@react-navigation/elements": "^1.0.0-next.6",
|
||||||
"color": "^3.1.3",
|
"color": "^3.1.3",
|
||||||
"react-native-iphone-x-helper": "^1.3.0",
|
"react-native-iphone-x-helper": "^1.3.0",
|
||||||
"warn-once": "^0.0.1"
|
"warn-once": "^0.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@react-navigation/native": "^6.0.0-next.2",
|
"@react-navigation/native": "^6.0.0-next.4",
|
||||||
"@testing-library/react-native": "^7.2.0",
|
"@testing-library/react-native": "^7.2.0",
|
||||||
"@types/color": "^3.0.1",
|
"@types/color": "^3.0.1",
|
||||||
"@types/react": "^16.9.53",
|
"@types/react": "^16.9.53",
|
||||||
"@types/react-native": "~0.63.51",
|
"@types/react-native": "~0.64.4",
|
||||||
"del-cli": "^3.0.1",
|
"del-cli": "^3.0.1",
|
||||||
"react": "~16.13.1",
|
"react": "~16.13.1",
|
||||||
"react-native": "~0.63.4",
|
"react-native": "~0.63.4",
|
||||||
|
|||||||
@@ -118,13 +118,15 @@ export function forModalPresentationIOS({
|
|||||||
: 0
|
: 0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isFirst = index === 0;
|
||||||
|
|
||||||
const translateY = multiply(
|
const translateY = multiply(
|
||||||
progress.interpolate({
|
progress.interpolate({
|
||||||
inputRange: [0, 1, 2],
|
inputRange: [0, 1, 2],
|
||||||
outputRange: [
|
outputRange: [
|
||||||
screen.height,
|
screen.height,
|
||||||
index === 0 ? 0 : topOffset,
|
isFirst ? 0 : topOffset,
|
||||||
(index === 0 ? statusBarHeight : 0) - topOffset * aspectRatio,
|
(isFirst ? statusBarHeight : 0) - topOffset * aspectRatio,
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
inverted
|
inverted
|
||||||
@@ -148,7 +150,7 @@ export function forModalPresentationIOS({
|
|||||||
|
|
||||||
const borderRadius = isLandscape
|
const borderRadius = isLandscape
|
||||||
? 0
|
? 0
|
||||||
: index === 0
|
: isFirst
|
||||||
? progress.interpolate({
|
? progress.interpolate({
|
||||||
inputRange: [0, 1, 1.0001, 2],
|
inputRange: [0, 1, 1.0001, 2],
|
||||||
outputRange: [0, 0, isIphoneX() ? 38 : 0, 10],
|
outputRange: [0, 0, isIphoneX() ? 38 : 0, 10],
|
||||||
@@ -164,8 +166,8 @@ export function forModalPresentationIOS({
|
|||||||
// But different border radius for corners improves animation perf
|
// But different border radius for corners improves animation perf
|
||||||
borderBottomLeftRadius: isIphoneX() ? borderRadius : 0,
|
borderBottomLeftRadius: isIphoneX() ? borderRadius : 0,
|
||||||
borderBottomRightRadius: isIphoneX() ? borderRadius : 0,
|
borderBottomRightRadius: isIphoneX() ? borderRadius : 0,
|
||||||
marginTop: index === 0 ? 0 : statusBarHeight,
|
marginTop: isFirst ? 0 : statusBarHeight,
|
||||||
marginBottom: index === 0 ? 0 : topOffset,
|
marginBottom: isFirst ? 0 : topOffset,
|
||||||
transform: [{ translateY }, { scale }],
|
transform: [{ translateY }, { scale }],
|
||||||
},
|
},
|
||||||
overlayStyle: { opacity: overlayOpacity },
|
overlayStyle: { opacity: overlayOpacity },
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Platform } from 'react-native';
|
|
||||||
import {
|
import {
|
||||||
useNavigationBuilder,
|
useNavigationBuilder,
|
||||||
createNavigatorFactory,
|
createNavigatorFactory,
|
||||||
@@ -54,21 +53,9 @@ function StackNavigator({
|
|||||||
initialRouteName,
|
initialRouteName,
|
||||||
children,
|
children,
|
||||||
screenOptions,
|
screenOptions,
|
||||||
defaultScreenOptions: ({ options }) => ({
|
defaultScreenOptions: () => ({
|
||||||
headerShown: headerMode ? headerMode !== 'none' : true,
|
headerShown: headerMode ? headerMode !== 'none' : true,
|
||||||
headerMode:
|
headerMode: headerMode && headerMode !== 'none' ? headerMode : undefined,
|
||||||
headerMode && headerMode !== 'none'
|
|
||||||
? headerMode
|
|
||||||
: rest.mode !== 'modal' &&
|
|
||||||
Platform.OS === 'ios' &&
|
|
||||||
options.header === undefined
|
|
||||||
? 'float'
|
|
||||||
: 'screen',
|
|
||||||
gestureEnabled: Platform.OS === 'ios',
|
|
||||||
animationEnabled:
|
|
||||||
Platform.OS !== 'web' &&
|
|
||||||
Platform.OS !== 'windows' &&
|
|
||||||
Platform.OS !== 'macos',
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export type StackNavigationHelpers = NavigationHelpers<
|
|||||||
|
|
||||||
export type StackNavigationProp<
|
export type StackNavigationProp<
|
||||||
ParamList extends ParamListBase,
|
ParamList extends ParamListBase,
|
||||||
RouteName extends keyof ParamList = string
|
RouteName extends keyof ParamList = keyof ParamList
|
||||||
> = NavigationProp<
|
> = NavigationProp<
|
||||||
ParamList,
|
ParamList,
|
||||||
RouteName,
|
RouteName,
|
||||||
@@ -58,7 +58,7 @@ export type StackNavigationProp<
|
|||||||
|
|
||||||
export type StackScreenProps<
|
export type StackScreenProps<
|
||||||
ParamList extends ParamListBase,
|
ParamList extends ParamListBase,
|
||||||
RouteName extends keyof ParamList = string
|
RouteName extends keyof ParamList = keyof ParamList
|
||||||
> = {
|
> = {
|
||||||
navigation: StackNavigationProp<ParamList, RouteName>;
|
navigation: StackNavigationProp<ParamList, RouteName>;
|
||||||
route: RouteProp<ParamList, RouteName>;
|
route: RouteProp<ParamList, RouteName>;
|
||||||
@@ -72,11 +72,21 @@ export type GestureDirection =
|
|||||||
| 'vertical'
|
| 'vertical'
|
||||||
| 'vertical-inverted';
|
| 'vertical-inverted';
|
||||||
|
|
||||||
|
type SceneOptionsDefaults = TransitionPreset & {
|
||||||
|
animationEnabled: boolean;
|
||||||
|
gestureEnabled: boolean;
|
||||||
|
cardOverlayEnabled: boolean;
|
||||||
|
headerMode: StackHeaderMode;
|
||||||
|
};
|
||||||
|
|
||||||
export type Scene = {
|
export type Scene = {
|
||||||
/**
|
/**
|
||||||
* Descriptor object for the screen.
|
* Descriptor object for the screen.
|
||||||
*/
|
*/
|
||||||
descriptor: StackDescriptor;
|
descriptor: Omit<StackDescriptor, 'options'> & {
|
||||||
|
options: Omit<StackDescriptor['options'], keyof SceneOptionsDefaults> &
|
||||||
|
SceneOptionsDefaults;
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* Animated nodes representing the progress of the animation.
|
* Animated nodes representing the progress of the animation.
|
||||||
*/
|
*/
|
||||||
@@ -102,7 +112,7 @@ export type SceneProgress = {
|
|||||||
|
|
||||||
export type StackHeaderMode = 'float' | 'screen';
|
export type StackHeaderMode = 'float' | 'screen';
|
||||||
|
|
||||||
export type StackCardMode = 'card' | 'modal';
|
export type StackPresentationMode = 'card' | 'modal';
|
||||||
|
|
||||||
export type StackHeaderOptions = HeaderOptions & {
|
export type StackHeaderOptions = HeaderOptions & {
|
||||||
/**
|
/**
|
||||||
@@ -182,7 +192,7 @@ export type StackHeaderProps = {
|
|||||||
export type StackDescriptor = Descriptor<
|
export type StackDescriptor = Descriptor<
|
||||||
StackNavigationOptions,
|
StackNavigationOptions,
|
||||||
StackNavigationProp<ParamListBase>,
|
StackNavigationProp<ParamListBase>,
|
||||||
RouteProp<ParamListBase, string>
|
RouteProp<ParamListBase>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type StackDescriptorMap = Record<string, StackDescriptor>;
|
export type StackDescriptorMap = Record<string, StackDescriptor>;
|
||||||
@@ -228,8 +238,12 @@ export type StackNavigationOptions = StackHeaderOptions &
|
|||||||
*
|
*
|
||||||
* You can also specify `{ backgroundColor: 'transparent' }` to make the previous screen visible underneath.
|
* You can also specify `{ backgroundColor: 'transparent' }` to make the previous screen visible underneath.
|
||||||
* This is useful to implement things like modal dialogs.
|
* This is useful to implement things like modal dialogs.
|
||||||
* If you use [`react-native-screens`](https://github.com/kmagiera/react-native-screens), you should also specify `mode: 'modal'`
|
*
|
||||||
* in the stack view config when using a transparent background so previous screens aren't detached.
|
* You should also specify `detachPreviousScreen: false` in options when using a transparent background
|
||||||
|
* so that the previous screen isn't detached and stays below the current screen.
|
||||||
|
*
|
||||||
|
* You might also need to change the animation of the screen using `cardStyleInterpolator`
|
||||||
|
* so that the previous screen isn't transformed or invisible.
|
||||||
*/
|
*/
|
||||||
cardStyle?: StyleProp<ViewStyle>;
|
cardStyle?: StyleProp<ViewStyle>;
|
||||||
/**
|
/**
|
||||||
@@ -238,6 +252,16 @@ export type StackNavigationOptions = StackHeaderOptions &
|
|||||||
* Defaults to `true` on Android and iOS, `false` on Web.
|
* Defaults to `true` on Android and iOS, `false` on Web.
|
||||||
*/
|
*/
|
||||||
animationEnabled?: boolean;
|
animationEnabled?: boolean;
|
||||||
|
/**
|
||||||
|
* Whether this screen should be presented as a modal or a regular card.
|
||||||
|
*
|
||||||
|
* If you haven't customized the animations separately, the animation will change based on the value:
|
||||||
|
* - 'modal' - modal animation on iOS and Android. It'll also default `headerMode` to `screen`.
|
||||||
|
* - 'card' - horizontal slide animation on iOS, OS-default animation on Android.
|
||||||
|
*
|
||||||
|
* Defaults to 'card'.
|
||||||
|
*/
|
||||||
|
animationPresentation?: 'card' | 'modal';
|
||||||
/**
|
/**
|
||||||
* The type of animation to use when this screen replaces another screen. Defaults to `push`.
|
* The type of animation to use when this screen replaces another screen. Defaults to `push`.
|
||||||
* When `pop` is used, the `pop` animation is applied to the screen being replaced.
|
* When `pop` is used, the `pop` animation is applied to the screen being replaced.
|
||||||
@@ -262,13 +286,12 @@ export type StackNavigationOptions = StackHeaderOptions &
|
|||||||
* Whether to detach the previous screen from the view hierarchy to save memory.
|
* Whether to detach the previous screen from the view hierarchy to save memory.
|
||||||
* Set it to `false` if you need the previous screen to be seen through the active screen.
|
* Set it to `false` if you need the previous screen to be seen through the active screen.
|
||||||
* Only applicable if `detachInactiveScreens` isn't set to `false`.
|
* Only applicable if `detachInactiveScreens` isn't set to `false`.
|
||||||
* Defaults to `false` for the last screen when mode='modal', otherwise `true`.
|
* Defaults to `false` for the last screen for modals, otherwise `true`.
|
||||||
*/
|
*/
|
||||||
detachPreviousScreen?: boolean;
|
detachPreviousScreen?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type StackNavigationConfig = {
|
export type StackNavigationConfig = {
|
||||||
mode?: StackCardMode;
|
|
||||||
/**
|
/**
|
||||||
* If `false`, the keyboard will NOT automatically dismiss when navigating to a new screen.
|
* If `false`, the keyboard will NOT automatically dismiss when navigating to a new screen.
|
||||||
* Defaults to `true`.
|
* Defaults to `true`.
|
||||||
@@ -319,7 +342,7 @@ export type StackCardInterpolationProps = {
|
|||||||
progress: Animated.AnimatedInterpolation;
|
progress: Animated.AnimatedInterpolation;
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* The index of the card in the stack.
|
* The index of the card with this interpolation in the stack.
|
||||||
*/
|
*/
|
||||||
index: number;
|
index: number;
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ import {
|
|||||||
import type {
|
import type {
|
||||||
Layout,
|
Layout,
|
||||||
Scene,
|
Scene,
|
||||||
StackHeaderStyleInterpolator,
|
|
||||||
StackNavigationProp,
|
StackNavigationProp,
|
||||||
StackHeaderProps,
|
StackHeaderProps,
|
||||||
|
StackHeaderMode,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
mode: 'float' | 'screen';
|
mode: StackHeaderMode;
|
||||||
layout: Layout;
|
layout: Layout;
|
||||||
scenes: (Scene | undefined)[];
|
scenes: (Scene | undefined)[];
|
||||||
getPreviousScene: (props: { route: Route<string> }) => Scene | undefined;
|
getPreviousScene: (props: { route: Route<string> }) => Scene | undefined;
|
||||||
@@ -33,7 +33,6 @@ export type Props = {
|
|||||||
route: Route<string>;
|
route: Route<string>;
|
||||||
height: number;
|
height: number;
|
||||||
}) => void;
|
}) => void;
|
||||||
styleInterpolator: StackHeaderStyleInterpolator;
|
|
||||||
style?: Animated.WithAnimatedValue<StyleProp<ViewStyle>>;
|
style?: Animated.WithAnimatedValue<StyleProp<ViewStyle>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -44,7 +43,6 @@ export default function HeaderContainer({
|
|||||||
getPreviousScene,
|
getPreviousScene,
|
||||||
getFocusedRoute,
|
getFocusedRoute,
|
||||||
onContentHeightChange,
|
onContentHeightChange,
|
||||||
styleInterpolator,
|
|
||||||
style,
|
style,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const focusedRoute = getFocusedRoute();
|
const focusedRoute = getFocusedRoute();
|
||||||
@@ -57,8 +55,13 @@ export default function HeaderContainer({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { header, headerMode, headerShown = true, headerTransparent } =
|
const {
|
||||||
scene.descriptor.options || {};
|
header,
|
||||||
|
headerMode,
|
||||||
|
headerShown = true,
|
||||||
|
headerTransparent,
|
||||||
|
headerStyleInterpolator,
|
||||||
|
} = scene.descriptor.options;
|
||||||
|
|
||||||
if (headerMode !== mode || !headerShown) {
|
if (headerMode !== mode || !headerShown) {
|
||||||
return null;
|
return null;
|
||||||
@@ -120,7 +123,7 @@ export default function HeaderContainer({
|
|||||||
: nextGestureDirection === 'horizontal-inverted'
|
: nextGestureDirection === 'horizontal-inverted'
|
||||||
? forSlideRight
|
? forSlideRight
|
||||||
: forSlideLeft
|
: forSlideLeft
|
||||||
: styleInterpolator
|
: headerStyleInterpolator
|
||||||
: forNoAnimation,
|
: forNoAnimation,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Animated, View, Platform, ViewProps } from 'react-native';
|
import { Animated, View, ViewProps } from 'react-native';
|
||||||
|
|
||||||
let Screens: typeof import('react-native-screens') | undefined;
|
let Screens: typeof import('react-native-screens') | undefined;
|
||||||
|
|
||||||
@@ -9,31 +9,6 @@ try {
|
|||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
export const shouldUseActivityState = Screens?.shouldUseActivityState;
|
|
||||||
|
|
||||||
// So we use our custom implementation to handle a11y better
|
|
||||||
class WebScreen extends React.Component<
|
|
||||||
ViewProps & {
|
|
||||||
active: number;
|
|
||||||
children: React.ReactNode;
|
|
||||||
}
|
|
||||||
> {
|
|
||||||
render() {
|
|
||||||
const { active, style, ...rest } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
// @ts-expect-error: hidden exists on web, but not in React Native
|
|
||||||
hidden={!active}
|
|
||||||
style={[style, { display: active ? 'flex' : 'none' }]}
|
|
||||||
{...rest}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const AnimatedWebScreen = Animated.createAnimatedComponent(WebScreen);
|
|
||||||
|
|
||||||
export const MaybeScreenContainer = ({
|
export const MaybeScreenContainer = ({
|
||||||
enabled,
|
enabled,
|
||||||
...rest
|
...rest
|
||||||
@@ -41,11 +16,8 @@ export const MaybeScreenContainer = ({
|
|||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) => {
|
}) => {
|
||||||
if (enabled && Platform.OS !== 'web' && Screens?.screensEnabled()) {
|
if (Screens != null) {
|
||||||
return (
|
return <Screens.ScreenContainer enabled={enabled} {...rest} />;
|
||||||
// @ts-ignore
|
|
||||||
<Screens.ScreenContainer enabled={enabled} {...rest} />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return <View {...rest} />;
|
return <View {...rest} />;
|
||||||
@@ -60,18 +32,10 @@ export const MaybeScreen = ({
|
|||||||
active: 0 | 1 | Animated.AnimatedInterpolation;
|
active: 0 | 1 | Animated.AnimatedInterpolation;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) => {
|
}) => {
|
||||||
if (enabled && Platform.OS === 'web') {
|
if (Screens != null) {
|
||||||
return <AnimatedWebScreen active={active} {...rest} />;
|
return (
|
||||||
}
|
<Screens.Screen enabled={enabled} activityState={active} {...rest} />
|
||||||
|
);
|
||||||
if (enabled && Screens?.screensEnabled()) {
|
|
||||||
if (shouldUseActivityState) {
|
|
||||||
return (
|
|
||||||
<Screens.Screen enabled={enabled} activityState={active} {...rest} />
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return <Screens.Screen enabled={enabled} active={active} {...rest} />;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return <View {...rest} />;
|
return <View {...rest} />;
|
||||||
|
|||||||
@@ -29,10 +29,12 @@ import type {
|
|||||||
StackCardStyleInterpolator,
|
StackCardStyleInterpolator,
|
||||||
GestureDirection,
|
GestureDirection,
|
||||||
Layout,
|
Layout,
|
||||||
|
StackCardInterpolationProps,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
|
||||||
type Props = ViewProps & {
|
type Props = ViewProps & {
|
||||||
index: number;
|
// index: number;
|
||||||
|
interpolationIndex: number;
|
||||||
closing: boolean;
|
closing: boolean;
|
||||||
next?: Animated.AnimatedInterpolation;
|
next?: Animated.AnimatedInterpolation;
|
||||||
current: Animated.AnimatedInterpolation;
|
current: Animated.AnimatedInterpolation;
|
||||||
@@ -344,38 +346,14 @@ export default class Card extends React.Component<Props> {
|
|||||||
private getInterpolatedStyle = memoize(
|
private getInterpolatedStyle = memoize(
|
||||||
(
|
(
|
||||||
styleInterpolator: StackCardStyleInterpolator,
|
styleInterpolator: StackCardStyleInterpolator,
|
||||||
index: number,
|
animation: StackCardInterpolationProps
|
||||||
current: Animated.AnimatedInterpolation,
|
) => styleInterpolator(animation)
|
||||||
next: Animated.AnimatedInterpolation | undefined,
|
|
||||||
layout: Layout,
|
|
||||||
insetTop: number,
|
|
||||||
insetRight: number,
|
|
||||||
insetBottom: number,
|
|
||||||
insetLeft: number
|
|
||||||
) =>
|
|
||||||
styleInterpolator({
|
|
||||||
index,
|
|
||||||
current: { progress: current },
|
|
||||||
next: next && { progress: next },
|
|
||||||
closing: this.isClosing,
|
|
||||||
swiping: this.isSwiping,
|
|
||||||
inverted: this.inverted,
|
|
||||||
layouts: {
|
|
||||||
screen: layout,
|
|
||||||
},
|
|
||||||
insets: {
|
|
||||||
top: insetTop,
|
|
||||||
right: insetRight,
|
|
||||||
bottom: insetBottom,
|
|
||||||
left: insetLeft,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Keep track of the animation context when deps changes.
|
// Keep track of the animation context when deps changes.
|
||||||
private getCardAnimationContext = memoize(
|
private getCardAnimation = memoize(
|
||||||
(
|
(
|
||||||
index: number,
|
interpolationIndex: number,
|
||||||
current: Animated.AnimatedInterpolation,
|
current: Animated.AnimatedInterpolation,
|
||||||
next: Animated.AnimatedInterpolation | undefined,
|
next: Animated.AnimatedInterpolation | undefined,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
@@ -384,7 +362,7 @@ export default class Card extends React.Component<Props> {
|
|||||||
insetBottom: number,
|
insetBottom: number,
|
||||||
insetLeft: number
|
insetLeft: number
|
||||||
) => ({
|
) => ({
|
||||||
index,
|
index: interpolationIndex,
|
||||||
current: { progress: current },
|
current: { progress: current },
|
||||||
next: next && { progress: next },
|
next: next && { progress: next },
|
||||||
closing: this.isClosing,
|
closing: this.isClosing,
|
||||||
@@ -450,7 +428,8 @@ export default class Card extends React.Component<Props> {
|
|||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
styleInterpolator,
|
styleInterpolator,
|
||||||
index,
|
// index,
|
||||||
|
interpolationIndex,
|
||||||
current,
|
current,
|
||||||
gesture,
|
gesture,
|
||||||
next,
|
next,
|
||||||
@@ -469,9 +448,8 @@ export default class Card extends React.Component<Props> {
|
|||||||
...rest
|
...rest
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const interpolatedStyle = this.getInterpolatedStyle(
|
const interpolationProps = this.getCardAnimation(
|
||||||
styleInterpolator,
|
interpolationIndex,
|
||||||
index,
|
|
||||||
current,
|
current,
|
||||||
next,
|
next,
|
||||||
layout,
|
layout,
|
||||||
@@ -481,15 +459,9 @@ export default class Card extends React.Component<Props> {
|
|||||||
insets.left
|
insets.left
|
||||||
);
|
);
|
||||||
|
|
||||||
const animationContext = this.getCardAnimationContext(
|
const interpolatedStyle = this.getInterpolatedStyle(
|
||||||
index,
|
styleInterpolator,
|
||||||
current,
|
interpolationProps
|
||||||
next,
|
|
||||||
layout,
|
|
||||||
insets.top,
|
|
||||||
insets.right,
|
|
||||||
insets.bottom,
|
|
||||||
insets.left
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -521,13 +493,13 @@ export default class Card extends React.Component<Props> {
|
|||||||
: false;
|
: false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CardAnimationContext.Provider value={animationContext}>
|
<CardAnimationContext.Provider value={interpolationProps}>
|
||||||
{
|
{
|
||||||
// StatusBar messes with translucent status bar on Android
|
// StatusBar messes with translucent status bar on Android
|
||||||
// So we should only enable it on iOS
|
// So we should only enable it on iOS
|
||||||
Platform.OS === 'ios' &&
|
Platform.OS === 'ios' &&
|
||||||
overlayEnabled &&
|
overlayEnabled &&
|
||||||
index === 0 &&
|
interpolationIndex === 0 &&
|
||||||
next &&
|
next &&
|
||||||
styleInterpolator === forModalPresentationIOS ? (
|
styleInterpolator === forModalPresentationIOS ? (
|
||||||
<ModalStatusBarManager
|
<ModalStatusBarManager
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Animated, View, StyleSheet, StyleProp, ViewStyle } from 'react-native';
|
import { Animated, View, StyleSheet } from 'react-native';
|
||||||
import { Route, useTheme } from '@react-navigation/native';
|
import { Route, useTheme } from '@react-navigation/native';
|
||||||
import {
|
import {
|
||||||
HeaderShownContext,
|
HeaderShownContext,
|
||||||
@@ -11,16 +11,10 @@ import type { Props as HeaderContainerProps } from '../Header/HeaderContainer';
|
|||||||
import Card from './Card';
|
import Card from './Card';
|
||||||
import { forModalPresentationIOS } from '../../TransitionConfigs/CardStyleInterpolators';
|
import { forModalPresentationIOS } from '../../TransitionConfigs/CardStyleInterpolators';
|
||||||
import ModalPresentationContext from '../../utils/ModalPresentationContext';
|
import ModalPresentationContext from '../../utils/ModalPresentationContext';
|
||||||
import type {
|
import type { Layout, Scene } from '../../types';
|
||||||
Layout,
|
|
||||||
StackHeaderMode,
|
|
||||||
StackCardMode,
|
|
||||||
TransitionPreset,
|
|
||||||
Scene,
|
|
||||||
} from '../../types';
|
|
||||||
|
|
||||||
type Props = TransitionPreset & {
|
type Props = {
|
||||||
index: number;
|
interpolationIndex: number;
|
||||||
active: boolean;
|
active: boolean;
|
||||||
focused: boolean;
|
focused: boolean;
|
||||||
closing: boolean;
|
closing: boolean;
|
||||||
@@ -32,12 +26,6 @@ type Props = TransitionPreset & {
|
|||||||
safeAreaInsetRight: number;
|
safeAreaInsetRight: number;
|
||||||
safeAreaInsetBottom: number;
|
safeAreaInsetBottom: number;
|
||||||
safeAreaInsetLeft: number;
|
safeAreaInsetLeft: number;
|
||||||
cardOverlay?: (props: {
|
|
||||||
style: Animated.WithAnimatedValue<StyleProp<ViewStyle>>;
|
|
||||||
}) => React.ReactNode;
|
|
||||||
cardOverlayEnabled: boolean;
|
|
||||||
cardShadowEnabled?: boolean;
|
|
||||||
cardStyle?: StyleProp<ViewStyle>;
|
|
||||||
getPreviousScene: (props: { route: Route<string> }) => Scene | undefined;
|
getPreviousScene: (props: { route: Route<string> }) => Scene | undefined;
|
||||||
getFocusedRoute: () => Route<string>;
|
getFocusedRoute: () => Route<string>;
|
||||||
renderHeader: (props: HeaderContainerProps) => React.ReactNode;
|
renderHeader: (props: HeaderContainerProps) => React.ReactNode;
|
||||||
@@ -55,12 +43,6 @@ type Props = TransitionPreset & {
|
|||||||
onGestureStart?: (props: { route: Route<string> }) => void;
|
onGestureStart?: (props: { route: Route<string> }) => void;
|
||||||
onGestureEnd?: (props: { route: Route<string> }) => void;
|
onGestureEnd?: (props: { route: Route<string> }) => void;
|
||||||
onGestureCancel?: (props: { route: Route<string> }) => void;
|
onGestureCancel?: (props: { route: Route<string> }) => void;
|
||||||
gestureEnabled?: boolean;
|
|
||||||
gestureResponseDistance?: number;
|
|
||||||
gestureVelocityImpact?: number;
|
|
||||||
mode: StackCardMode;
|
|
||||||
headerMode: StackHeaderMode;
|
|
||||||
headerShown: boolean;
|
|
||||||
hasAbsoluteFloatHeader: boolean;
|
hasAbsoluteFloatHeader: boolean;
|
||||||
headerHeight: number;
|
headerHeight: number;
|
||||||
onHeaderHeightChange: (props: {
|
onHeaderHeightChange: (props: {
|
||||||
@@ -74,30 +56,17 @@ const EPSILON = 0.1;
|
|||||||
|
|
||||||
function CardContainer({
|
function CardContainer({
|
||||||
active,
|
active,
|
||||||
cardOverlay,
|
|
||||||
cardOverlayEnabled,
|
|
||||||
cardShadowEnabled,
|
|
||||||
cardStyle,
|
|
||||||
cardStyleInterpolator,
|
|
||||||
closing,
|
closing,
|
||||||
gesture,
|
gesture,
|
||||||
focused,
|
focused,
|
||||||
gestureDirection,
|
|
||||||
gestureEnabled,
|
|
||||||
gestureResponseDistance,
|
|
||||||
gestureVelocityImpact,
|
|
||||||
getPreviousScene,
|
getPreviousScene,
|
||||||
getFocusedRoute,
|
getFocusedRoute,
|
||||||
mode,
|
|
||||||
headerDarkContent,
|
headerDarkContent,
|
||||||
headerMode,
|
|
||||||
headerShown,
|
|
||||||
headerStyleInterpolator,
|
|
||||||
hasAbsoluteFloatHeader,
|
hasAbsoluteFloatHeader,
|
||||||
headerHeight,
|
headerHeight,
|
||||||
onHeaderHeightChange,
|
onHeaderHeightChange,
|
||||||
isParentHeaderShown,
|
isParentHeaderShown,
|
||||||
index,
|
interpolationIndex,
|
||||||
layout,
|
layout,
|
||||||
onCloseRoute,
|
onCloseRoute,
|
||||||
onOpenRoute,
|
onOpenRoute,
|
||||||
@@ -116,7 +85,6 @@ function CardContainer({
|
|||||||
safeAreaInsetRight,
|
safeAreaInsetRight,
|
||||||
safeAreaInsetTop,
|
safeAreaInsetTop,
|
||||||
scene,
|
scene,
|
||||||
transitionSpec,
|
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const parentHeaderHeight = React.useContext(HeaderHeightContext);
|
const parentHeaderHeight = React.useContext(HeaderHeightContext);
|
||||||
|
|
||||||
@@ -188,7 +156,6 @@ function CardContainer({
|
|||||||
);
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
// @ts-expect-error: AnimatedInterpolation optionally has addListener, but the type defs don't think so
|
|
||||||
const listener = scene.progress.next?.addListener?.(
|
const listener = scene.progress.next?.addListener?.(
|
||||||
({ value }: { value: number }) => {
|
({ value }: { value: number }) => {
|
||||||
setPointerEvents(value <= EPSILON ? 'box-none' : 'none');
|
setPointerEvents(value <= EPSILON ? 'box-none' : 'none');
|
||||||
@@ -197,12 +164,27 @@ function CardContainer({
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (listener) {
|
if (listener) {
|
||||||
// @ts-expect-error: AnimatedInterpolation optionally has removedListener, but the type defs don't think so
|
|
||||||
scene.progress.next?.removeListener?.(listener);
|
scene.progress.next?.removeListener?.(listener);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [pointerEvents, scene.progress.next]);
|
}, [pointerEvents, scene.progress.next]);
|
||||||
|
|
||||||
|
const {
|
||||||
|
animationPresentation,
|
||||||
|
cardOverlay,
|
||||||
|
cardOverlayEnabled,
|
||||||
|
cardShadowEnabled,
|
||||||
|
cardStyle,
|
||||||
|
cardStyleInterpolator,
|
||||||
|
gestureDirection,
|
||||||
|
gestureEnabled,
|
||||||
|
gestureResponseDistance,
|
||||||
|
gestureVelocityImpact,
|
||||||
|
headerMode,
|
||||||
|
headerShown,
|
||||||
|
transitionSpec,
|
||||||
|
} = scene.descriptor.options;
|
||||||
|
|
||||||
const isModalPresentation = cardStyleInterpolator === forModalPresentationIOS;
|
const isModalPresentation = cardStyleInterpolator === forModalPresentationIOS;
|
||||||
const previousScene = getPreviousScene({ route: scene.descriptor.route });
|
const previousScene = getPreviousScene({ route: scene.descriptor.route });
|
||||||
|
|
||||||
@@ -221,7 +203,7 @@ function CardContainer({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
index={index}
|
interpolationIndex={interpolationIndex}
|
||||||
gestureDirection={gestureDirection}
|
gestureDirection={gestureDirection}
|
||||||
layout={layout}
|
layout={layout}
|
||||||
insets={insets}
|
insets={insets}
|
||||||
@@ -246,7 +228,9 @@ 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 !== 'float' && mode === 'card'}
|
pageOverflowEnabled={
|
||||||
|
headerMode !== 'float' && animationPresentation !== 'modal'
|
||||||
|
}
|
||||||
headerDarkContent={headerDarkContent}
|
headerDarkContent={headerDarkContent}
|
||||||
containerStyle={
|
containerStyle={
|
||||||
hasAbsoluteFloatHeader && headerMode !== 'screen'
|
hasAbsoluteFloatHeader && headerMode !== 'screen'
|
||||||
@@ -278,14 +262,15 @@ function CardContainer({
|
|||||||
</HeaderBackContext.Provider>
|
</HeaderBackContext.Provider>
|
||||||
</View>
|
</View>
|
||||||
{headerMode !== 'float' ? (
|
{headerMode !== 'float' ? (
|
||||||
<ModalPresentationContext.Provider value={isModalPresentation}>
|
<ModalPresentationContext.Provider
|
||||||
|
value={isModalPresentation && interpolationIndex !== 0}
|
||||||
|
>
|
||||||
{renderHeader({
|
{renderHeader({
|
||||||
mode: 'screen',
|
mode: 'screen',
|
||||||
layout,
|
layout,
|
||||||
scenes: [previousScene, scene],
|
scenes: [previousScene, scene],
|
||||||
getPreviousScene,
|
getPreviousScene,
|
||||||
getFocusedRoute,
|
getFocusedRoute,
|
||||||
styleInterpolator: headerStyleInterpolator,
|
|
||||||
onContentHeightChange: onHeaderHeightChange,
|
onContentHeightChange: onHeaderHeightChange,
|
||||||
})}
|
})}
|
||||||
</ModalPresentationContext.Provider>
|
</ModalPresentationContext.Provider>
|
||||||
|
|||||||
@@ -18,26 +18,25 @@ import {
|
|||||||
Background,
|
Background,
|
||||||
} from '@react-navigation/elements';
|
} from '@react-navigation/elements';
|
||||||
|
|
||||||
import {
|
import { MaybeScreenContainer, MaybeScreen } from '../Screens';
|
||||||
MaybeScreenContainer,
|
|
||||||
MaybeScreen,
|
|
||||||
shouldUseActivityState,
|
|
||||||
} from '../Screens';
|
|
||||||
import type { Props as HeaderContainerProps } from '../Header/HeaderContainer';
|
import type { Props as HeaderContainerProps } from '../Header/HeaderContainer';
|
||||||
import CardContainer from './CardContainer';
|
import CardContainer from './CardContainer';
|
||||||
import {
|
import {
|
||||||
DefaultTransition,
|
DefaultTransition,
|
||||||
ModalTransition,
|
ModalTransition,
|
||||||
} from '../../TransitionConfigs/TransitionPresets';
|
} from '../../TransitionConfigs/TransitionPresets';
|
||||||
import { forNoAnimation as forNoAnimationCard } from '../../TransitionConfigs/CardStyleInterpolators';
|
import {
|
||||||
|
forModalPresentationIOS,
|
||||||
|
forNoAnimation as forNoAnimationCard,
|
||||||
|
} from '../../TransitionConfigs/CardStyleInterpolators';
|
||||||
import getDistanceForDirection from '../../utils/getDistanceForDirection';
|
import getDistanceForDirection from '../../utils/getDistanceForDirection';
|
||||||
import type {
|
import type {
|
||||||
Layout,
|
Layout,
|
||||||
StackCardMode,
|
|
||||||
StackDescriptorMap,
|
|
||||||
StackNavigationOptions,
|
|
||||||
StackDescriptor,
|
|
||||||
Scene,
|
Scene,
|
||||||
|
StackDescriptor,
|
||||||
|
StackDescriptorMap,
|
||||||
|
StackHeaderMode,
|
||||||
|
StackNavigationOptions,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
|
||||||
type GestureValues = {
|
type GestureValues = {
|
||||||
@@ -45,7 +44,6 @@ type GestureValues = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
mode: StackCardMode;
|
|
||||||
insets: EdgeInsets;
|
insets: EdgeInsets;
|
||||||
state: StackNavigationState<ParamListBase>;
|
state: StackNavigationState<ParamListBase>;
|
||||||
descriptors: StackDescriptorMap;
|
descriptors: StackDescriptorMap;
|
||||||
@@ -57,7 +55,6 @@ type Props = {
|
|||||||
getPreviousRoute: (props: {
|
getPreviousRoute: (props: {
|
||||||
route: Route<string>;
|
route: Route<string>;
|
||||||
}) => Route<string> | undefined;
|
}) => Route<string> | undefined;
|
||||||
getGesturesEnabled: (props: { route: Route<string> }) => boolean;
|
|
||||||
renderHeader: (props: HeaderContainerProps) => React.ReactNode;
|
renderHeader: (props: HeaderContainerProps) => React.ReactNode;
|
||||||
renderScene: (props: { route: Route<string> }) => React.ReactNode;
|
renderScene: (props: { route: Route<string> }) => React.ReactNode;
|
||||||
isParentHeaderShown: boolean;
|
isParentHeaderShown: boolean;
|
||||||
@@ -121,27 +118,25 @@ const getHeaderHeights = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getDistanceFromOptions = (
|
const getDistanceFromOptions = (
|
||||||
mode: StackCardMode,
|
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
descriptor?: StackDescriptor
|
descriptor?: StackDescriptor
|
||||||
) => {
|
) => {
|
||||||
const {
|
const {
|
||||||
gestureDirection = mode === 'modal'
|
animationPresentation,
|
||||||
|
gestureDirection = animationPresentation === 'modal'
|
||||||
? ModalTransition.gestureDirection
|
? ModalTransition.gestureDirection
|
||||||
: DefaultTransition.gestureDirection,
|
: DefaultTransition.gestureDirection,
|
||||||
} = descriptor?.options || {};
|
} = (descriptor?.options || {}) as StackNavigationOptions;
|
||||||
|
|
||||||
return getDistanceForDirection(layout, gestureDirection);
|
return getDistanceForDirection(layout, gestureDirection);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getProgressFromGesture = (
|
const getProgressFromGesture = (
|
||||||
mode: StackCardMode,
|
|
||||||
gesture: Animated.Value,
|
gesture: Animated.Value,
|
||||||
layout: Layout,
|
layout: Layout,
|
||||||
descriptor?: StackDescriptor
|
descriptor?: StackDescriptor
|
||||||
) => {
|
) => {
|
||||||
const distance = getDistanceFromOptions(
|
const distance = getDistanceFromOptions(
|
||||||
mode,
|
|
||||||
{
|
{
|
||||||
// Make sure that we have a non-zero distance, otherwise there will be incorrect progress
|
// Make sure that we have a non-zero distance, otherwise there will be incorrect progress
|
||||||
// This causes blank screen on web if it was previously inside container with display: none
|
// This causes blank screen on web if it was previously inside container with display: none
|
||||||
@@ -165,7 +160,10 @@ const getProgressFromGesture = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default class CardStack extends React.Component<Props, State> {
|
export default class CardStack extends React.Component<Props, State> {
|
||||||
static getDerivedStateFromProps(props: Props, state: State) {
|
static getDerivedStateFromProps(
|
||||||
|
props: Props,
|
||||||
|
state: State
|
||||||
|
): Partial<State> | null {
|
||||||
if (
|
if (
|
||||||
props.routes === state.routes &&
|
props.routes === state.routes &&
|
||||||
props.descriptors === state.descriptors
|
props.descriptors === state.descriptors
|
||||||
@@ -182,7 +180,7 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
new Animated.Value(
|
new Animated.Value(
|
||||||
props.openingRouteKeys.includes(curr.key) &&
|
props.openingRouteKeys.includes(curr.key) &&
|
||||||
animationEnabled !== false
|
animationEnabled !== false
|
||||||
? getDistanceFromOptions(props.mode, state.layout, descriptor)
|
? getDistanceFromOptions(state.layout, descriptor)
|
||||||
: 0
|
: 0
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -216,19 +214,97 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
props.descriptors[previousRoute?.key] ||
|
props.descriptors[previousRoute?.key] ||
|
||||||
state.descriptors[previousRoute?.key];
|
state.descriptors[previousRoute?.key];
|
||||||
|
|
||||||
|
const { options } = descriptor;
|
||||||
|
|
||||||
|
let defaultTransitionPreset =
|
||||||
|
options.animationPresentation === 'modal'
|
||||||
|
? ModalTransition
|
||||||
|
: DefaultTransition;
|
||||||
|
|
||||||
|
const {
|
||||||
|
animationEnabled = Platform.OS !== 'web' &&
|
||||||
|
Platform.OS !== 'windows' &&
|
||||||
|
Platform.OS !== 'macos',
|
||||||
|
gestureEnabled = Platform.OS === 'ios' &&
|
||||||
|
animationEnabled &&
|
||||||
|
index !== 0,
|
||||||
|
gestureDirection = defaultTransitionPreset.gestureDirection,
|
||||||
|
transitionSpec = defaultTransitionPreset.transitionSpec,
|
||||||
|
cardStyleInterpolator = animationEnabled === false
|
||||||
|
? forNoAnimationCard
|
||||||
|
: defaultTransitionPreset.cardStyleInterpolator,
|
||||||
|
headerStyleInterpolator = defaultTransitionPreset.headerStyleInterpolator,
|
||||||
|
cardOverlayEnabled = Platform.OS !== 'ios' ||
|
||||||
|
cardStyleInterpolator === forModalPresentationIOS,
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
let transitionConfig = {
|
||||||
|
gestureDirection,
|
||||||
|
transitionSpec,
|
||||||
|
cardStyleInterpolator,
|
||||||
|
headerStyleInterpolator,
|
||||||
|
cardOverlayEnabled,
|
||||||
|
};
|
||||||
|
|
||||||
|
// When a screen is not the last, it should use next screen's transition config
|
||||||
|
// Many transitions also animate the previous screen, so using 2 different transitions doesn't look right
|
||||||
|
// For example combining a slide and a modal transition would look wrong otherwise
|
||||||
|
// With this approach, combining different transition styles in the same navigator mostly looks right
|
||||||
|
// This will still be broken when 2 transitions have different idle state (e.g. modal presentation),
|
||||||
|
// but majority of the transitions look alright
|
||||||
|
if (index !== self.length - 1) {
|
||||||
|
if (nextDescriptor) {
|
||||||
|
const {
|
||||||
|
animationEnabled,
|
||||||
|
gestureDirection = defaultTransitionPreset.gestureDirection,
|
||||||
|
transitionSpec = defaultTransitionPreset.transitionSpec,
|
||||||
|
cardStyleInterpolator = animationEnabled === false
|
||||||
|
? forNoAnimationCard
|
||||||
|
: defaultTransitionPreset.cardStyleInterpolator,
|
||||||
|
headerStyleInterpolator = defaultTransitionPreset.headerStyleInterpolator,
|
||||||
|
cardOverlayEnabled = descriptor.options.cardOverlayEnabled ??
|
||||||
|
cardStyleInterpolator === forModalPresentationIOS,
|
||||||
|
} = nextDescriptor.options;
|
||||||
|
|
||||||
|
transitionConfig = {
|
||||||
|
gestureDirection,
|
||||||
|
transitionSpec,
|
||||||
|
cardStyleInterpolator,
|
||||||
|
headerStyleInterpolator,
|
||||||
|
cardOverlayEnabled,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const headerMode: StackHeaderMode =
|
||||||
|
options.headerMode ??
|
||||||
|
(options.animationPresentation !== 'modal' &&
|
||||||
|
transitionConfig.cardStyleInterpolator !== forModalPresentationIOS &&
|
||||||
|
Platform.OS === 'ios' &&
|
||||||
|
options.header === undefined
|
||||||
|
? 'float'
|
||||||
|
: 'screen');
|
||||||
|
|
||||||
const scene = {
|
const scene = {
|
||||||
route,
|
route,
|
||||||
descriptor,
|
descriptor: {
|
||||||
|
...descriptor,
|
||||||
|
options: {
|
||||||
|
...options,
|
||||||
|
...transitionConfig,
|
||||||
|
animationEnabled,
|
||||||
|
gestureEnabled,
|
||||||
|
headerMode,
|
||||||
|
},
|
||||||
|
},
|
||||||
progress: {
|
progress: {
|
||||||
current: getProgressFromGesture(
|
current: getProgressFromGesture(
|
||||||
props.mode,
|
|
||||||
currentGesture,
|
currentGesture,
|
||||||
state.layout,
|
state.layout,
|
||||||
descriptor
|
descriptor
|
||||||
),
|
),
|
||||||
next: nextGesture
|
next: nextGesture
|
||||||
? getProgressFromGesture(
|
? getProgressFromGesture(
|
||||||
props.mode,
|
|
||||||
nextGesture,
|
nextGesture,
|
||||||
state.layout,
|
state.layout,
|
||||||
nextDescriptor
|
nextDescriptor
|
||||||
@@ -236,7 +312,6 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
: undefined,
|
: undefined,
|
||||||
previous: previousGesture
|
previous: previousGesture
|
||||||
? getProgressFromGesture(
|
? getProgressFromGesture(
|
||||||
props.mode,
|
|
||||||
previousGesture,
|
previousGesture,
|
||||||
state.layout,
|
state.layout,
|
||||||
previousDescriptor
|
previousDescriptor
|
||||||
@@ -369,15 +444,12 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
mode,
|
|
||||||
insets,
|
insets,
|
||||||
descriptors,
|
|
||||||
state,
|
state,
|
||||||
routes,
|
routes,
|
||||||
closingRouteKeys,
|
closingRouteKeys,
|
||||||
onOpenRoute,
|
onOpenRoute,
|
||||||
onCloseRoute,
|
onCloseRoute,
|
||||||
getGesturesEnabled,
|
|
||||||
renderHeader,
|
renderHeader,
|
||||||
renderScene,
|
renderScene,
|
||||||
isParentHeaderShown,
|
isParentHeaderShown,
|
||||||
@@ -389,47 +461,19 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
onGestureStart,
|
onGestureStart,
|
||||||
onGestureEnd,
|
onGestureEnd,
|
||||||
onGestureCancel,
|
onGestureCancel,
|
||||||
// Enable on new versions of `react-native-screens`
|
detachInactiveScreens = Platform.OS === 'web' ||
|
||||||
// On older versions of `react-native-screens`, there's an issue with screens not being responsive to user interaction.
|
Platform.OS === 'android' ||
|
||||||
detachInactiveScreens = Platform.OS === 'web'
|
Platform.OS === 'ios',
|
||||||
? true
|
|
||||||
: shouldUseActivityState ?? false,
|
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const { scenes, layout, gestures, headerHeights } = this.state;
|
const { scenes, layout, gestures, headerHeights } = this.state;
|
||||||
|
|
||||||
const focusedRoute = state.routes[state.index];
|
const focusedRoute = state.routes[state.index];
|
||||||
const focusedDescriptor = descriptors[focusedRoute.key];
|
|
||||||
const focusedOptions = focusedDescriptor ? focusedDescriptor.options : {};
|
|
||||||
const focusedHeaderHeight = headerHeights[focusedRoute.key];
|
const focusedHeaderHeight = headerHeights[focusedRoute.key];
|
||||||
|
|
||||||
let defaultTransitionPreset =
|
|
||||||
mode === 'modal' ? ModalTransition : DefaultTransition;
|
|
||||||
|
|
||||||
let activeScreensLimit = 1;
|
|
||||||
|
|
||||||
for (let i = scenes.length - 1; i >= 0; i--) {
|
|
||||||
const {
|
|
||||||
// By default, we don't want to detach the previous screen of the active one for modals
|
|
||||||
detachPreviousScreen = mode === 'modal'
|
|
||||||
? i !== scenes.length - 1
|
|
||||||
: true,
|
|
||||||
} = scenes[i].descriptor.options;
|
|
||||||
|
|
||||||
if (detachPreviousScreen === false) {
|
|
||||||
activeScreensLimit++;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const isFloatHeaderAbsolute = this.state.scenes.slice(-2).some((scene) => {
|
const isFloatHeaderAbsolute = this.state.scenes.slice(-2).some((scene) => {
|
||||||
const options = scene.descriptor.options ?? {};
|
const options = scene.descriptor.options ?? {};
|
||||||
const {
|
const { headerMode, headerTransparent, headerShown = true } = options;
|
||||||
headerMode = 'screen',
|
|
||||||
headerTransparent,
|
|
||||||
headerShown = true,
|
|
||||||
} = options;
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
headerTransparent ||
|
headerTransparent ||
|
||||||
@@ -442,6 +486,25 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let activeScreensLimit = 1;
|
||||||
|
|
||||||
|
for (let i = scenes.length - 1; i >= 0; i--) {
|
||||||
|
const { options } = scenes[i].descriptor;
|
||||||
|
const {
|
||||||
|
// By default, we don't want to detach the previous screen of the active one for modals
|
||||||
|
detachPreviousScreen = options.animationPresentation === 'modal' ||
|
||||||
|
options.cardStyleInterpolator === forModalPresentationIOS
|
||||||
|
? i !== scenes.length - 1
|
||||||
|
: true,
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
if (detachPreviousScreen === false) {
|
||||||
|
activeScreensLimit++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const floatingHeader = (
|
const floatingHeader = (
|
||||||
<React.Fragment key="header">
|
<React.Fragment key="header">
|
||||||
{renderHeader({
|
{renderHeader({
|
||||||
@@ -451,10 +514,6 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
getPreviousScene: this.getPreviousScene,
|
getPreviousScene: this.getPreviousScene,
|
||||||
getFocusedRoute: this.getFocusedRoute,
|
getFocusedRoute: this.getFocusedRoute,
|
||||||
onContentHeightChange: this.handleHeaderLayout,
|
onContentHeightChange: this.handleHeaderLayout,
|
||||||
styleInterpolator:
|
|
||||||
focusedOptions.headerStyleInterpolator !== undefined
|
|
||||||
? focusedOptions.headerStyleInterpolator
|
|
||||||
: defaultTransitionPreset.headerStyleInterpolator,
|
|
||||||
style: [
|
style: [
|
||||||
styles.floating,
|
styles.floating,
|
||||||
isFloatHeaderAbsolute && [
|
isFloatHeaderAbsolute && [
|
||||||
@@ -486,96 +545,33 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
// For the old implementation, it stays the same it was
|
// For the old implementation, it stays the same it was
|
||||||
let isScreenActive: Animated.AnimatedInterpolation | 2 | 1 | 0 = 1;
|
let isScreenActive: Animated.AnimatedInterpolation | 2 | 1 | 0 = 1;
|
||||||
|
|
||||||
if (shouldUseActivityState || Platform.OS === 'web') {
|
if (index < self.length - activeScreensLimit - 1) {
|
||||||
if (index < self.length - activeScreensLimit - 1) {
|
// screen should be inactive because it is too deep in the stack
|
||||||
// screen should be inactive because it is too deep in the stack
|
isScreenActive = STATE_INACTIVE;
|
||||||
isScreenActive = STATE_INACTIVE;
|
|
||||||
} else {
|
|
||||||
const sceneForActivity = scenes[self.length - 1];
|
|
||||||
const outputValue =
|
|
||||||
index === self.length - 1
|
|
||||||
? STATE_ON_TOP // the screen is on top after the transition
|
|
||||||
: index >= self.length - activeScreensLimit
|
|
||||||
? STATE_TRANSITIONING_OR_BELOW_TOP // the screen should stay active after the transition, it is not on top but is in activeLimit
|
|
||||||
: STATE_INACTIVE; // the screen should be active only during the transition, it is at the edge of activeLimit
|
|
||||||
isScreenActive = sceneForActivity
|
|
||||||
? sceneForActivity.progress.current.interpolate({
|
|
||||||
inputRange: [0, 1 - EPSILON, 1],
|
|
||||||
outputRange: [1, 1, outputValue],
|
|
||||||
extrapolate: 'clamp',
|
|
||||||
})
|
|
||||||
: STATE_TRANSITIONING_OR_BELOW_TOP;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
isScreenActive = scene.progress.next
|
const sceneForActivity = scenes[self.length - 1];
|
||||||
? scene.progress.next.interpolate({
|
const outputValue =
|
||||||
|
index === self.length - 1
|
||||||
|
? STATE_ON_TOP // the screen is on top after the transition
|
||||||
|
: index >= self.length - activeScreensLimit
|
||||||
|
? STATE_TRANSITIONING_OR_BELOW_TOP // the screen should stay active after the transition, it is not on top but is in activeLimit
|
||||||
|
: STATE_INACTIVE; // the screen should be active only during the transition, it is at the edge of activeLimit
|
||||||
|
isScreenActive = sceneForActivity
|
||||||
|
? sceneForActivity.progress.current.interpolate({
|
||||||
inputRange: [0, 1 - EPSILON, 1],
|
inputRange: [0, 1 - EPSILON, 1],
|
||||||
outputRange: [1, 1, 0],
|
outputRange: [1, 1, outputValue],
|
||||||
extrapolate: 'clamp',
|
extrapolate: 'clamp',
|
||||||
})
|
})
|
||||||
: 1;
|
: STATE_TRANSITIONING_OR_BELOW_TOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
cardStyleInterpolator,
|
||||||
headerShown = true,
|
headerShown = true,
|
||||||
headerMode = 'screen',
|
|
||||||
headerTransparent,
|
headerTransparent,
|
||||||
headerStyle,
|
headerStyle,
|
||||||
headerTintColor,
|
headerTintColor,
|
||||||
cardShadowEnabled,
|
} = scene.descriptor.options;
|
||||||
cardOverlayEnabled = Platform.OS !== 'ios' || mode === 'modal',
|
|
||||||
cardOverlay,
|
|
||||||
cardStyle,
|
|
||||||
animationEnabled,
|
|
||||||
gestureResponseDistance,
|
|
||||||
gestureVelocityImpact,
|
|
||||||
gestureDirection = defaultTransitionPreset.gestureDirection,
|
|
||||||
transitionSpec = defaultTransitionPreset.transitionSpec,
|
|
||||||
cardStyleInterpolator = animationEnabled === false
|
|
||||||
? forNoAnimationCard
|
|
||||||
: defaultTransitionPreset.cardStyleInterpolator,
|
|
||||||
headerStyleInterpolator = defaultTransitionPreset.headerStyleInterpolator,
|
|
||||||
} = scene.descriptor
|
|
||||||
? scene.descriptor.options
|
|
||||||
: ({} as StackNavigationOptions);
|
|
||||||
|
|
||||||
let transitionConfig = {
|
|
||||||
gestureDirection,
|
|
||||||
transitionSpec,
|
|
||||||
cardStyleInterpolator,
|
|
||||||
headerStyleInterpolator,
|
|
||||||
};
|
|
||||||
|
|
||||||
// When a screen is not the last, it should use next screen's transition config
|
|
||||||
// Many transitions also animate the previous screen, so using 2 different transitions doesn't look right
|
|
||||||
// For example combining a slide and a modal transition would look wrong otherwise
|
|
||||||
// With this approach, combining different transition styles in the same navigator mostly looks right
|
|
||||||
// This will still be broken when 2 transitions have different idle state (e.g. modal presentation),
|
|
||||||
// but majority of the transitions look alright
|
|
||||||
if (index !== self.length - 1) {
|
|
||||||
const nextScene = scenes[index + 1];
|
|
||||||
|
|
||||||
if (nextScene) {
|
|
||||||
const {
|
|
||||||
animationEnabled,
|
|
||||||
gestureDirection = defaultTransitionPreset.gestureDirection,
|
|
||||||
transitionSpec = defaultTransitionPreset.transitionSpec,
|
|
||||||
cardStyleInterpolator = animationEnabled === false
|
|
||||||
? forNoAnimationCard
|
|
||||||
: defaultTransitionPreset.cardStyleInterpolator,
|
|
||||||
headerStyleInterpolator = defaultTransitionPreset.headerStyleInterpolator,
|
|
||||||
} = nextScene.descriptor
|
|
||||||
? nextScene.descriptor.options
|
|
||||||
: ({} as StackNavigationOptions);
|
|
||||||
|
|
||||||
transitionConfig = {
|
|
||||||
gestureDirection,
|
|
||||||
transitionSpec,
|
|
||||||
cardStyleInterpolator,
|
|
||||||
headerStyleInterpolator,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const safeAreaInsetTop = insets.top;
|
const safeAreaInsetTop = insets.top;
|
||||||
const safeAreaInsetRight = insets.right;
|
const safeAreaInsetRight = insets.right;
|
||||||
@@ -598,6 +594,20 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start from current card and count backwards the number of cards with same interpolation
|
||||||
|
let interpolationIndex = 0;
|
||||||
|
|
||||||
|
for (let i = index - 1; i >= 0; i--) {
|
||||||
|
const cardStyleInterpolatorCurrent =
|
||||||
|
scenes[i]?.descriptor.options.cardStyleInterpolator;
|
||||||
|
|
||||||
|
if (cardStyleInterpolatorCurrent !== cardStyleInterpolator) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
interpolationIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MaybeScreen
|
<MaybeScreen
|
||||||
key={route.key}
|
key={route.key}
|
||||||
@@ -607,7 +617,7 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
pointerEvents="box-none"
|
pointerEvents="box-none"
|
||||||
>
|
>
|
||||||
<CardContainer
|
<CardContainer
|
||||||
index={index}
|
interpolationIndex={interpolationIndex}
|
||||||
active={index === self.length - 1}
|
active={index === self.length - 1}
|
||||||
focused={focused}
|
focused={focused}
|
||||||
closing={closingRouteKeys.includes(route.key)}
|
closing={closingRouteKeys.includes(route.key)}
|
||||||
@@ -618,25 +628,17 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
safeAreaInsetRight={safeAreaInsetRight}
|
safeAreaInsetRight={safeAreaInsetRight}
|
||||||
safeAreaInsetBottom={safeAreaInsetBottom}
|
safeAreaInsetBottom={safeAreaInsetBottom}
|
||||||
safeAreaInsetLeft={safeAreaInsetLeft}
|
safeAreaInsetLeft={safeAreaInsetLeft}
|
||||||
cardOverlay={cardOverlay}
|
|
||||||
cardOverlayEnabled={cardOverlayEnabled}
|
|
||||||
cardShadowEnabled={cardShadowEnabled}
|
|
||||||
cardStyle={cardStyle}
|
|
||||||
onPageChangeStart={onPageChangeStart}
|
onPageChangeStart={onPageChangeStart}
|
||||||
onPageChangeConfirm={onPageChangeConfirm}
|
onPageChangeConfirm={onPageChangeConfirm}
|
||||||
onPageChangeCancel={onPageChangeCancel}
|
onPageChangeCancel={onPageChangeCancel}
|
||||||
onGestureStart={onGestureStart}
|
onGestureStart={onGestureStart}
|
||||||
onGestureCancel={onGestureCancel}
|
onGestureCancel={onGestureCancel}
|
||||||
onGestureEnd={onGestureEnd}
|
onGestureEnd={onGestureEnd}
|
||||||
gestureResponseDistance={gestureResponseDistance}
|
|
||||||
headerHeight={headerHeight}
|
headerHeight={headerHeight}
|
||||||
isParentHeaderShown={isParentHeaderShown}
|
isParentHeaderShown={isParentHeaderShown}
|
||||||
onHeaderHeightChange={this.handleHeaderLayout}
|
onHeaderHeightChange={this.handleHeaderLayout}
|
||||||
getPreviousScene={this.getPreviousScene}
|
getPreviousScene={this.getPreviousScene}
|
||||||
getFocusedRoute={this.getFocusedRoute}
|
getFocusedRoute={this.getFocusedRoute}
|
||||||
mode={mode}
|
|
||||||
headerMode={headerMode}
|
|
||||||
headerShown={headerShown}
|
|
||||||
headerDarkContent={headerDarkContent}
|
headerDarkContent={headerDarkContent}
|
||||||
hasAbsoluteFloatHeader={
|
hasAbsoluteFloatHeader={
|
||||||
isFloatHeaderAbsolute && !headerTransparent
|
isFloatHeaderAbsolute && !headerTransparent
|
||||||
@@ -647,9 +649,6 @@ export default class CardStack extends React.Component<Props, State> {
|
|||||||
onCloseRoute={onCloseRoute}
|
onCloseRoute={onCloseRoute}
|
||||||
onTransitionStart={onTransitionStart}
|
onTransitionStart={onTransitionStart}
|
||||||
onTransitionEnd={onTransitionEnd}
|
onTransitionEnd={onTransitionEnd}
|
||||||
gestureEnabled={index !== 0 && getGesturesEnabled({ route })}
|
|
||||||
gestureVelocityImpact={gestureVelocityImpact}
|
|
||||||
{...transitionConfig}
|
|
||||||
/>
|
/>
|
||||||
</MaybeScreen>
|
</MaybeScreen>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -288,24 +288,6 @@ export default class StackView extends React.Component<Props, State> {
|
|||||||
descriptors: {},
|
descriptors: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
private getGesturesEnabled = ({ route }: { route: Route<string> }) => {
|
|
||||||
const descriptor = this.state.descriptors[route.key];
|
|
||||||
|
|
||||||
if (descriptor) {
|
|
||||||
const { gestureEnabled, animationEnabled } = descriptor.options;
|
|
||||||
|
|
||||||
if (animationEnabled === false) {
|
|
||||||
// When animation is disabled, also disable gestures
|
|
||||||
// The gesture to dismiss a route will look weird when not animated
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return gestureEnabled !== false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
private getPreviousRoute = ({ route }: { route: Route<string> }) => {
|
private getPreviousRoute = ({ route }: { route: Route<string> }) => {
|
||||||
const { closingRouteKeys, replacingRouteKeys } = this.state;
|
const { closingRouteKeys, replacingRouteKeys } = this.state;
|
||||||
const routes = this.state.routes.filter(
|
const routes = this.state.routes.filter(
|
||||||
@@ -438,7 +420,6 @@ export default class StackView extends React.Component<Props, State> {
|
|||||||
state,
|
state,
|
||||||
navigation,
|
navigation,
|
||||||
keyboardHandlingEnabled,
|
keyboardHandlingEnabled,
|
||||||
mode = 'card',
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
descriptors: _,
|
descriptors: _,
|
||||||
...rest
|
...rest
|
||||||
@@ -462,11 +443,9 @@ export default class StackView extends React.Component<Props, State> {
|
|||||||
<HeaderShownContext.Consumer>
|
<HeaderShownContext.Consumer>
|
||||||
{(isParentHeaderShown) => (
|
{(isParentHeaderShown) => (
|
||||||
<CardStack
|
<CardStack
|
||||||
mode={mode}
|
|
||||||
insets={insets as EdgeInsets}
|
insets={insets as EdgeInsets}
|
||||||
isParentHeaderShown={isParentHeaderShown}
|
isParentHeaderShown={isParentHeaderShown}
|
||||||
getPreviousRoute={this.getPreviousRoute}
|
getPreviousRoute={this.getPreviousRoute}
|
||||||
getGesturesEnabled={this.getGesturesEnabled}
|
|
||||||
routes={routes}
|
routes={routes}
|
||||||
openingRouteKeys={openingRouteKeys}
|
openingRouteKeys={openingRouteKeys}
|
||||||
closingRouteKeys={closingRouteKeys}
|
closingRouteKeys={closingRouteKeys}
|
||||||
|
|||||||
418
yarn.lock
418
yarn.lock
@@ -1397,12 +1397,32 @@
|
|||||||
xcode "^3.0.1"
|
xcode "^3.0.1"
|
||||||
xml2js "^0.4.23"
|
xml2js "^0.4.23"
|
||||||
|
|
||||||
|
"@expo/config-plugins@1.0.29":
|
||||||
|
version "1.0.29"
|
||||||
|
resolved "https://registry.yarnpkg.com/@expo/config-plugins/-/config-plugins-1.0.29.tgz#fc36a7a90a08e1a67ed2c19241f4309b08e88a25"
|
||||||
|
integrity sha512-dKtb4dTRiyWmCr/HyMFqt1tHIFpuuvIPnmvakOrg012sY7be81W9WOXjsr6WP7uLT2BfSLFhj1A9EAUzpl6sJw==
|
||||||
|
dependencies:
|
||||||
|
"@expo/config-types" "^40.0.0-beta.2"
|
||||||
|
"@expo/configure-splash-screen" "0.3.4"
|
||||||
|
"@expo/image-utils" "0.3.13"
|
||||||
|
"@expo/json-file" "8.2.29"
|
||||||
|
"@expo/plist" "0.0.12"
|
||||||
|
find-up "~5.0.0"
|
||||||
|
fs-extra "9.0.0"
|
||||||
|
getenv "^1.0.0"
|
||||||
|
glob "7.1.6"
|
||||||
|
resolve-from "^5.0.0"
|
||||||
|
slash "^3.0.0"
|
||||||
|
slugify "^1.3.4"
|
||||||
|
xcode "^3.0.1"
|
||||||
|
xml2js "^0.4.23"
|
||||||
|
|
||||||
"@expo/config-types@^40.0.0-beta.2":
|
"@expo/config-types@^40.0.0-beta.2":
|
||||||
version "40.0.0-beta.2"
|
version "40.0.0-beta.2"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-40.0.0-beta.2.tgz#4fea4ef5654d02218b02b0b3772529a9ce5b0471"
|
resolved "https://registry.yarnpkg.com/@expo/config-types/-/config-types-40.0.0-beta.2.tgz#4fea4ef5654d02218b02b0b3772529a9ce5b0471"
|
||||||
integrity sha512-t9pHCQMXOP4nwd7LGXuHkLlFy0JdfknRSCAeVF4Kw2/y+5OBbR9hW9ZVnetpBf0kORrekgiI7K/qDaa3hh5+Qg==
|
integrity sha512-t9pHCQMXOP4nwd7LGXuHkLlFy0JdfknRSCAeVF4Kw2/y+5OBbR9hW9ZVnetpBf0kORrekgiI7K/qDaa3hh5+Qg==
|
||||||
|
|
||||||
"@expo/config@3.3.34", "@expo/config@^3.3.18":
|
"@expo/config@3.3.34":
|
||||||
version "3.3.34"
|
version "3.3.34"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/config/-/config-3.3.34.tgz#ab8cab4c04a406cc92ed483f7a7f071e8e0f3e98"
|
resolved "https://registry.yarnpkg.com/@expo/config/-/config-3.3.34.tgz#ab8cab4c04a406cc92ed483f7a7f071e8e0f3e98"
|
||||||
integrity sha512-Yekmn9sIm70vGUwugXlL/jpTQufTJXV7IrYWvFKd4B8ZwdMBFK08NY2XBwvl+jJOVdhmLe+yHc44bCmrEPb6vA==
|
integrity sha512-Yekmn9sIm70vGUwugXlL/jpTQufTJXV7IrYWvFKd4B8ZwdMBFK08NY2XBwvl+jJOVdhmLe+yHc44bCmrEPb6vA==
|
||||||
@@ -1422,6 +1442,26 @@
|
|||||||
semver "7.3.2"
|
semver "7.3.2"
|
||||||
slugify "^1.3.4"
|
slugify "^1.3.4"
|
||||||
|
|
||||||
|
"@expo/config@3.3.39", "@expo/config@^3.3.35":
|
||||||
|
version "3.3.39"
|
||||||
|
resolved "https://registry.yarnpkg.com/@expo/config/-/config-3.3.39.tgz#c5b02544aa6f1c4efb208f34fdee062d42e092e8"
|
||||||
|
integrity sha512-xT+OeMSeKrX+OtOs15Plvr8YIsfUfyT+ofpSxzMuAHQ4ivbhR5bIW7XcJTwg4ie3GUTatraoDUYz84TLoirKaA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/core" "7.9.0"
|
||||||
|
"@babel/plugin-proposal-class-properties" "~7.12.13"
|
||||||
|
"@babel/preset-env" "~7.12.13"
|
||||||
|
"@babel/preset-typescript" "~7.12.13"
|
||||||
|
"@expo/config-plugins" "1.0.29"
|
||||||
|
"@expo/config-types" "^40.0.0-beta.2"
|
||||||
|
"@expo/json-file" "8.2.29"
|
||||||
|
fs-extra "9.0.0"
|
||||||
|
getenv "^1.0.0"
|
||||||
|
glob "7.1.6"
|
||||||
|
require-from-string "^2.0.2"
|
||||||
|
resolve-from "^5.0.0"
|
||||||
|
semver "7.3.2"
|
||||||
|
slugify "^1.3.4"
|
||||||
|
|
||||||
"@expo/configure-splash-screen@0.3.4":
|
"@expo/configure-splash-screen@0.3.4":
|
||||||
version "0.3.4"
|
version "0.3.4"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/configure-splash-screen/-/configure-splash-screen-0.3.4.tgz#b91d8f08fd96272bd3d7aaa9b51d6189b932c7cc"
|
resolved "https://registry.yarnpkg.com/@expo/configure-splash-screen/-/configure-splash-screen-0.3.4.tgz#b91d8f08fd96272bd3d7aaa9b51d6189b932c7cc"
|
||||||
@@ -1438,24 +1478,24 @@
|
|||||||
xcode "^3.0.0"
|
xcode "^3.0.0"
|
||||||
xml-js "^1.6.11"
|
xml-js "^1.6.11"
|
||||||
|
|
||||||
"@expo/dev-server@0.1.60":
|
"@expo/dev-server@0.1.65":
|
||||||
version "0.1.60"
|
version "0.1.65"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/dev-server/-/dev-server-0.1.60.tgz#eb88f5c52e2617611a41325089a3fb516e3d813d"
|
resolved "https://registry.yarnpkg.com/@expo/dev-server/-/dev-server-0.1.65.tgz#e20ff69786c9f0a39156a920a2ffdc328686a193"
|
||||||
integrity sha512-tm+l8enWZ//2nst6s91V+29KwXlA69bFhG6b50lTXfY++7Q0OaOsDoGl3cQaWHKo2K3MQ/7C8riIGf7q6T5wjg==
|
integrity sha512-3N2omGlKQrvcU2T/LmtWf+YoQc6yGwFHlikdy1Zh+Z1DBI0rnXPb4YSie3a7k9iBhZlXbCWp2AmzxRRUiQKoMg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@expo/bunyan" "4.0.0"
|
"@expo/bunyan" "4.0.0"
|
||||||
"@expo/metro-config" "0.1.60"
|
"@expo/metro-config" "0.1.65"
|
||||||
"@react-native-community/cli-server-api" "4.9.0"
|
"@react-native-community/cli-server-api" "4.9.0"
|
||||||
body-parser "1.19.0"
|
body-parser "1.19.0"
|
||||||
resolve-from "^5.0.0"
|
resolve-from "^5.0.0"
|
||||||
serialize-error "6.0.0"
|
serialize-error "6.0.0"
|
||||||
|
|
||||||
"@expo/dev-tools@0.13.89":
|
"@expo/dev-tools@0.13.95":
|
||||||
version "0.13.89"
|
version "0.13.95"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/dev-tools/-/dev-tools-0.13.89.tgz#743d8d496a94abb6f55c4c01e4dc1fbf3f91aa25"
|
resolved "https://registry.yarnpkg.com/@expo/dev-tools/-/dev-tools-0.13.95.tgz#62f3655cf4fc12c59ed969399a79bc6417521290"
|
||||||
integrity sha512-8qlcd46x5CJU2VR+IL3MoHY0eScLe9Io2ibzvuFK+7kNP3gQle/LU+biAKtWIfUVlp4+xzEaAiDc202RTtHhqA==
|
integrity sha512-g75GOKTfhaZsPSQw7uHHhObwmkZHb9DPtg5/ptDfwzt7FEkvU10gLvepin6dfwOnzTZ1M/HMKMExxa68FCav7Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@expo/config" "3.3.34"
|
"@expo/config" "3.3.39"
|
||||||
base64url "3.0.1"
|
base64url "3.0.1"
|
||||||
express "4.16.4"
|
express "4.16.4"
|
||||||
freeport-async "2.0.0"
|
freeport-async "2.0.0"
|
||||||
@@ -1501,6 +1541,23 @@
|
|||||||
semver "7.3.2"
|
semver "7.3.2"
|
||||||
tempy "0.3.0"
|
tempy "0.3.0"
|
||||||
|
|
||||||
|
"@expo/image-utils@0.3.13":
|
||||||
|
version "0.3.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/@expo/image-utils/-/image-utils-0.3.13.tgz#cba070a61ce89e6c113b8e6afd5655cb83da6377"
|
||||||
|
integrity sha512-BpKoFVJBjG9H5AU040Skrm3R2uDGpWXBU/4TivB5H10cyJphoJKp3GNJVPHYLOVc70OtAxjWDIhLMW6xsWfrgw==
|
||||||
|
dependencies:
|
||||||
|
"@expo/spawn-async" "1.5.0"
|
||||||
|
chalk "^4.0.0"
|
||||||
|
fs-extra "9.0.0"
|
||||||
|
getenv "^1.0.0"
|
||||||
|
jimp "0.12.1"
|
||||||
|
mime "^2.4.4"
|
||||||
|
node-fetch "^2.6.0"
|
||||||
|
parse-png "^2.1.0"
|
||||||
|
resolve-from "^5.0.0"
|
||||||
|
semver "7.3.2"
|
||||||
|
tempy "0.3.0"
|
||||||
|
|
||||||
"@expo/json-file@8.2.28":
|
"@expo/json-file@8.2.28":
|
||||||
version "8.2.28"
|
version "8.2.28"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.2.28.tgz#9218bb70ad12d8be03c6376990b01fbeb4a15b72"
|
resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.2.28.tgz#9218bb70ad12d8be03c6376990b01fbeb4a15b72"
|
||||||
@@ -1511,7 +1568,27 @@
|
|||||||
json5 "^1.0.1"
|
json5 "^1.0.1"
|
||||||
write-file-atomic "^2.3.0"
|
write-file-atomic "^2.3.0"
|
||||||
|
|
||||||
"@expo/metro-config@0.1.60", "@expo/metro-config@^0.1.59":
|
"@expo/json-file@8.2.29":
|
||||||
|
version "8.2.29"
|
||||||
|
resolved "https://registry.yarnpkg.com/@expo/json-file/-/json-file-8.2.29.tgz#5e66c4c1dc531a583fe654d99fe417246d91741d"
|
||||||
|
integrity sha512-9C8XwpJiJN9fyClnnNDSTh034zJU9hon6MCUqbBa4dZYQN7OZ00KFZEpbtjy+FndE7YD+KagDxRD6O1HS5vU0g==
|
||||||
|
dependencies:
|
||||||
|
"@babel/code-frame" "~7.10.4"
|
||||||
|
fs-extra "9.0.0"
|
||||||
|
json5 "^1.0.1"
|
||||||
|
write-file-atomic "^2.3.0"
|
||||||
|
|
||||||
|
"@expo/metro-config@0.1.65", "@expo/metro-config@^0.1.63":
|
||||||
|
version "0.1.65"
|
||||||
|
resolved "https://registry.yarnpkg.com/@expo/metro-config/-/metro-config-0.1.65.tgz#95bd4f265def2edca6d229e3860d933425045d83"
|
||||||
|
integrity sha512-iREEn0RXueAUAuiu0Z4ECxed2UhEkI0KZD2avRggEmCBdDS6uo4TgfFo/2pmMLfXv56nS0wRmtB6o3SqUcgh3g==
|
||||||
|
dependencies:
|
||||||
|
"@expo/config" "3.3.39"
|
||||||
|
chalk "^4.1.0"
|
||||||
|
getenv "^1.0.0"
|
||||||
|
metro-react-native-babel-transformer "^0.59.0"
|
||||||
|
|
||||||
|
"@expo/metro-config@^0.1.59":
|
||||||
version "0.1.60"
|
version "0.1.60"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/metro-config/-/metro-config-0.1.60.tgz#43b2bf4d5e00a02a700f756f7ae6bbd9e755e124"
|
resolved "https://registry.yarnpkg.com/@expo/metro-config/-/metro-config-0.1.60.tgz#43b2bf4d5e00a02a700f756f7ae6bbd9e755e124"
|
||||||
integrity sha512-aA/UMZ5ga1QfF9pN1rYvwTg7ez/Ptz6vSFWyOdYM00X+egKlQFDwe8UuMKiUZUHaLFJ3XbixMLTIvDVdnVxk7w==
|
integrity sha512-aA/UMZ5ga1QfF9pN1rYvwTg7ez/Ptz6vSFWyOdYM00X+egKlQFDwe8UuMKiUZUHaLFJ3XbixMLTIvDVdnVxk7w==
|
||||||
@@ -1521,20 +1598,20 @@
|
|||||||
getenv "^1.0.0"
|
getenv "^1.0.0"
|
||||||
metro-react-native-babel-transformer "^0.59.0"
|
metro-react-native-babel-transformer "^0.59.0"
|
||||||
|
|
||||||
"@expo/osascript@2.0.25":
|
"@expo/osascript@2.0.27":
|
||||||
version "2.0.25"
|
version "2.0.27"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/osascript/-/osascript-2.0.25.tgz#bd88b08ba4c32c09a349c66745ec60d34f0f55f9"
|
resolved "https://registry.yarnpkg.com/@expo/osascript/-/osascript-2.0.27.tgz#738fa409e4bff1288c0cf29bb6606fbf130ff0b1"
|
||||||
integrity sha512-rB+RLHCp72q0OBWmisoBswfTpyzc91OJMs3UQVWJP9mXVNJhemONt7PKjE+FinBm33uH1HCC6U7JPGigpVsJBg==
|
integrity sha512-q2fh4EuegZkr48v8lvZSQdCRhHbtoBJ3CUpmipVjAXJ+jMJGwwCcZvGpE57N5ODxCTKi5RP0NiEfFAfEnpGnQw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@expo/spawn-async" "^1.5.0"
|
"@expo/spawn-async" "^1.5.0"
|
||||||
exec-async "^2.2.0"
|
exec-async "^2.2.0"
|
||||||
|
|
||||||
"@expo/package-manager@0.0.39":
|
"@expo/package-manager@0.0.42":
|
||||||
version "0.0.39"
|
version "0.0.42"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/package-manager/-/package-manager-0.0.39.tgz#6cf7458af198184e5c4dbcf73546f581bc328ae4"
|
resolved "https://registry.yarnpkg.com/@expo/package-manager/-/package-manager-0.0.42.tgz#6b33854ee72c3936010c6527b6aafc731d8f12c0"
|
||||||
integrity sha512-2KSx1jjdDmWsnkZfWZL4TwveeIyAcORQna5VOZdd+sBalK8taMtPQEdchwAGD4mOFsFFPmpbQHwboRfXoSlbOQ==
|
integrity sha512-8237/Gpz1NvcWv+Ja2ytMaVxgVPiiiai8wjvyGSvD0GWm3vUm66qi9lAN9m3EtfL0DvcwLIz0GYzleM8mOSxXw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@expo/json-file" "8.2.28"
|
"@expo/json-file" "8.2.29"
|
||||||
"@expo/spawn-async" "^1.5.0"
|
"@expo/spawn-async" "^1.5.0"
|
||||||
ansi-regex "^5.0.0"
|
ansi-regex "^5.0.0"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
@@ -1558,10 +1635,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@expo/results/-/results-1.0.0.tgz#fd4b22f936ceafce23b04799f54b87fe2a9e18d1"
|
resolved "https://registry.yarnpkg.com/@expo/results/-/results-1.0.0.tgz#fd4b22f936ceafce23b04799f54b87fe2a9e18d1"
|
||||||
integrity sha512-qECzzXX5oJot3m2Gu9pfRDz50USdBieQVwYAzeAtQRUTD3PVeTK1tlRUoDcrK8PSruDLuVYdKkLebX4w/o55VA==
|
integrity sha512-qECzzXX5oJot3m2Gu9pfRDz50USdBieQVwYAzeAtQRUTD3PVeTK1tlRUoDcrK8PSruDLuVYdKkLebX4w/o55VA==
|
||||||
|
|
||||||
"@expo/schemer@1.3.27":
|
"@expo/schemer@1.3.28":
|
||||||
version "1.3.27"
|
version "1.3.28"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/schemer/-/schemer-1.3.27.tgz#55d7e7a28bfbd4eca26f59306e305cc5fc8b33e0"
|
resolved "https://registry.yarnpkg.com/@expo/schemer/-/schemer-1.3.28.tgz#3ad544f3c1b61bea9dda0ec5d195002b70d8a3ca"
|
||||||
integrity sha512-cuCvSo6qErgK7OOM8CoCtCsVifq+WX1wUCeu+fmSyhnZcqnz45ZTK20Ghk5bT3OrTNQipbTiCjn9RCDrkEMMkg==
|
integrity sha512-9wmnhlD1X1ro8FTFzM/J3nSxaFpI9X+bcaimP3hKkc3flIR8cGjQcLmE+MOEgE2LET0ScxRBtM3hteernFI6Ww==
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv "^5.2.2"
|
ajv "^5.2.2"
|
||||||
json-schema-traverse "0.3.1"
|
json-schema-traverse "0.3.1"
|
||||||
@@ -1593,7 +1670,47 @@
|
|||||||
lodash.pick "^4.4.0"
|
lodash.pick "^4.4.0"
|
||||||
lodash.template "^4.5.0"
|
lodash.template "^4.5.0"
|
||||||
|
|
||||||
"@expo/webpack-config@0.12.64", "@expo/webpack-config@~0.12.63":
|
"@expo/webpack-config@0.12.69":
|
||||||
|
version "0.12.69"
|
||||||
|
resolved "https://registry.yarnpkg.com/@expo/webpack-config/-/webpack-config-0.12.69.tgz#e71da0c2a2db5fce0d940311a558d01cd01cd034"
|
||||||
|
integrity sha512-S/gJvzcsd0M6nHsjsVftQgazFwpmcOfAh2ryOTd6QTn5OL9tFsNXfWfP7gad+a+hJLKz43hEDAlJKljNgy9KDw==
|
||||||
|
dependencies:
|
||||||
|
"@babel/core" "7.9.0"
|
||||||
|
"@babel/runtime" "7.9.0"
|
||||||
|
"@expo/config" "3.3.39"
|
||||||
|
"@pmmmwh/react-refresh-webpack-plugin" "^0.3.3"
|
||||||
|
babel-loader "8.1.0"
|
||||||
|
chalk "^4.0.0"
|
||||||
|
clean-webpack-plugin "^3.0.0"
|
||||||
|
copy-webpack-plugin "~6.0.3"
|
||||||
|
css-loader "~3.6.0"
|
||||||
|
expo-pwa "0.0.75"
|
||||||
|
file-loader "~6.0.0"
|
||||||
|
find-yarn-workspace-root "~2.0.0"
|
||||||
|
getenv "^1.0.0"
|
||||||
|
html-loader "~1.1.0"
|
||||||
|
html-webpack-plugin "~4.3.0"
|
||||||
|
is-wsl "^2.0.0"
|
||||||
|
mini-css-extract-plugin "^0.5.0"
|
||||||
|
node-html-parser "^1.2.12"
|
||||||
|
optimize-css-assets-webpack-plugin "^5.0.3"
|
||||||
|
pnp-webpack-plugin "^1.5.0"
|
||||||
|
postcss-safe-parser "^4.0.2"
|
||||||
|
progress "^2.0.3"
|
||||||
|
react-dev-utils "~11.0.1"
|
||||||
|
react-refresh "^0.8.2"
|
||||||
|
semver "~7.3.2"
|
||||||
|
style-loader "~1.2.1"
|
||||||
|
terser-webpack-plugin "^3.0.6"
|
||||||
|
url-loader "~4.1.0"
|
||||||
|
webpack "4.43.0"
|
||||||
|
webpack-deep-scope-plugin "1.6.0"
|
||||||
|
webpack-manifest-plugin "~2.2.0"
|
||||||
|
webpackbar "^4.0.0"
|
||||||
|
workbox-webpack-plugin "^3.6.3"
|
||||||
|
worker-loader "^2.0.0"
|
||||||
|
|
||||||
|
"@expo/webpack-config@~0.12.63":
|
||||||
version "0.12.64"
|
version "0.12.64"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/webpack-config/-/webpack-config-0.12.64.tgz#0b44fa37416e765bb9ffe65399d0a40c0d3387f0"
|
resolved "https://registry.yarnpkg.com/@expo/webpack-config/-/webpack-config-0.12.64.tgz#0b44fa37416e765bb9ffe65399d0a40c0d3387f0"
|
||||||
integrity sha512-STR9ctDYG36JUIjgcGClvsi3ZU55lc2jtIxf04+0TN8IVYOCoYTF3P971zA1dd3En/q//CpgtKX/UAoimdlL9A==
|
integrity sha512-STR9ctDYG36JUIjgcGClvsi3ZU55lc2jtIxf04+0TN8IVYOCoYTF3P971zA1dd3En/q//CpgtKX/UAoimdlL9A==
|
||||||
@@ -1633,10 +1750,10 @@
|
|||||||
workbox-webpack-plugin "^3.6.3"
|
workbox-webpack-plugin "^3.6.3"
|
||||||
worker-loader "^2.0.0"
|
worker-loader "^2.0.0"
|
||||||
|
|
||||||
"@expo/xcpretty@^1.0.4":
|
"@expo/xcpretty@~2.0.1":
|
||||||
version "1.1.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@expo/xcpretty/-/xcpretty-1.1.1.tgz#2b5b1679f256449e13f25cebfc0dcf008b687b57"
|
resolved "https://registry.yarnpkg.com/@expo/xcpretty/-/xcpretty-2.0.1.tgz#2c912166ca50a88f710cfe3b6b441144f5df14a2"
|
||||||
integrity sha512-YospUT3y7tPheNCW0SgzbDM8KzipuWukW/qxJRX1MnlgVb1wnnsvtBrY0z/ndRCBMlZFVUu+FkNfI0qDKo8YiA==
|
integrity sha512-fyQbzvZpLiKpx68QDzeLlL1AtFhhEW35dqxIqb4QQ6e3iofu57NdWBQTmIAQzDOPcNNXUR9SFncu3M4iyWwQ7Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "7.10.4"
|
"@babel/code-frame" "7.10.4"
|
||||||
chalk "^4.1.0"
|
chalk "^4.1.0"
|
||||||
@@ -3256,11 +3373,16 @@
|
|||||||
sudo-prompt "^9.0.0"
|
sudo-prompt "^9.0.0"
|
||||||
wcwidth "^1.0.1"
|
wcwidth "^1.0.1"
|
||||||
|
|
||||||
"@react-native-masked-view/masked-view@0.2.3", "@react-native-masked-view/masked-view@^0.2.3":
|
"@react-native-masked-view/masked-view@^0.2.3":
|
||||||
version "0.2.3"
|
version "0.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/@react-native-masked-view/masked-view/-/masked-view-0.2.3.tgz#5f7a39be4787c89d5b35ac80de2ea5d0a0bb64d7"
|
resolved "https://registry.yarnpkg.com/@react-native-masked-view/masked-view/-/masked-view-0.2.3.tgz#5f7a39be4787c89d5b35ac80de2ea5d0a0bb64d7"
|
||||||
integrity sha512-t8VcdaFbyXscNs26h/NCsPqVjawWHhIMzGBR9oCIx6kbDa7JW3Q67lNLGkzDudSVnw3Qv09JZrkLXXOGjOABpg==
|
integrity sha512-t8VcdaFbyXscNs26h/NCsPqVjawWHhIMzGBR9oCIx6kbDa7JW3Q67lNLGkzDudSVnw3Qv09JZrkLXXOGjOABpg==
|
||||||
|
|
||||||
|
"@react-native-masked-view/masked-view@~0.2.4":
|
||||||
|
version "0.2.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@react-native-masked-view/masked-view/-/masked-view-0.2.4.tgz#305a548abd47dee494a38f90016432d3a6e4164c"
|
||||||
|
integrity sha512-2Y9OXWHRutYmdyW+bNMaFTW8uTBpaaK20xdIFoVtqahEOO9++B+ut3CAWKPZcdRtb9ikG0LUKChGqMeocg0PGA==
|
||||||
|
|
||||||
"@segment/loosely-validate-event@^2.0.0":
|
"@segment/loosely-validate-event@^2.0.0":
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz#87dfc979e5b4e7b82c5f1d8b722dfd5d77644681"
|
resolved "https://registry.yarnpkg.com/@segment/loosely-validate-event/-/loosely-validate-event-2.0.0.tgz#87dfc979e5b4e7b82c5f1d8b722dfd5d77644681"
|
||||||
@@ -3677,13 +3799,20 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react-native@~0.63.2", "@types/react-native@~0.63.51":
|
"@types/react-native@~0.63.2":
|
||||||
version "0.63.52"
|
version "0.63.52"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.63.52.tgz#449beb4a413ec0f2c172cbf676a95f5b0952adf4"
|
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.63.52.tgz#449beb4a413ec0f2c172cbf676a95f5b0952adf4"
|
||||||
integrity sha512-sBXvvtJaIUSXQLDh9NZitx1KHkKUdBLZy34lFKJaIXtpHIh5OEbBXeyUTFBtFwjk/RD0tneAtUqsdhheZRzAzw==
|
integrity sha512-sBXvvtJaIUSXQLDh9NZitx1KHkKUdBLZy34lFKJaIXtpHIh5OEbBXeyUTFBtFwjk/RD0tneAtUqsdhheZRzAzw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
|
|
||||||
|
"@types/react-native@~0.64.4":
|
||||||
|
version "0.64.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/react-native/-/react-native-0.64.4.tgz#9f11bef7dd5520801884829c73b19d75aa42e73c"
|
||||||
|
integrity sha512-VqnlmadGkD5usREvnuyVpWDS1W8f6cCz6MP5fZdgONsaZ9/Ijfb9Iq9MZ5O3bnW1OyJixDX9HtSp3COsFSLD8Q==
|
||||||
|
dependencies:
|
||||||
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react@*":
|
"@types/react@*":
|
||||||
version "17.0.3"
|
version "17.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.3.tgz#ba6e215368501ac3826951eef2904574c262cc79"
|
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.3.tgz#ba6e215368501ac3826951eef2904574c262cc79"
|
||||||
@@ -3755,11 +3884,6 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.7.tgz#545158342f949e8fd3bfd813224971ecddc3fac4"
|
resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.7.tgz#545158342f949e8fd3bfd813224971ecddc3fac4"
|
||||||
integrity sha512-0VBprVqfgFD7Ehb2vd8Lh9TG3jP98gvr8rgehQqzztZNI7o8zS8Ad4jyZneKELphpuE212D8J70LnSNQSyO6bQ==
|
integrity sha512-0VBprVqfgFD7Ehb2vd8Lh9TG3jP98gvr8rgehQqzztZNI7o8zS8Ad4jyZneKELphpuE212D8J70LnSNQSyO6bQ==
|
||||||
|
|
||||||
"@types/text-table@^0.2.1":
|
|
||||||
version "0.2.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/text-table/-/text-table-0.2.1.tgz#39c4d4a058a82f677392dfd09976e83d9b4c9264"
|
|
||||||
integrity sha512-dchbFCWfVgUSWEvhOkXGS7zjm+K7jCUvGrQkAHPk2Fmslfofp4HQTH2pqnQ3Pw5GPYv0zWa2AQjKtsfZThuemQ==
|
|
||||||
|
|
||||||
"@types/uglify-js@*":
|
"@types/uglify-js@*":
|
||||||
version "3.13.0"
|
version "3.13.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.13.0.tgz#1cad8df1fb0b143c5aba08de5712ea9d1ff71124"
|
resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.13.0.tgz#1cad8df1fb0b143c5aba08de5712ea9d1ff71124"
|
||||||
@@ -3896,13 +4020,12 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
compare-versions "^3.4.0"
|
compare-versions "^3.4.0"
|
||||||
|
|
||||||
"@unimodules/react-native-adapter@~6.2.1":
|
"@unimodules/react-native-adapter@~6.2.2":
|
||||||
version "6.2.1"
|
version "6.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/@unimodules/react-native-adapter/-/react-native-adapter-6.2.1.tgz#e944bca491aee79bdef68b5d70f9534b79e7a785"
|
resolved "https://registry.yarnpkg.com/@unimodules/react-native-adapter/-/react-native-adapter-6.2.2.tgz#0b76af76589ec5ff2c52f274e40ed609e91c5e4c"
|
||||||
integrity sha512-dVg0FnaH04VvLr6hRPQJuFoiTQhR1RgShjtm1w/vndAGK4CJ1oerLSBL+p887UFmNTk/NSMLkcbdS1ZIRH06Rg==
|
integrity sha512-hBXL+IX3u+4TcAHu9lIItdycA7pYWZn3Tt7s5TTna9QKHjyrwo0zVss27LkpJ40tXRHyh/GJ8VzN2CD+0M5I2A==
|
||||||
dependencies:
|
dependencies:
|
||||||
invariant "^2.2.4"
|
invariant "^2.2.4"
|
||||||
lodash "^4.5.0"
|
|
||||||
|
|
||||||
"@webassemblyjs/ast@1.9.0":
|
"@webassemblyjs/ast@1.9.0":
|
||||||
version "1.9.0"
|
version "1.9.0"
|
||||||
@@ -5508,14 +5631,6 @@ callsites@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||||
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
||||||
|
|
||||||
camel-case@^3.0.0:
|
|
||||||
version "3.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73"
|
|
||||||
integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=
|
|
||||||
dependencies:
|
|
||||||
no-case "^2.2.0"
|
|
||||||
upper-case "^1.1.1"
|
|
||||||
|
|
||||||
camel-case@^4.1.1:
|
camel-case@^4.1.1:
|
||||||
version "4.1.2"
|
version "4.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a"
|
resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a"
|
||||||
@@ -7996,10 +8111,10 @@ expect@^26.6.2:
|
|||||||
jest-message-util "^26.6.2"
|
jest-message-util "^26.6.2"
|
||||||
jest-regex-util "^26.0.0"
|
jest-regex-util "^26.0.0"
|
||||||
|
|
||||||
expo-application@~3.1.0:
|
expo-application@~3.1.2:
|
||||||
version "3.1.0"
|
version "3.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/expo-application/-/expo-application-3.1.0.tgz#7c04b31a202ac24d60a00982276cbe8b2fb87e34"
|
resolved "https://registry.yarnpkg.com/expo-application/-/expo-application-3.1.2.tgz#7c93e8108a7f2a0be0afe37151f36c98e0111e7c"
|
||||||
integrity sha512-s/lLjkuBf9TnfSANPgOJe+T2xB+Nztl+vyjyBhoeLgxo4E7YQRHqKFofwHnQJ308suOAB5vt0MI87EgFgnSR/Q==
|
integrity sha512-JZcKUpGmqzQ1zLxRxUditGzPqnPCXY6JT/Pbq4nyV4VPzjDd8wihVPuud+cuv8gHgdj8QLvKs/lcJJqN94EX5Q==
|
||||||
|
|
||||||
expo-asset@~8.3.1:
|
expo-asset@~8.3.1:
|
||||||
version "8.3.1"
|
version "8.3.1"
|
||||||
@@ -8017,33 +8132,33 @@ expo-blur@~9.0.3:
|
|||||||
resolved "https://registry.yarnpkg.com/expo-blur/-/expo-blur-9.0.3.tgz#5095b5bd04d000f73b351d0e4736767b86b49bbd"
|
resolved "https://registry.yarnpkg.com/expo-blur/-/expo-blur-9.0.3.tgz#5095b5bd04d000f73b351d0e4736767b86b49bbd"
|
||||||
integrity sha512-7jMqzo53eg5t9Uc1Tg+yGu9lKL9the4CWAQO0kC6YMhrsDiB13mwOUesC+IScHDTSUKNMGcHI8kN+OmvEWfPig==
|
integrity sha512-7jMqzo53eg5t9Uc1Tg+yGu9lKL9the4CWAQO0kC6YMhrsDiB13mwOUesC+IScHDTSUKNMGcHI8kN+OmvEWfPig==
|
||||||
|
|
||||||
expo-cli@^4.3.4:
|
expo-cli@^4.4.4:
|
||||||
version "4.3.4"
|
version "4.4.4"
|
||||||
resolved "https://registry.yarnpkg.com/expo-cli/-/expo-cli-4.3.4.tgz#54af9c9f6cb91096a73583f189a2f01fb3c74127"
|
resolved "https://registry.yarnpkg.com/expo-cli/-/expo-cli-4.4.4.tgz#6ddc3ebba6c7cf82dd620df328dc8f3fba8f73d6"
|
||||||
integrity sha512-feD7OAnzf7PKZgi4VpEpkuI8TYdplPaQVILoS+6ejMLvjjgDOTPh9Tn47xdox35Q3S1VPWS6qivNvOXjhUNDDQ==
|
integrity sha512-bQN+XxZYoJnSY3fCNSBAZ1ChZEhHOmv5KhwNmPa/Tc2/IPRFCzdopNGf+Uf5FrpjDex/UqewjVrAkb4Ak4/1Hg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@expo/apple-utils" "0.0.0-alpha.17"
|
"@expo/apple-utils" "0.0.0-alpha.17"
|
||||||
"@expo/bunyan" "4.0.0"
|
"@expo/bunyan" "4.0.0"
|
||||||
"@expo/config" "3.3.34"
|
"@expo/config" "3.3.39"
|
||||||
"@expo/config-plugins" "1.0.24"
|
"@expo/config-plugins" "1.0.29"
|
||||||
"@expo/dev-tools" "0.13.89"
|
"@expo/dev-tools" "0.13.95"
|
||||||
"@expo/json-file" "8.2.28"
|
"@expo/json-file" "8.2.29"
|
||||||
"@expo/osascript" "2.0.25"
|
"@expo/osascript" "2.0.27"
|
||||||
"@expo/package-manager" "0.0.39"
|
"@expo/package-manager" "0.0.42"
|
||||||
"@expo/plist" "0.0.12"
|
"@expo/plist" "0.0.12"
|
||||||
"@expo/results" "^1.0.0"
|
"@expo/results" "^1.0.0"
|
||||||
"@expo/simple-spinner" "1.0.2"
|
"@expo/simple-spinner" "1.0.2"
|
||||||
"@expo/spawn-async" "1.5.0"
|
"@expo/spawn-async" "1.5.0"
|
||||||
"@expo/xcpretty" "^1.0.4"
|
"@expo/xcpretty" "~2.0.1"
|
||||||
"@hapi/joi" "^17.1.1"
|
"@hapi/joi" "^17.1.1"
|
||||||
babel-runtime "6.26.0"
|
babel-runtime "6.26.0"
|
||||||
base32.js "0.1.0"
|
base32.js "0.1.0"
|
||||||
boxen "4.1.0"
|
boxen "4.1.0"
|
||||||
|
bplist-parser "0.2.0"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
cli-table3 "^0.6.0"
|
cli-table3 "^0.6.0"
|
||||||
command-exists "^1.2.8"
|
command-exists "^1.2.8"
|
||||||
commander "2.17.1"
|
commander "2.17.1"
|
||||||
concat-stream "1.6.2"
|
|
||||||
dateformat "3.0.3"
|
dateformat "3.0.3"
|
||||||
env-editor "^0.4.1"
|
env-editor "^0.4.1"
|
||||||
envinfo "7.5.0"
|
envinfo "7.5.0"
|
||||||
@@ -8072,6 +8187,7 @@ expo-cli@^4.3.4:
|
|||||||
react-dev-utils "~11.0.1"
|
react-dev-utils "~11.0.1"
|
||||||
read-last-lines "1.6.0"
|
read-last-lines "1.6.0"
|
||||||
semver "7.3.2"
|
semver "7.3.2"
|
||||||
|
slugify "^1.3.4"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
tar "^6.0.5"
|
tar "^6.0.5"
|
||||||
tempy "^0.7.1"
|
tempy "^0.7.1"
|
||||||
@@ -8081,15 +8197,14 @@ expo-cli@^4.3.4:
|
|||||||
url-join "4.0.0"
|
url-join "4.0.0"
|
||||||
uuid "^8.0.0"
|
uuid "^8.0.0"
|
||||||
wrap-ansi "^7.0.0"
|
wrap-ansi "^7.0.0"
|
||||||
xcode "^3.0.1"
|
xdl "59.0.35"
|
||||||
xdl "59.0.29"
|
|
||||||
|
|
||||||
expo-constants@~10.1.1:
|
expo-constants@~10.1.3:
|
||||||
version "10.1.1"
|
version "10.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/expo-constants/-/expo-constants-10.1.1.tgz#1cdf8c23c63bc3923da199d608037ae845361dd9"
|
resolved "https://registry.yarnpkg.com/expo-constants/-/expo-constants-10.1.3.tgz#dfbe30362d27d6f500318eb528621424034b72d5"
|
||||||
integrity sha512-sj8NgtJ97hh8HempI1z9Eo2nYFPV2PdjmmflvZLUBKbxqU4k+9+FiE6aTKNb23LsdbadZu2D/hzXT0pDub/GdQ==
|
integrity sha512-Eq/xeshnhSoe4ok89d5lrHvI9jq3bMe1FhJUbiHVGcGmW8mGCotwbQBIfDkkMrAKnSOwQq/Qfyg0XBxnG2XFjw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@expo/config" "^3.3.18"
|
"@expo/config" "^3.3.35"
|
||||||
uuid "^3.3.2"
|
uuid "^3.3.2"
|
||||||
|
|
||||||
expo-error-recovery@~2.1.0:
|
expo-error-recovery@~2.1.0:
|
||||||
@@ -8097,10 +8212,10 @@ expo-error-recovery@~2.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/expo-error-recovery/-/expo-error-recovery-2.1.0.tgz#7baf6cabc53162cdd2b36edb20b8aa6d1cdc1107"
|
resolved "https://registry.yarnpkg.com/expo-error-recovery/-/expo-error-recovery-2.1.0.tgz#7baf6cabc53162cdd2b36edb20b8aa6d1cdc1107"
|
||||||
integrity sha512-N5g2QKtdNntUNGQVnB/tG1jHdtJP1+kLMWDS+7ZKRcKfulm3JX/M3l460fsEtqg84n/latxPkBT0yfKw2DSq+Q==
|
integrity sha512-N5g2QKtdNntUNGQVnB/tG1jHdtJP1+kLMWDS+7ZKRcKfulm3JX/M3l460fsEtqg84n/latxPkBT0yfKw2DSq+Q==
|
||||||
|
|
||||||
expo-file-system@~11.0.0:
|
expo-file-system@~11.0.2:
|
||||||
version "11.0.0"
|
version "11.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/expo-file-system/-/expo-file-system-11.0.0.tgz#3a6d2f8a9ad4033fae2cabe1a2133372a90a4f20"
|
resolved "https://registry.yarnpkg.com/expo-file-system/-/expo-file-system-11.0.2.tgz#c3f9b9c6ba25456a0d32c7a9bb38e55310d471bd"
|
||||||
integrity sha512-SkJ3HwPLYoLFUR4w7KMvyhxRdCZcDsW/jeoUffGSh52wHs3+1OTKDMta4nQImeiWGZvXsOJ1KyJ+WubRxAgtMg==
|
integrity sha512-nodNvUVa+US4N4xnj5BFw8W9ZF/qCHJVC2t45cHWrBiwkVVxz45wjE7uSHUmkMWyWT7a/7AJuL3XJfYp7h90IQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@expo/config-plugins" "^1.0.18"
|
"@expo/config-plugins" "^1.0.18"
|
||||||
uuid "^3.4.0"
|
uuid "^3.4.0"
|
||||||
@@ -8112,17 +8227,17 @@ expo-font@~9.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fontfaceobserver "^2.1.0"
|
fontfaceobserver "^2.1.0"
|
||||||
|
|
||||||
expo-keep-awake@~9.1.1:
|
expo-keep-awake@~9.1.2:
|
||||||
version "9.1.1"
|
version "9.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-9.1.1.tgz#d56d520ae62bc22b9178afacaafea73a1adc89cf"
|
resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-9.1.2.tgz#b3e52c7bef0ade975ae88637a2bf980f6b573368"
|
||||||
integrity sha512-2NLUN/be9gjsvk0SF0ArA5omzUUIiVc/cMLfHdb/YnGGzBmNNGYOg9x/4iMzzASuKblttzT3iaf0uqgBqCxM6Q==
|
integrity sha512-CCuEOQUNLYtMA0rt0sQ9u5LlIMH7lDJG7dImoorfKMsP95yHXy8dl3oCdtaz2zbsPgggVYeom9gE+gQu+Ki4rQ==
|
||||||
|
|
||||||
expo-linking@~2.2.1:
|
expo-linking@~2.2.3:
|
||||||
version "2.2.1"
|
version "2.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/expo-linking/-/expo-linking-2.2.1.tgz#9365ea80be10016ac8b88ec49784c413b921beac"
|
resolved "https://registry.yarnpkg.com/expo-linking/-/expo-linking-2.2.3.tgz#925584a0ed7a617065fe92a39ba4509f70972664"
|
||||||
integrity sha512-/6kjAJId/v4b4qgkH+VT1e2GuBK5KonUO++FdxaK6UC4X0mdZIsWZfFCTqEARWKISedaLMT5v1+DQQRkiVj6cw==
|
integrity sha512-1NqL8sY4EzwRPVnBxbvNKBCfsG/tNZm72tVwzjoLxhO0XA6VTtZcb72Jaku4IlqEyH0lejxV2YAU0rbLv1pAVA==
|
||||||
dependencies:
|
dependencies:
|
||||||
expo-constants "~10.1.1"
|
expo-constants "~10.1.3"
|
||||||
invariant "^2.2.4"
|
invariant "^2.2.4"
|
||||||
qs "^6.5.0"
|
qs "^6.5.0"
|
||||||
url-parse "^1.4.4"
|
url-parse "^1.4.4"
|
||||||
@@ -8138,15 +8253,26 @@ expo-pwa@0.0.70:
|
|||||||
commander "2.20.0"
|
commander "2.20.0"
|
||||||
update-check "1.5.3"
|
update-check "1.5.3"
|
||||||
|
|
||||||
|
expo-pwa@0.0.75:
|
||||||
|
version "0.0.75"
|
||||||
|
resolved "https://registry.yarnpkg.com/expo-pwa/-/expo-pwa-0.0.75.tgz#9511d9226aea2715007ab898ab28b74555b3ee28"
|
||||||
|
integrity sha512-EULfm5yg+xxluhj/qYZokUuFZKoarX8DTHFXNzW8+TlsL38n89PBR7okT5na7YpFEdAaOPTBNQEZZfN5O5tPHQ==
|
||||||
|
dependencies:
|
||||||
|
"@expo/config" "3.3.39"
|
||||||
|
"@expo/image-utils" "0.3.13"
|
||||||
|
chalk "^4.0.0"
|
||||||
|
commander "2.20.0"
|
||||||
|
update-check "1.5.3"
|
||||||
|
|
||||||
expo-structured-headers@~1.0.1:
|
expo-structured-headers@~1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/expo-structured-headers/-/expo-structured-headers-1.0.1.tgz#2f3117fc9480e01aa6705493d3213060c2dcf683"
|
resolved "https://registry.yarnpkg.com/expo-structured-headers/-/expo-structured-headers-1.0.1.tgz#2f3117fc9480e01aa6705493d3213060c2dcf683"
|
||||||
integrity sha512-U4frE8rT5x1LqZv5Ru/9CtzY8gh0wp1MfwTu5hetPydnwxXfWchuXvKgWRjEHglFU2X/29kYFY/J1UkPvCN8xg==
|
integrity sha512-U4frE8rT5x1LqZv5Ru/9CtzY8gh0wp1MfwTu5hetPydnwxXfWchuXvKgWRjEHglFU2X/29kYFY/J1UkPvCN8xg==
|
||||||
|
|
||||||
expo-updates@~0.5.3:
|
expo-updates@~0.5.4:
|
||||||
version "0.5.3"
|
version "0.5.4"
|
||||||
resolved "https://registry.yarnpkg.com/expo-updates/-/expo-updates-0.5.3.tgz#b8806260f84fb0bd4e2b276f797dc5fab536824d"
|
resolved "https://registry.yarnpkg.com/expo-updates/-/expo-updates-0.5.4.tgz#ee1b395fee701fb230e7ae28729f4d7055dd3514"
|
||||||
integrity sha512-BmTvD6qtSEArg4GUpFbGOfRddn2pL4waR1JhDkBl6Af0RdzkzzLDpxdPyr9cuRMg2iWhxpbHag0TaRNlBeuhiA==
|
integrity sha512-2lwvcBqZutUT4TwqPgTpcBuomjTHt781k1DjGKpf1lS9X/E4w1dgklESXfSASaTS84YuXfK/i6/7LjTWucCv/A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@expo/config-plugins" "^1.0.18"
|
"@expo/config-plugins" "^1.0.18"
|
||||||
"@expo/metro-config" "^0.1.59"
|
"@expo/metro-config" "^0.1.59"
|
||||||
@@ -8155,25 +8281,25 @@ expo-updates@~0.5.3:
|
|||||||
resolve-from "^5.0.0"
|
resolve-from "^5.0.0"
|
||||||
uuid "^3.4.0"
|
uuid "^3.4.0"
|
||||||
|
|
||||||
expo@^41.0.0-beta.2:
|
expo@^41.0.1:
|
||||||
version "41.0.0-beta.2"
|
version "41.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/expo/-/expo-41.0.0-beta.2.tgz#444702ade489b69bf6f396b9aa7eb255e76e81b1"
|
resolved "https://registry.yarnpkg.com/expo/-/expo-41.0.1.tgz#2689003212dcc948d010f86dadf055721a6314b4"
|
||||||
integrity sha512-TIr1VmV79SnpcUsWoiDPYtj6scFEuQwmZTkxkbf8fXO5nKsEXz8KMJfp2Lbo+n2Lv27LZ4wP0ZETQqHGWG9jRA==
|
integrity sha512-Lk4Xdst+OfsLgBNeu89hxk0qFrZnHwwXFmBbJkYLlZkdC3tvNJ8jgGHsKg6jYpsnal/z0uVc+uk2ev91qXQykg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.1.2"
|
"@babel/runtime" "^7.1.2"
|
||||||
"@expo/metro-config" "^0.1.59"
|
"@expo/metro-config" "^0.1.63"
|
||||||
"@expo/vector-icons" "^12.0.4"
|
"@expo/vector-icons" "^12.0.4"
|
||||||
"@unimodules/core" "~7.1.0"
|
"@unimodules/core" "~7.1.0"
|
||||||
"@unimodules/react-native-adapter" "~6.2.1"
|
"@unimodules/react-native-adapter" "~6.2.2"
|
||||||
babel-preset-expo "~8.3.0"
|
babel-preset-expo "~8.3.0"
|
||||||
cross-spawn "^6.0.5"
|
cross-spawn "^6.0.5"
|
||||||
expo-application "~3.1.0"
|
expo-application "~3.1.2"
|
||||||
expo-asset "~8.3.1"
|
expo-asset "~8.3.1"
|
||||||
expo-constants "~10.1.1"
|
expo-constants "~10.1.3"
|
||||||
expo-error-recovery "~2.1.0"
|
expo-error-recovery "~2.1.0"
|
||||||
expo-file-system "~11.0.0"
|
expo-file-system "~11.0.2"
|
||||||
expo-font "~9.1.0"
|
expo-font "~9.1.0"
|
||||||
expo-keep-awake "~9.1.1"
|
expo-keep-awake "~9.1.2"
|
||||||
fbemitter "^2.1.1"
|
fbemitter "^2.1.1"
|
||||||
invariant "^2.2.2"
|
invariant "^2.2.2"
|
||||||
md5-file "^3.2.3"
|
md5-file "^3.2.3"
|
||||||
@@ -9921,11 +10047,6 @@ imurmurhash@^0.1.4:
|
|||||||
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
|
||||||
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
|
||||||
|
|
||||||
indent-string@3.2.0:
|
|
||||||
version "3.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
|
|
||||||
integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=
|
|
||||||
|
|
||||||
indent-string@4.0.0, indent-string@^4.0.0:
|
indent-string@4.0.0, indent-string@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
|
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
|
||||||
@@ -11862,7 +11983,7 @@ lodash.uniq@^4.5.0:
|
|||||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||||
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
|
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
|
||||||
|
|
||||||
"lodash@>=3.5 <5", lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.5.0, lodash@^4.7.0:
|
"lodash@>=3.5 <5", lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0, lodash@^4.7.0:
|
||||||
version "4.17.21"
|
version "4.17.21"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||||
@@ -11903,11 +12024,6 @@ loud-rejection@^1.0.0:
|
|||||||
currently-unhandled "^0.4.1"
|
currently-unhandled "^0.4.1"
|
||||||
signal-exit "^3.0.0"
|
signal-exit "^3.0.0"
|
||||||
|
|
||||||
lower-case@^1.1.1:
|
|
||||||
version "1.1.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac"
|
|
||||||
integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw=
|
|
||||||
|
|
||||||
lower-case@^2.0.2:
|
lower-case@^2.0.2:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
|
resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
|
||||||
@@ -12864,7 +12980,7 @@ natural-compare@^1.4.0:
|
|||||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||||
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
||||||
|
|
||||||
ncp@2.0.0, ncp@~2.0.0:
|
ncp@~2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3"
|
resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3"
|
||||||
integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=
|
integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=
|
||||||
@@ -12898,13 +13014,6 @@ nice-try@^1.0.4:
|
|||||||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||||
|
|
||||||
no-case@^2.2.0:
|
|
||||||
version "2.3.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac"
|
|
||||||
integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==
|
|
||||||
dependencies:
|
|
||||||
lower-case "^1.1.1"
|
|
||||||
|
|
||||||
no-case@^3.0.4:
|
no-case@^3.0.4:
|
||||||
version "3.0.4"
|
version "3.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
|
resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
|
||||||
@@ -13909,14 +14018,6 @@ parseurl@^1.3.2, parseurl@~1.3.2, parseurl@~1.3.3:
|
|||||||
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
|
resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
|
||||||
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
|
integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
|
||||||
|
|
||||||
pascal-case@2.0.1:
|
|
||||||
version "2.0.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-2.0.1.tgz#2d578d3455f660da65eca18ef95b4e0de912761e"
|
|
||||||
integrity sha1-LVeNNFX2YNpl7KGO+VtODekSdh4=
|
|
||||||
dependencies:
|
|
||||||
camel-case "^3.0.0"
|
|
||||||
upper-case-first "^1.1.0"
|
|
||||||
|
|
||||||
pascal-case@^3.1.2:
|
pascal-case@^3.1.2:
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb"
|
resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb"
|
||||||
@@ -15165,9 +15266,9 @@ react-native-vector-icons@^8.1.0:
|
|||||||
yargs "^16.1.1"
|
yargs "^16.1.1"
|
||||||
|
|
||||||
react-native-web@~0.15.0:
|
react-native-web@~0.15.0:
|
||||||
version "0.15.5"
|
version "0.15.7"
|
||||||
resolved "https://registry.yarnpkg.com/react-native-web/-/react-native-web-0.15.5.tgz#6ad8d4553df080c9a9c30b63cffc7b41d0e076ec"
|
resolved "https://registry.yarnpkg.com/react-native-web/-/react-native-web-0.15.7.tgz#5b07d98032a36af3cb558357c7a1470e879fc422"
|
||||||
integrity sha512-SSXQfVJ8Zm5p633JM5QgkZ1BhZHqJEkRaSUa1BUzgzpMcqWX+XUFM0ZFwsRO5O9yd0wgi4yH89Da4qdoaCjoDw==
|
integrity sha512-mrbQayl1luIO4Gfyw6KLdlWc30JcJOQgRn84iOj6dLJYVRwcE6W5U2Af68hQYFJsGgVb9sdlYC0ppfFM7ywqXQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
array-find-index "^1.0.2"
|
array-find-index "^1.0.2"
|
||||||
create-react-class "^15.7.0"
|
create-react-class "^15.7.0"
|
||||||
@@ -15612,11 +15713,6 @@ repeating@^2.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-finite "^1.0.0"
|
is-finite "^1.0.0"
|
||||||
|
|
||||||
replace-string@1.1.0:
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/replace-string/-/replace-string-1.1.0.tgz#87062117f823fe5800c306bacb2cfa359b935fea"
|
|
||||||
integrity sha1-hwYhF/gj/lgAwwa6yyz6NZuTX+o=
|
|
||||||
|
|
||||||
request-promise-core@1.1.4:
|
request-promise-core@1.1.4:
|
||||||
version "1.1.4"
|
version "1.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f"
|
resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f"
|
||||||
@@ -16367,7 +16463,7 @@ slugid@1.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
uuid "^2.0.1"
|
uuid "^2.0.1"
|
||||||
|
|
||||||
slugify@^1.3.4, slugify@^1.3.6:
|
slugify@^1.3.4:
|
||||||
version "1.5.0"
|
version "1.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.5.0.tgz#5f3c8e2a84105b54eb51486db1b468a599b3c9b8"
|
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.5.0.tgz#5f3c8e2a84105b54eb51486db1b468a599b3c9b8"
|
||||||
integrity sha512-Q2UPZ2udzquy1ElHfOLILMBMqBEXkiD3wE75qtBvV+FsDdZZjUqPZ44vqLTejAVq+wLLHacOMcENnP8+ZbzmIA==
|
integrity sha512-Q2UPZ2udzquy1ElHfOLILMBMqBEXkiD3wE75qtBvV+FsDdZZjUqPZ44vqLTejAVq+wLLHacOMcENnP8+ZbzmIA==
|
||||||
@@ -17632,11 +17728,16 @@ typedarray@^0.0.6:
|
|||||||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||||
|
|
||||||
typescript@^4.2.3, typescript@~4.2.3:
|
typescript@^4.2.3:
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.3.tgz#39062d8019912d43726298f09493d598048c1ce3"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.3.tgz#39062d8019912d43726298f09493d598048c1ce3"
|
||||||
integrity sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==
|
integrity sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==
|
||||||
|
|
||||||
|
typescript@~4.2.3:
|
||||||
|
version "4.2.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961"
|
||||||
|
integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==
|
||||||
|
|
||||||
ua-parser-js@^0.7.18:
|
ua-parser-js@^0.7.18:
|
||||||
version "0.7.27"
|
version "0.7.27"
|
||||||
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.27.tgz#b54f8ce9eb6c7abf3584edeaf9a3d8b3bd92edba"
|
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.27.tgz#b54f8ce9eb6c7abf3584edeaf9a3d8b3bd92edba"
|
||||||
@@ -17856,18 +17957,6 @@ update-notifier@^4.1.0:
|
|||||||
semver-diff "^3.1.1"
|
semver-diff "^3.1.1"
|
||||||
xdg-basedir "^4.0.0"
|
xdg-basedir "^4.0.0"
|
||||||
|
|
||||||
upper-case-first@^1.1.0:
|
|
||||||
version "1.1.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-1.1.2.tgz#5d79bedcff14419518fd2edb0a0507c9b6859115"
|
|
||||||
integrity sha1-XXm+3P8UQZUY/S7bCgUHybaFkRU=
|
|
||||||
dependencies:
|
|
||||||
upper-case "^1.1.1"
|
|
||||||
|
|
||||||
upper-case@^1.1.1:
|
|
||||||
version "1.1.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598"
|
|
||||||
integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=
|
|
||||||
|
|
||||||
uri-js@^4.2.2:
|
uri-js@^4.2.2:
|
||||||
version "4.4.1"
|
version "4.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
|
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
|
||||||
@@ -18737,24 +18826,24 @@ xdg-basedir@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
|
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
|
||||||
integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
|
integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
|
||||||
|
|
||||||
xdl@59.0.29:
|
xdl@59.0.35:
|
||||||
version "59.0.29"
|
version "59.0.35"
|
||||||
resolved "https://registry.yarnpkg.com/xdl/-/xdl-59.0.29.tgz#ae2fa01dbf195d3e2d4f91cf6ad61277c4323fa7"
|
resolved "https://registry.yarnpkg.com/xdl/-/xdl-59.0.35.tgz#70f807e1c2930260563ca0169bca9f80abb6ef84"
|
||||||
integrity sha512-f593BX+PUoAy/Sz+OG6GFGhobKKWbi5nzW9Pph9RKZK3ovpiKc+dVX8zNY+bJxWCkgPCv7c11smb/8mOPsWAQA==
|
integrity sha512-nXVjmVKLA/Z+jxhXQm9ZFwaLPehbg0xxT0tW9IbeDVK/QqXbrX2UV/qHdTw9Qa95rxHqaccjX2qbPPgRQqa/Rg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@expo/bunyan" "4.0.0"
|
"@expo/bunyan" "4.0.0"
|
||||||
"@expo/config" "3.3.34"
|
"@expo/config" "3.3.39"
|
||||||
"@expo/dev-server" "0.1.60"
|
"@expo/config-plugins" "1.0.29"
|
||||||
|
"@expo/dev-server" "0.1.65"
|
||||||
"@expo/devcert" "^1.0.0"
|
"@expo/devcert" "^1.0.0"
|
||||||
"@expo/json-file" "8.2.28"
|
"@expo/json-file" "8.2.29"
|
||||||
"@expo/osascript" "2.0.25"
|
"@expo/osascript" "2.0.27"
|
||||||
"@expo/package-manager" "0.0.39"
|
"@expo/package-manager" "0.0.42"
|
||||||
"@expo/plist" "0.0.12"
|
"@expo/plist" "0.0.12"
|
||||||
"@expo/schemer" "1.3.27"
|
"@expo/schemer" "1.3.28"
|
||||||
"@expo/spawn-async" "1.5.0"
|
"@expo/spawn-async" "1.5.0"
|
||||||
"@expo/webpack-config" "0.12.64"
|
"@expo/webpack-config" "0.12.69"
|
||||||
"@hapi/joi" "^17.1.1"
|
"@hapi/joi" "^17.1.1"
|
||||||
"@types/text-table" "^0.2.1"
|
|
||||||
analytics-node "3.5.0"
|
analytics-node "3.5.0"
|
||||||
axios "0.21.1"
|
axios "0.21.1"
|
||||||
boxen "4.1.0"
|
boxen "4.1.0"
|
||||||
@@ -18768,7 +18857,6 @@ xdl@59.0.29:
|
|||||||
getenv "^1.0.0"
|
getenv "^1.0.0"
|
||||||
glob "7.1.6"
|
glob "7.1.6"
|
||||||
hasbin "1.2.3"
|
hasbin "1.2.3"
|
||||||
indent-string "3.2.0"
|
|
||||||
internal-ip "4.3.0"
|
internal-ip "4.3.0"
|
||||||
is-reachable "^4.0.0"
|
is-reachable "^4.0.0"
|
||||||
is-root "^2.1.0"
|
is-root "^2.1.0"
|
||||||
@@ -18778,25 +18866,22 @@ xdl@59.0.29:
|
|||||||
md5hex "1.0.0"
|
md5hex "1.0.0"
|
||||||
minimatch "3.0.4"
|
minimatch "3.0.4"
|
||||||
mv "2.1.1"
|
mv "2.1.1"
|
||||||
ncp "2.0.0"
|
|
||||||
node-forge "0.10.0"
|
node-forge "0.10.0"
|
||||||
p-map "3.0.0"
|
p-map "3.0.0"
|
||||||
p-retry "4.1.0"
|
p-retry "4.1.0"
|
||||||
p-timeout "3.1.0"
|
p-timeout "3.1.0"
|
||||||
package-json "6.4.0"
|
package-json "6.4.0"
|
||||||
pascal-case "2.0.1"
|
|
||||||
pretty-bytes "^5.3.0"
|
pretty-bytes "^5.3.0"
|
||||||
probe-image-size "~6.0.0"
|
probe-image-size "~6.0.0"
|
||||||
progress "2.0.3"
|
progress "2.0.3"
|
||||||
prompts "^2.3.2"
|
prompts "^2.3.2"
|
||||||
raven "2.6.3"
|
raven "2.6.3"
|
||||||
react-dev-utils "~11.0.1"
|
react-dev-utils "~11.0.1"
|
||||||
replace-string "1.1.0"
|
|
||||||
requireg "^0.2.2"
|
requireg "^0.2.2"
|
||||||
|
resolve-from "^5.0.0"
|
||||||
semver "7.3.2"
|
semver "7.3.2"
|
||||||
serialize-error "6.0.0"
|
serialize-error "6.0.0"
|
||||||
slugid "1.1.0"
|
slugid "1.1.0"
|
||||||
slugify "^1.3.6"
|
|
||||||
source-map-support "0.4.18"
|
source-map-support "0.4.18"
|
||||||
split "1.0.1"
|
split "1.0.1"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
@@ -18808,6 +18893,7 @@ xdl@59.0.29:
|
|||||||
uuid "3.3.2"
|
uuid "3.3.2"
|
||||||
webpack "4.43.0"
|
webpack "4.43.0"
|
||||||
webpack-dev-server "3.11.0"
|
webpack-dev-server "3.11.0"
|
||||||
|
wrap-ansi "^7.0.0"
|
||||||
|
|
||||||
xhr@^2.0.1:
|
xhr@^2.0.1:
|
||||||
version "2.6.0"
|
version "2.6.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user