mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-18 18:08:17 +08:00
Compare commits
33 Commits
@react-nav
...
@react-nav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5d539a11b | ||
|
|
7da45e1e89 | ||
|
|
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 | ||
|
|
aef35c5046 | ||
|
|
338ed6ff07 | ||
|
|
47e371609d | ||
|
|
ef42fa2d36 | ||
|
|
cc5d195f9a | ||
|
|
7e10bcd089 |
@@ -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
|
||||||
|
|||||||
62
.github/workflows/check-repro.yml
vendored
62
.github/workflows/check-repro.yml
vendored
@@ -23,26 +23,54 @@ jobs:
|
|||||||
'gm'
|
'gm'
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!regex.test(body)) {
|
if (regex.test(body)) {
|
||||||
return;
|
await github.issues.addLabels({
|
||||||
}
|
|
||||||
|
|
||||||
await github.issues.addLabels({
|
|
||||||
issue_number: context.issue.number,
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
labels: ['repro provided'],
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
await github.issues.removeLabel({
|
|
||||||
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,
|
||||||
name: 'needs repro',
|
labels: ['repro provided'],
|
||||||
});
|
});
|
||||||
} catch (error) {
|
|
||||||
if (!/Label does not exist/.test(error.message)) {
|
try {
|
||||||
throw error;
|
await github.issues.removeLabel({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
name: 'needs repro',
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
if (!/Label does not exist/.test(error.message)) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (context.eventName !== 'issues') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const body = "Hey! Thanks for opening the issue. The issue doesn't seem to contain a link to a repro (a [snack.expo.io](https://snack.expo.io) link or link to a GitHub repo under your username).\n\nCan you provide a [minimal repro](https://stackoverflow.com/help/minimal-reproducible-example) which demonstrates the issue? A repro will help us debug the issue faster. Please try to keep the repro as small as possible and make sure that we can run it without additional setup.";
|
||||||
|
|
||||||
|
const comments = await github.issues.listComments({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (comments.data.some(comment => comment.body === body)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await github.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body,
|
||||||
|
});
|
||||||
|
|
||||||
|
await github.issues.addLabels({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
labels: ['needs repro'],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
8
.github/workflows/expo-preview.yml
vendored
8
.github/workflows/expo-preview.yml
vendored
@@ -13,14 +13,12 @@ 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
|
||||||
with:
|
with:
|
||||||
expo-version: 3.x
|
expo-token: ${{ secrets.EXPO_TOKEN }}
|
||||||
expo-username: ${{ secrets.EXPO_CLI_USERNAME }}
|
|
||||||
expo-password: ${{ secrets.EXPO_CLI_PASSWORD }}
|
|
||||||
expo-cache: true
|
expo-cache: true
|
||||||
|
|
||||||
- name: Restore yarn cache
|
- name: Restore yarn cache
|
||||||
@@ -36,7 +34,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Publish Expo app
|
- name: Publish Expo app
|
||||||
working-directory: ./example
|
working-directory: ./example
|
||||||
run: expo publish --release-channel=pr-${{ github.event.number }}
|
run: yarn expo publish --release-channel=pr-${{ github.event.number }}
|
||||||
env:
|
env:
|
||||||
EXPO_USE_DEV_SERVER: true
|
EXPO_USE_DEV_SERVER: true
|
||||||
|
|
||||||
|
|||||||
8
.github/workflows/expo.yml
vendored
8
.github/workflows/expo.yml
vendored
@@ -16,14 +16,12 @@ 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
|
||||||
with:
|
with:
|
||||||
expo-version: 3.x
|
expo-token: ${{ secrets.EXPO_TOKEN }}
|
||||||
expo-username: ${{ secrets.EXPO_CLI_USERNAME }}
|
|
||||||
expo-password: ${{ secrets.EXPO_CLI_PASSWORD }}
|
|
||||||
expo-cache: true
|
expo-cache: true
|
||||||
|
|
||||||
- name: Restore yarn cache
|
- name: Restore yarn cache
|
||||||
@@ -39,4 +37,4 @@ jobs:
|
|||||||
|
|
||||||
- name: Publish Expo app
|
- name: Publish Expo app
|
||||||
working-directory: ./example
|
working-directory: ./example
|
||||||
run: expo publish
|
run: yarn expo publish
|
||||||
|
|||||||
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.'
|
||||||
2
.github/workflows/triage.yml
vendored
2
.github/workflows/triage.yml
vendored
@@ -31,7 +31,7 @@ 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! Thanks for opening the issue. Can you provide a [minimal repro](https://stackoverflow.com/help/minimal-reproducible-example) which demonstrates the issue? Posting a snippet of your code in the issue is useful, but it's not usually straightforward to run. A repro will help us debug the issue faster. Please try to keep the repro as small as possible.\n\nThe easiest way to provide a repro is on [snack.expo.io](https://snack.expo.io). If it's not possible to repro it on [snack.expo.io](https://snack.expo.io), then please provide the repro in a GitHub repository."
|
body: "Hey! Thanks for opening the issue. Can you provide a [minimal repro](https://stackoverflow.com/help/minimal-reproducible-example) which demonstrates the issue? Posting a snippet of your code in the issue is useful, but it's not usually straightforward to run. A repro will help us debug the issue faster. Please try to keep the repro as small as possible and make sure that we can run it without additional setup.\n\nThe easiest way to provide a repro is on [snack.expo.io](https://snack.expo.io). If it's not possible to repro it on [snack.expo.io](https://snack.expo.io), then please provide the repro in a GitHub repository."
|
||||||
})
|
})
|
||||||
|
|
||||||
question:
|
question:
|
||||||
|
|||||||
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,45 @@
|
|||||||
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.8](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@6.0.0-next.7...@react-navigation/bottom-tabs@6.0.0-next.8) (2021-05-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [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)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* update tab bar height correctly. fixes [#9296](https://github.com/react-navigation/react-navigation/issues/9296) ([338ed6f](https://github.com/react-navigation/react-navigation/commit/338ed6ff07bd2d6efa1abdb369612ea72f540502))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [6.0.0-next.4](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@6.0.0-next.3...@react-navigation/bottom-tabs@6.0.0-next.4) (2021-04-08)
|
# [6.0.0-next.4](https://github.com/react-navigation/react-navigation/compare/@react-navigation/bottom-tabs@6.0.0-next.3...@react-navigation/bottom-tabs@6.0.0-next.4) (2021-04-08)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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.4",
|
"version": "6.0.0-next.8",
|
||||||
"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.7",
|
||||||
"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.5",
|
||||||
"@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.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -284,12 +284,9 @@ export default function BottomTabBar({
|
|||||||
tabBarStyle,
|
tabBarStyle,
|
||||||
]}
|
]}
|
||||||
pointerEvents={isTabBarHidden ? 'none' : 'auto'}
|
pointerEvents={isTabBarHidden ? 'none' : 'auto'}
|
||||||
|
onLayout={handleLayout}
|
||||||
>
|
>
|
||||||
<View
|
<View accessibilityRole="tablist" style={styles.content}>
|
||||||
accessibilityRole="tablist"
|
|
||||||
style={styles.content}
|
|
||||||
onLayout={handleLayout}
|
|
||||||
>
|
|
||||||
{routes.map((route, index) => {
|
{routes.map((route, index) => {
|
||||||
const focused = index === state.index;
|
const focused = index === state.index;
|
||||||
const { options } = descriptors[route.key];
|
const { options } = descriptors[route.key];
|
||||||
|
|||||||
@@ -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,41 @@
|
|||||||
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/core@6.0.0-next.4...@react-navigation/core@6.0.0-next.5) (2021-05-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix type annotations for useNavigation ([7da45e1](https://github.com/react-navigation/react-navigation/commit/7da45e1e8951ff46e09db4ebc2c88085c67ab8e9))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [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.5",
|
||||||
"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,9 @@ 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<{}>
|
||||||
|
| 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,33 @@
|
|||||||
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/devtools@6.0.0-next.4...@react-navigation/devtools@6.0.0-next.5) (2021-05-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/devtools
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [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.5",
|
||||||
"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.5",
|
||||||
"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,34 @@
|
|||||||
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/drawer@6.0.0-next.6...@react-navigation/drawer@6.0.0-next.7) (2021-05-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/drawer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [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.7",
|
||||||
"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.7",
|
||||||
"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.5",
|
||||||
"@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,33 @@
|
|||||||
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.7](https://github.com/react-navigation/react-navigation/compare/@react-navigation/elements@1.0.0-next.6...@react-navigation/elements@1.0.0-next.7) (2021-05-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/elements
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [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.7",
|
||||||
"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.5",
|
||||||
"@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,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.5](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-bottom-tabs@6.0.0-next.4...@react-navigation/material-bottom-tabs@6.0.0-next.5) (2021-05-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [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.5",
|
||||||
"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.5",
|
||||||
"@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,38 @@
|
|||||||
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/material-top-tabs@6.0.0-next.5...@react-navigation/material-top-tabs@6.0.0-next.6) (2021-05-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [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)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [6.0.0-next.2](https://github.com/react-navigation/react-navigation/compare/@react-navigation/material-top-tabs@6.0.0-next.1...@react-navigation/material-top-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-top-tabs@6.0.0-next.1...@react-navigation/material-top-tabs@6.0.0-next.2) (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.2",
|
"version": "6.0.0-next.6",
|
||||||
"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.5",
|
||||||
"@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,5 +1,5 @@
|
|||||||
import type { StyleProp, ViewStyle, TextStyle } from 'react-native';
|
import type { StyleProp, ViewStyle, TextStyle } from 'react-native';
|
||||||
import type { SceneRendererProps, TabView } from 'react-native-tab-view';
|
import type { SceneRendererProps, TabViewProps } from 'react-native-tab-view';
|
||||||
import type {
|
import type {
|
||||||
ParamListBase,
|
ParamListBase,
|
||||||
Descriptor,
|
Descriptor,
|
||||||
@@ -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>;
|
||||||
@@ -67,6 +67,16 @@ export type MaterialTopTabNavigationOptions = {
|
|||||||
*/
|
*/
|
||||||
lazy?: boolean;
|
lazy?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that returns a React element to render if this screen hasn't been rendered yet.
|
||||||
|
* The `lazy` option also needs to be enabled for this to work.
|
||||||
|
*
|
||||||
|
* This view is usually only shown for a split second. Keep it lightweight.
|
||||||
|
*
|
||||||
|
* By default, this renders null.
|
||||||
|
*/
|
||||||
|
lazyPlaceholder?: () => React.ReactNode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Title string of a tab displayed in the tab bar
|
* Title string of a tab displayed in the tab bar
|
||||||
* or a function that given { focused: boolean, color: string } returns a React.Node, to display in tab bar.
|
* or a function that given { focused: boolean, color: string } returns a React.Node, to display in tab bar.
|
||||||
@@ -179,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<
|
||||||
@@ -187,37 +197,21 @@ export type MaterialTopTabDescriptorMap = Record<
|
|||||||
MaterialTopTabDescriptor
|
MaterialTopTabDescriptor
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type MaterialTopTabNavigationConfig = Partial<
|
export type MaterialTopTabNavigationConfig = Omit<
|
||||||
Omit<
|
TabViewProps<Route<string>>,
|
||||||
React.ComponentProps<typeof TabView>,
|
| 'navigationState'
|
||||||
| 'navigationState'
|
| 'onIndexChange'
|
||||||
| 'onIndexChange'
|
| 'onSwipeStart'
|
||||||
| 'onSwipeStart'
|
| 'onSwipeEnd'
|
||||||
| 'onSwipeEnd'
|
| 'renderScene'
|
||||||
| 'renderScene'
|
| 'renderTabBar'
|
||||||
| 'renderTabBar'
|
| 'renderLazyPlaceholder'
|
||||||
| 'renderLazyPlaceholder'
|
| 'lazy'
|
||||||
| 'lazy'
|
|
||||||
>
|
|
||||||
> & {
|
> & {
|
||||||
/**
|
|
||||||
* Function that returns a React element to render for routes that haven't been rendered yet.
|
|
||||||
* Receives an object containing the route as the prop.
|
|
||||||
* The lazy prop also needs to be enabled.
|
|
||||||
*
|
|
||||||
* This view is usually only shown for a split second. Keep it lightweight.
|
|
||||||
*
|
|
||||||
* By default, this renders null.
|
|
||||||
*/
|
|
||||||
lazyPlaceholder?: (props: { route: Route<string> }) => React.ReactNode;
|
|
||||||
/**
|
/**
|
||||||
* Function that returns a React element to display as the tab bar.
|
* Function that returns a React element to display as the tab bar.
|
||||||
*/
|
*/
|
||||||
tabBar?: (props: MaterialTopTabBarProps) => React.ReactNode;
|
tabBar?: (props: MaterialTopTabBarProps) => React.ReactNode;
|
||||||
/**
|
|
||||||
* Position of the tab bar. Defaults to `top`.
|
|
||||||
*/
|
|
||||||
tabBarPosition?: 'top' | 'bottom';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type MaterialTopTabBarProps = SceneRendererProps & {
|
export type MaterialTopTabBarProps = SceneRendererProps & {
|
||||||
|
|||||||
@@ -21,11 +21,9 @@ type Props = MaterialTopTabNavigationConfig & {
|
|||||||
state: TabNavigationState<ParamListBase>;
|
state: TabNavigationState<ParamListBase>;
|
||||||
navigation: MaterialTopTabNavigationHelpers;
|
navigation: MaterialTopTabNavigationHelpers;
|
||||||
descriptors: MaterialTopTabDescriptorMap;
|
descriptors: MaterialTopTabDescriptorMap;
|
||||||
tabBarPosition?: 'top' | 'bottom';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function MaterialTopTabView({
|
export default function MaterialTopTabView({
|
||||||
lazyPlaceholder,
|
|
||||||
tabBar = (props: MaterialTopTabBarProps) => <MaterialTopTabBar {...props} />,
|
tabBar = (props: MaterialTopTabBarProps) => <MaterialTopTabBar {...props} />,
|
||||||
state,
|
state,
|
||||||
navigation,
|
navigation,
|
||||||
@@ -57,7 +55,9 @@ export default function MaterialTopTabView({
|
|||||||
renderScene={({ route }) => descriptors[route.key].render()}
|
renderScene={({ route }) => descriptors[route.key].render()}
|
||||||
navigationState={state}
|
navigationState={state}
|
||||||
renderTabBar={renderTabBar}
|
renderTabBar={renderTabBar}
|
||||||
renderLazyPlaceholder={lazyPlaceholder}
|
renderLazyPlaceholder={({ route }) =>
|
||||||
|
descriptors[route.key].options.lazyPlaceholder?.() ?? null
|
||||||
|
}
|
||||||
lazy={({ route }) => descriptors[route.key].options.lazy === true}
|
lazy={({ route }) => descriptors[route.key].options.lazy === true}
|
||||||
onSwipeStart={() => navigation.emit({ type: 'swipeStart' })}
|
onSwipeStart={() => navigation.emit({ type: 'swipeStart' })}
|
||||||
onSwipeEnd={() => navigation.emit({ type: 'swipeEnd' })}
|
onSwipeEnd={() => navigation.emit({ type: 'swipeEnd' })}
|
||||||
|
|||||||
@@ -3,6 +3,37 @@
|
|||||||
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/native@6.0.0-next.4...@react-navigation/native@6.0.0-next.5) (2021-05-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/native
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [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.5",
|
||||||
"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.5",
|
||||||
"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,50 @@
|
|||||||
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.12](https://github.com/react-navigation/react-navigation/compare/@react-navigation/stack@6.0.0-next.11...@react-navigation/stack@6.0.0-next.12) (2021-05-09)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @react-navigation/stack
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [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.12",
|
||||||
"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.7",
|
||||||
"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.5",
|
||||||
"@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