Compare commits
51 Commits
@react-nav
...
@react-nav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22e306004a | ||
|
|
8a835b3556 | ||
|
|
d9237e9a0d | ||
|
|
0644ac03aa | ||
|
|
41a5e1a385 | ||
|
|
3d937d1e65 | ||
|
|
343320783f | ||
|
|
5411816188 | ||
|
|
d8bda604ee | ||
|
|
c70635b7d7 | ||
|
|
94d7b28c0b | ||
|
|
b19b3b2725 | ||
|
|
3dcec142f7 | ||
|
|
0c159db4c9 | ||
|
|
2479da98ed | ||
|
|
5197ee2a9c | ||
|
|
0ead2662ec | ||
|
|
5af5c29f07 | ||
|
|
d448cdc11f | ||
|
|
0e8fda3196 | ||
|
|
9198597b7f | ||
|
|
9be904d9c4 | ||
|
|
fa4a959549 | ||
|
|
d0510d0220 | ||
|
|
0b4bf1dcc8 | ||
|
|
5a3f8356b0 | ||
|
|
eeae11033a | ||
|
|
b931ae62df | ||
|
|
ea66b1a3b8 | ||
|
|
4bc0c8f66f | ||
|
|
68016de385 | ||
|
|
e55e866af2 | ||
|
|
50b366e734 | ||
|
|
edf96d839f | ||
|
|
141d397bdf | ||
|
|
0f18b91690 | ||
|
|
6262f7298b | ||
|
|
a6f58677dc | ||
|
|
9bfb295620 | ||
|
|
ecd68afb46 | ||
|
|
5fe140e61b | ||
|
|
944fa35ed4 | ||
|
|
2243b45cc1 | ||
|
|
5e7cfc4ac0 | ||
|
|
5751e7f97a | ||
|
|
179e807a64 | ||
|
|
2f1f0af862 | ||
|
|
9976a888a0 | ||
|
|
16c64e7298 | ||
|
|
f1fe951cf9 | ||
|
|
14250851d1 |
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* text eol=lf
|
||||
53
.github/workflows/expo-preview.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
name: Expo Preview
|
||||
on: [pull_request]
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Install and publish
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10.x
|
||||
|
||||
- name: Setup Expo
|
||||
uses: expo/expo-github-action@v5
|
||||
with:
|
||||
expo-version: 3.x
|
||||
expo-username: ${{ secrets.EXPO_CLI_USERNAME }}
|
||||
expo-password: ${{ secrets.EXPO_CLI_PASSWORD }}
|
||||
expo-cache: true
|
||||
|
||||
- name: Get yarn cache
|
||||
id: yarn-cache
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- name: Check yarn cache
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn
|
||||
|
||||
- name: Publish Expo app
|
||||
working-directory: ./example
|
||||
run: expo publish --release-channel=pr-${{ github.event.number }}
|
||||
|
||||
- name: Get expo link
|
||||
id: expo
|
||||
run: echo "::set-output name=path::@react-navigation/react-navigation-example?release-channel=pr-${{ github.event.number }}"
|
||||
|
||||
- name: Comment on PR
|
||||
uses: unsplash/comment-on-pr@master
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
msg: The Expo app for the example from this branch is ready!<br><br>[expo.io/${{ steps.expo.outputs.path }}](https://expo.io/${{ steps.expo.outputs.path }})<br><br><a href="https://exp.host/${{ steps.expo.outputs.path }}"><img src="https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=exp://exp.host/${{ steps.expo.outputs.path }}" height="200px" width="200px"></a>.
|
||||
44
.github/workflows/expo.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
name: Expo Publish
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Install and publish
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v1
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 10.x
|
||||
|
||||
- name: Setup Expo
|
||||
uses: expo/expo-github-action@v5
|
||||
with:
|
||||
expo-version: 3.x
|
||||
expo-username: ${{ secrets.EXPO_CLI_USERNAME }}
|
||||
expo-password: ${{ secrets.EXPO_CLI_PASSWORD }}
|
||||
expo-cache: true
|
||||
|
||||
- name: Get yarn cache
|
||||
id: yarn-cache
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- uses: actions/cache@v1
|
||||
with:
|
||||
path: ${{ steps.yarn-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn
|
||||
|
||||
- name: Publish Expo app
|
||||
working-directory: ./example
|
||||
run: expo publish
|
||||
27
.github/workflows/rebase.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: Automatic Rebase
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
rebase:
|
||||
name: Rebase
|
||||
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase')
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Automatic Rebase
|
||||
uses: cirrus-actions/rebase@1.2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# https://github.community/t5/GitHub-Actions/Workflow-is-failing-if-no-job-can-be-ran-due-to-condition/m-p/38186#M3250
|
||||
always_job:
|
||||
name: Always run job
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Always run
|
||||
run: echo "This job is used to prevent the workflow to fail when all other jobs are skipped."
|
||||
@@ -16,5 +16,7 @@ module.exports = {
|
||||
plugins: [
|
||||
'@babel/plugin-proposal-class-properties',
|
||||
'@babel/plugin-proposal-optional-chaining',
|
||||
'@babel/transform-flow-strip-types',
|
||||
'@babel/plugin-proposal-nullish-coalescing-operator',
|
||||
],
|
||||
};
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<facet type="android-gradle" name="Android-Gradle">
|
||||
<configuration>
|
||||
<option name="GRADLE_PROJECT_PATH" value=":app" />
|
||||
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" value="3.3.0" />
|
||||
<option name="LAST_KNOWN_AGP_VERSION" value="3.3.0" />
|
||||
<option name="LAST_SUCCESSFUL_SYNC_AGP_VERSION" value="3.4.2" />
|
||||
<option name="LAST_KNOWN_AGP_VERSION" value="3.4.2" />
|
||||
</configuration>
|
||||
</facet>
|
||||
<facet type="android" name="Android">
|
||||
@@ -19,8 +19,8 @@
|
||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
||||
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res;file://$MODULE_DIR$/build/generated/res/rs/debug;file://$MODULE_DIR$/build/generated/res/resValues/debug" />
|
||||
<option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" />
|
||||
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res;file://$MODULE_DIR$/build/generated/res/resValues/debug" />
|
||||
<option name="TEST_RES_FOLDERS_RELATIVE_PATH" value="" />
|
||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
||||
</configuration>
|
||||
</facet>
|
||||
@@ -70,6 +70,7 @@
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/rncli/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
|
||||
@@ -90,91 +91,103 @@
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 28 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:collections:28.0.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:common:1.1.1@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.core:common:1.1.1@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-annotations:28.0.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.infer.annotation:infer-annotation:0.11.2@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: javax.inject:javax.inject:1@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.code.findbugs:jsr305:3.0.2@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: javax.inject:javax.inject:1@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.collection:collection:1.1.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-common:2.1.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.arch.core:core-common:2.1.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.annotation:annotation:1.1.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp-urlconnection:3.12.1@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.squareup.okhttp3:okhttp:3.12.1@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.squareup.okio:okio:1.15.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.github.bumptech.glide:disklrucache:4.9.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.github.bumptech.glide:annotations:4.9.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.41@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib:1.3.41@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib-common:1.3.41@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.jetbrains:annotations:13.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.device.yearclass:yearclass:2.1.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: commons-codec:commons-codec:1.10@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: commons-io:commons-io:1.4@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.github.bumptech.glide:disklrucache:4.9.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.github.bumptech.glide:annotations:4.9.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.parse.bolts:bolts-tasks:1.4.0@jar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.react:react-native:0.61.5@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:appcompat-v7:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.appcompat:appcompat:1.1.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.browser:browser:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.github.bumptech.glide:glide:4.9.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.github.bumptech.glide:gifdecoder:4.9.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-location:16.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-base:16.0.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-places-placereport:16.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-tasks:16.0.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.google.android.gms:play-services-basement:16.0.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-v4:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-fragment:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:animated-vector-drawable:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:customtabs:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-core-ui:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-core-utils:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-vector-drawable:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:loader:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-media-compat:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:viewpager:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:coordinatorlayout:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:drawerlayout:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:slidingpanelayout:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:customview:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:swiperefreshlayout:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:asynclayoutinflater:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:support-compat:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:versionedparcelable:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:cursoradapter:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:runtime:1.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:documentfile:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:localbroadcastmanager:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:print:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:viewmodel:1.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.github.bumptech.glide:gifdecoder:4.9.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.android.support:interpolator:28.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata:1.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.lifecycle:livedata-core:1.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: android.arch.core:runtime:1.1.1@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:fresco:1.10.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline-okhttp3:1.10.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:drawee:1.10.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline:1.10.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline-base:1.10.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.legacy:legacy-support-v4:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.fragment:fragment:1.1.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.media:media:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.legacy:legacy-support-core-ui:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.legacy:legacy-support-core-utils:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.appcompat:appcompat-resources:1.1.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.drawerlayout:drawerlayout:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.viewpager:viewpager:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.loader:loader:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.activity:activity:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.vectordrawable:vectordrawable-animated:1.1.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.vectordrawable:vectordrawable:1.1.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.coordinatorlayout:coordinatorlayout:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.slidingpanelayout:slidingpanelayout:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.customview:customview:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.swiperefreshlayout:swiperefreshlayout:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.asynclayoutinflater:asynclayoutinflater:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.core:core:1.1.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.cursoradapter:cursoradapter:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.versionedparcelable:versionedparcelable:1.1.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.interpolator:interpolator:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-viewmodel:2.1.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-runtime:2.1.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.documentfile:documentfile:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.localbroadcastmanager:localbroadcastmanager:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.print:print:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.savedstate:savedstate:1.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-livedata:2.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.lifecycle:lifecycle-livedata-core:2.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: androidx.arch.core:core-runtime:2.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:fresco:2.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:fbcore:2.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:drawee:2.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline:2.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline-base:2.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.soloader:soloader:0.6.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:nativeimagefilters:2.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:nativeimagetranscoder:2.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:imagepipeline-okhttp3:2.0.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: io.nlopez.smartlocation:library:3.2.11@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: com.facebook.fresco:fbcore:1.10.0@aar" level="project" />
|
||||
<orderEntry type="library" name="Gradle: org.webkit:android-jsc:r245459@aar" level="project" />
|
||||
<orderEntry type="module" module-name="android-expo-permissions" />
|
||||
<orderEntry type="module" module-name="android-expo-constants" />
|
||||
<orderEntry type="module" module-name="android-unimodules-image-loader-interface" />
|
||||
<orderEntry type="module" module-name="android-expo-web-browser" />
|
||||
<orderEntry type="module" module-name="android-unimodules-react-native-adapter" />
|
||||
<orderEntry type="module" module-name="android-expo-file-system" />
|
||||
<orderEntry type="module" module-name="android-expo-location" />
|
||||
<orderEntry type="module" module-name="android-expo-error-recovery" />
|
||||
<orderEntry type="module" module-name="android-unimodules-permissions-interface" />
|
||||
<orderEntry type="module" module-name="android-unimodules-core" />
|
||||
<orderEntry type="module" module-name="android-expo-app-loader-provider" />
|
||||
<orderEntry type="module" module-name="android-expo-font" />
|
||||
<orderEntry type="module" module-name="android-expo-keep-awake" />
|
||||
<orderEntry type="module" module-name="android-expo-linear-gradient" />
|
||||
<orderEntry type="module" module-name="android-expo-sqlite" />
|
||||
<orderEntry type="module" module-name="android-unimodules-barcode-scanner-interface" />
|
||||
<orderEntry type="module" module-name="android-unimodules-camera-interface" />
|
||||
<orderEntry type="module" module-name="android-unimodules-constants-interface" />
|
||||
<orderEntry type="module" module-name="android-unimodules-face-detector-interface" />
|
||||
<orderEntry type="module" module-name="android-unimodules-file-system-interface" />
|
||||
<orderEntry type="module" module-name="android-unimodules-font-interface" />
|
||||
<orderEntry type="module" module-name="android-unimodules-sensors-interface" />
|
||||
<orderEntry type="module" module-name="android-unimodules-task-manager-interface" />
|
||||
<orderEntry type="module" module-name="android-@react-native-community_masked-view" />
|
||||
<orderEntry type="module" module-name="android-react-native-gesture-handler" />
|
||||
<orderEntry type="module" module-name="android-react-native-reanimated" />
|
||||
<orderEntry type="module" module-name="react-native-safe-area-context" />
|
||||
<orderEntry type="module" module-name="react-native-screens" />
|
||||
<orderEntry type="module" module-name="react-native-reanimated" />
|
||||
<orderEntry type="module" module-name="react-native-gesture-handler" />
|
||||
<orderEntry type="module" module-name="expo-permissions" />
|
||||
<orderEntry type="module" module-name="unimodules-core" />
|
||||
<orderEntry type="module" module-name="unimodules-react-native-adapter" />
|
||||
<orderEntry type="module" module-name="expo-app-loader-provider" />
|
||||
<orderEntry type="module" module-name="expo-constants" />
|
||||
<orderEntry type="module" module-name="expo-file-system" />
|
||||
<orderEntry type="module" module-name="expo-font" />
|
||||
<orderEntry type="module" module-name="expo-keep-awake" />
|
||||
<orderEntry type="module" module-name="expo-linear-gradient" />
|
||||
<orderEntry type="module" module-name="expo-location" />
|
||||
<orderEntry type="module" module-name="expo-sqlite" />
|
||||
<orderEntry type="module" module-name="expo-web-browser" />
|
||||
<orderEntry type="module" module-name="unimodules-barcode-scanner-interface" />
|
||||
<orderEntry type="module" module-name="unimodules-camera-interface" />
|
||||
<orderEntry type="module" module-name="unimodules-constants-interface" />
|
||||
<orderEntry type="module" module-name="unimodules-face-detector-interface" />
|
||||
<orderEntry type="module" module-name="unimodules-file-system-interface" />
|
||||
<orderEntry type="module" module-name="unimodules-font-interface" />
|
||||
<orderEntry type="module" module-name="unimodules-image-loader-interface" />
|
||||
<orderEntry type="module" module-name="unimodules-permissions-interface" />
|
||||
<orderEntry type="module" module-name="unimodules-sensors-interface" />
|
||||
<orderEntry type="module" module-name="unimodules-task-manager-interface" />
|
||||
</component>
|
||||
</module>
|
||||
</module>
|
||||
@@ -36,12 +36,19 @@
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="rne" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
|
||||
</application>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"displayName": "React Navigation Example",
|
||||
"expo": {
|
||||
"name": "@react-navigation/example",
|
||||
"owner": "react-navigation",
|
||||
"slug": "react-navigation-example",
|
||||
"description": "Demo app to showcase various functionality of React Navigation",
|
||||
"privacy": "public",
|
||||
|
||||
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
BIN
example/assets/album-art-04.jpg
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
example/assets/album-art-05.jpg
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
example/assets/album-art-06.jpg
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
example/assets/album-art-07.jpg
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
example/assets/album-art-08.jpg
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
example/assets/album-art-09.jpg
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
example/assets/album-art-10.jpg
Normal file
|
After Width: | Height: | Size: 229 KiB |
BIN
example/assets/album-art-11.jpg
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
example/assets/album-art-12.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
example/assets/album-art-13.jpg
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
example/assets/album-art-14.jpg
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
example/assets/album-art-15.jpg
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
example/assets/album-art-16.jpg
Normal file
|
After Width: | Height: | Size: 116 KiB |
BIN
example/assets/album-art-17.jpg
Normal file
|
After Width: | Height: | Size: 87 KiB |
BIN
example/assets/album-art-18.jpg
Normal file
|
After Width: | Height: | Size: 136 KiB |
BIN
example/assets/album-art-19.jpg
Normal file
|
After Width: | Height: | Size: 93 KiB |
BIN
example/assets/album-art-20.jpg
Normal file
|
After Width: | Height: | Size: 116 KiB |
BIN
example/assets/album-art-21.jpg
Normal file
|
After Width: | Height: | Size: 186 KiB |
BIN
example/assets/album-art-22.jpg
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
example/assets/album-art-23.jpg
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
example/assets/album-art-24.jpg
Normal file
|
After Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 900 B After Width: | Height: | Size: 683 B |
@@ -2,6 +2,8 @@ PODS:
|
||||
- boost-for-react-native (1.63.0)
|
||||
- DoubleConversion (1.1.6)
|
||||
- EXAppLoaderProvider (8.0.0)
|
||||
- EXBlur (8.0.0):
|
||||
- UMCore
|
||||
- EXConstants (8.0.0):
|
||||
- UMConstantsInterface
|
||||
- UMCore
|
||||
@@ -48,6 +50,8 @@ PODS:
|
||||
- glog
|
||||
- glog (0.3.5)
|
||||
- RCTRequired (0.61.5)
|
||||
- RCTRestart (0.0.13):
|
||||
- React
|
||||
- RCTTypeSafety (0.61.5):
|
||||
- FBLazyVector (= 0.61.5)
|
||||
- Folly (= 2018.10.22.00)
|
||||
@@ -249,11 +253,11 @@ PODS:
|
||||
- ReactCommon/jscallinvoker (= 0.61.5)
|
||||
- RNCMaskedView (0.1.5):
|
||||
- React
|
||||
- RNGestureHandler (1.5.3):
|
||||
- RNGestureHandler (1.5.5):
|
||||
- React
|
||||
- RNReanimated (1.4.0):
|
||||
- React
|
||||
- RNScreens (2.0.0-alpha.22):
|
||||
- RNScreens (2.0.0-alpha.33):
|
||||
- React
|
||||
- UMBarCodeScannerInterface (5.0.0)
|
||||
- UMCameraInterface (5.0.0)
|
||||
@@ -275,6 +279,7 @@ PODS:
|
||||
DEPENDENCIES:
|
||||
- DoubleConversion (from `../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
|
||||
- EXAppLoaderProvider (from `../../node_modules/expo-app-loader-provider/ios`)
|
||||
- EXBlur (from `../../node_modules/expo-blur/ios`)
|
||||
- EXConstants (from `../../node_modules/expo-constants/ios`)
|
||||
- EXErrorRecovery (from `../../node_modules/expo-error-recovery/ios`)
|
||||
- EXFileSystem (from `../../node_modules/expo-file-system/ios`)
|
||||
@@ -290,6 +295,7 @@ DEPENDENCIES:
|
||||
- Folly (from `../../node_modules/react-native/third-party-podspecs/Folly.podspec`)
|
||||
- glog (from `../../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
||||
- RCTRequired (from `../../node_modules/react-native/Libraries/RCTRequired`)
|
||||
- RCTRestart (from `../../node_modules/react-native-restart/ios`)
|
||||
- RCTTypeSafety (from `../../node_modules/react-native/Libraries/TypeSafety`)
|
||||
- React (from `../../node_modules/react-native/`)
|
||||
- React-Core (from `../../node_modules/react-native/`)
|
||||
@@ -340,6 +346,9 @@ EXTERNAL SOURCES:
|
||||
EXAppLoaderProvider:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../../node_modules/expo-app-loader-provider/ios"
|
||||
EXBlur:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../../node_modules/expo-blur/ios"
|
||||
EXConstants:
|
||||
:path: !ruby/object:Pathname
|
||||
path: "../../node_modules/expo-constants/ios"
|
||||
@@ -380,6 +389,8 @@ EXTERNAL SOURCES:
|
||||
:podspec: "../../node_modules/react-native/third-party-podspecs/glog.podspec"
|
||||
RCTRequired:
|
||||
:path: "../../node_modules/react-native/Libraries/RCTRequired"
|
||||
RCTRestart:
|
||||
:path: "../../node_modules/react-native-restart/ios"
|
||||
RCTTypeSafety:
|
||||
:path: "../../node_modules/react-native/Libraries/TypeSafety"
|
||||
React:
|
||||
@@ -469,6 +480,7 @@ SPEC CHECKSUMS:
|
||||
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
|
||||
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
|
||||
EXAppLoaderProvider: ebdb6bc2632c1ccadbe49f5e4104d8d690969c49
|
||||
EXBlur: d1604f66f89a9414f5ee65dfb23874437c1bb147
|
||||
EXConstants: 4051b16c17ef3defa03c541d42811dc92b249146
|
||||
EXErrorRecovery: d36db99ec6a3808f313f01b0890eb443796dd1c2
|
||||
EXFileSystem: 6e0d9bb6cc4ea404dbb8f583c1a8a2dcdf4b83b6
|
||||
@@ -484,6 +496,7 @@ SPEC CHECKSUMS:
|
||||
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
|
||||
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
|
||||
RCTRequired: b153add4da6e7dbc44aebf93f3cf4fcae392ddf1
|
||||
RCTRestart: dd19aab87fc1118e05b6b5b91b959105647f56b4
|
||||
RCTTypeSafety: 9aa1b91d7f9310fc6eadc3cf95126ffe818af320
|
||||
React: b6a59ef847b2b40bb6e0180a97d0ca716969ac78
|
||||
React-Core: 688b451f7d616cc1134ac95295b593d1b5158a04
|
||||
@@ -504,9 +517,9 @@ SPEC CHECKSUMS:
|
||||
React-RCTVibration: a49a1f42bf8f5acf1c3e297097517c6b3af377ad
|
||||
ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd
|
||||
RNCMaskedView: dd13f9f7b146a9ad82f9b7eb6c9b5548fcf6e990
|
||||
RNGestureHandler: 02905abe54e1f6e59c081a10b4bd689721e17aa6
|
||||
RNGestureHandler: d2270608171c868581b840cfc692f2962c05cd17
|
||||
RNReanimated: b2ab0b693dddd2339bd2f300e770f6302d2e960c
|
||||
RNScreens: 6adf01eb4080f44af6cca551207c6b0505066857
|
||||
RNScreens: 1c7fd499b915c77c21e8e6c327890c5af9b4cf7e
|
||||
UMBarCodeScannerInterface: 3802c8574ef119c150701d679ab386e2266d6a54
|
||||
UMCameraInterface: 985d301f688ed392f815728f0dd906ca34b7ccb1
|
||||
UMConstantsInterface: bda5f8bd3403ad99e663eb3c4da685d063c5653c
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#import <UMCore/UMModuleRegistry.h>
|
||||
#import <UMReactNativeAdapter/UMNativeModulesProxy.h>
|
||||
#import <UMReactNativeAdapter/UMModuleRegistryAdapter.h>
|
||||
#import <React/RCTLinkingManager.h>
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
@@ -52,4 +53,10 @@
|
||||
#endif
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
|
||||
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
|
||||
{
|
||||
return [RCTLinkingManager application:app openURL:url options:options];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -20,33 +20,27 @@
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>React Navigation Example</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>rne</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<!--See http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ -->
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
<key>NSExceptionDomains</key>
|
||||
<dict>
|
||||
<key>localhost</key>
|
||||
@@ -78,5 +72,19 @@
|
||||
<string>Give React Navigation Example periences permission to access your photos</string>
|
||||
<key>NSRemindersUsageDescription</key>
|
||||
<string>Allow React Navigation Example to access your reminders</string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -6,7 +6,7 @@ const escape = require('escape-string-regexp');
|
||||
const blacklist = require('metro-config/src/defaults/blacklist');
|
||||
|
||||
const root = path.resolve(__dirname, '..');
|
||||
const packages = path.resolve(__dirname, '..', 'packages');
|
||||
const packages = path.resolve(root, 'packages');
|
||||
|
||||
// Get the list of dependencies for all packages in the monorepo
|
||||
const modules = ['@expo/vector-icons']
|
||||
@@ -22,7 +22,7 @@ const modules = ['@expo/vector-icons']
|
||||
);
|
||||
|
||||
// We need to collect list of deps that this package imports
|
||||
// Collecting both dependencies are peerDependencies sould do it
|
||||
// Collecting both dependencies are peerDependencies should do it
|
||||
return Object.keys({
|
||||
...pak.dependencies,
|
||||
...pak.peerDependencies,
|
||||
@@ -59,7 +59,7 @@ module.exports = {
|
||||
// When we import a package from the monorepo, metro won't be able to find their deps
|
||||
// We need to specify them in `extraNodeModules` to tell metro where to find them
|
||||
extraNodeModules: modules.reduce((acc, name) => {
|
||||
acc[name] = path.join(__dirname, '..', 'node_modules', name);
|
||||
acc[name] = path.join(root, 'node_modules', name);
|
||||
return acc;
|
||||
}, {}),
|
||||
},
|
||||
@@ -67,11 +67,11 @@ module.exports = {
|
||||
server: {
|
||||
enhanceMiddleware: middleware => {
|
||||
return (req, res, next) => {
|
||||
// When an asset is imported outside the project root, it has wrong path on Android
|
||||
// This happens for the back button in stack, so we fix the path to correct one
|
||||
const assets = '/packages/stack/src/views/assets';
|
||||
|
||||
if (req.url.startsWith(assets)) {
|
||||
// When an asset is imported outside the project root, it has wrong path on Android
|
||||
// This happens for the back button in stack, so we fix the path to correct one
|
||||
req.url = req.url.replace(
|
||||
assets,
|
||||
'/assets/../packages/stack/src/views/assets'
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "expo start",
|
||||
"web": "expo start --web",
|
||||
"web": "expo start:web",
|
||||
"native": "react-native start",
|
||||
"android": "react-native run-android",
|
||||
"ios": "react-native run-ios"
|
||||
@@ -13,6 +13,7 @@
|
||||
"dependencies": {
|
||||
"@expo/vector-icons": "^10.0.0",
|
||||
"@react-native-community/masked-view": "0.1.5",
|
||||
"@types/react-native-restart": "^0.0.0",
|
||||
"color": "^3.1.2",
|
||||
"expo": "^36.0.2",
|
||||
"expo-asset": "~8.0.0",
|
||||
@@ -20,12 +21,13 @@
|
||||
"react": "~16.9.0",
|
||||
"react-dom": "~16.9.0",
|
||||
"react-native": "~0.61.5",
|
||||
"react-native-gesture-handler": "~1.5.3",
|
||||
"react-native-gesture-handler": "^1.5.5",
|
||||
"react-native-paper": "^3.5.0",
|
||||
"react-native-reanimated": "^1.4.0",
|
||||
"react-native-restart": "^0.0.13",
|
||||
"react-native-safe-area-context": "^0.6.2",
|
||||
"react-native-screens": "^2.0.0-alpha.25",
|
||||
"react-native-tab-view": "2.11.0",
|
||||
"react-native-screens": "^2.0.0-alpha.33",
|
||||
"react-native-tab-view": "2.13.0",
|
||||
"react-native-unimodules": "^0.7.0",
|
||||
"react-native-web": "^0.11.7"
|
||||
},
|
||||
|
||||
@@ -1 +1 @@
|
||||
export default [];
|
||||
export default ['rne://127.0.0.1:19000/--/'];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { View, TextInput, ActivityIndicator, StyleSheet } from 'react-native';
|
||||
import { Title, Button } from 'react-native-paper';
|
||||
import { ParamListBase } from '@react-navigation/native';
|
||||
import { useTheme, ParamListBase } from '@react-navigation/native';
|
||||
import {
|
||||
createStackNavigator,
|
||||
HeaderBackButton,
|
||||
@@ -40,11 +40,25 @@ const SplashScreen = () => {
|
||||
|
||||
const SignInScreen = () => {
|
||||
const { signIn } = React.useContext(AuthContext);
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<View style={styles.content}>
|
||||
<TextInput placeholder="Username" style={styles.input} />
|
||||
<TextInput placeholder="Password" secureTextEntry style={styles.input} />
|
||||
<TextInput
|
||||
placeholder="Username"
|
||||
style={[
|
||||
styles.input,
|
||||
{ backgroundColor: colors.card, color: colors.text },
|
||||
]}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder="Password"
|
||||
secureTextEntry
|
||||
style={[
|
||||
styles.input,
|
||||
{ backgroundColor: colors.card, color: colors.text },
|
||||
]}
|
||||
/>
|
||||
<Button mode="contained" onPress={signIn} style={styles.button}>
|
||||
Sign in
|
||||
</Button>
|
||||
@@ -73,6 +87,7 @@ type Props = {
|
||||
|
||||
type State = {
|
||||
isLoading: boolean;
|
||||
isSignout: boolean;
|
||||
userToken: undefined | string;
|
||||
};
|
||||
|
||||
@@ -94,17 +109,20 @@ export default function SimpleStackScreen({ navigation }: Props) {
|
||||
case 'SIGN_IN':
|
||||
return {
|
||||
...prevState,
|
||||
isSignout: false,
|
||||
userToken: action.token,
|
||||
};
|
||||
case 'SIGN_OUT':
|
||||
return {
|
||||
...prevState,
|
||||
isSignout: true,
|
||||
userToken: undefined,
|
||||
};
|
||||
}
|
||||
},
|
||||
{
|
||||
isLoading: true,
|
||||
isSignout: false,
|
||||
userToken: undefined,
|
||||
}
|
||||
);
|
||||
@@ -147,7 +165,10 @@ export default function SimpleStackScreen({ navigation }: Props) {
|
||||
) : state.userToken === undefined ? (
|
||||
<SimpleStack.Screen
|
||||
name="SignIn"
|
||||
options={{ title: 'Sign in' }}
|
||||
options={{
|
||||
title: 'Sign in',
|
||||
animationTypeForReplace: state.isSignout ? 'pop' : 'push',
|
||||
}}
|
||||
component={SignInScreen}
|
||||
/>
|
||||
) : (
|
||||
@@ -171,7 +192,6 @@ const styles = StyleSheet.create({
|
||||
input: {
|
||||
margin: 8,
|
||||
padding: 10,
|
||||
backgroundColor: 'white',
|
||||
borderRadius: 3,
|
||||
borderWidth: StyleSheet.hairlineWidth,
|
||||
borderColor: 'rgba(0, 0, 0, 0.08)',
|
||||
|
||||
154
example/src/Screens/StackTransparent.tsx
Normal file
@@ -0,0 +1,154 @@
|
||||
import * as React from 'react';
|
||||
import { View, StyleSheet, ScrollView } from 'react-native';
|
||||
import { Button, Paragraph } from 'react-native-paper';
|
||||
import { RouteProp, ParamListBase, useTheme } from '@react-navigation/native';
|
||||
import {
|
||||
createStackNavigator,
|
||||
StackNavigationProp,
|
||||
} from '@react-navigation/stack';
|
||||
import Article from '../Shared/Article';
|
||||
|
||||
type SimpleStackParams = {
|
||||
Article: { author: string };
|
||||
Dialog: undefined;
|
||||
};
|
||||
|
||||
type SimpleStackNavigation = StackNavigationProp<SimpleStackParams>;
|
||||
|
||||
const ArticleScreen = ({
|
||||
navigation,
|
||||
route,
|
||||
}: {
|
||||
navigation: SimpleStackNavigation;
|
||||
route: RouteProp<SimpleStackParams, 'Article'>;
|
||||
}) => {
|
||||
return (
|
||||
<ScrollView>
|
||||
<View style={styles.buttons}>
|
||||
<Button
|
||||
mode="contained"
|
||||
onPress={() => navigation.push('Dialog')}
|
||||
style={styles.button}
|
||||
>
|
||||
Show Dialog
|
||||
</Button>
|
||||
<Button
|
||||
mode="outlined"
|
||||
onPress={() => navigation.goBack()}
|
||||
style={styles.button}
|
||||
>
|
||||
Go back
|
||||
</Button>
|
||||
</View>
|
||||
<Article author={{ name: route.params.author }} scrollEnabled={false} />
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
const DialogScreen = ({
|
||||
navigation,
|
||||
}: {
|
||||
navigation: SimpleStackNavigation;
|
||||
}) => {
|
||||
const { colors } = useTheme();
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={[styles.dialog, { backgroundColor: colors.card }]}>
|
||||
<Paragraph>
|
||||
Mise en place is a French term that literally means “put in place.” It
|
||||
also refers to a way cooks in professional kitchens and restaurants
|
||||
set up their work stations—first by gathering all ingredients for a
|
||||
recipes, partially preparing them (like measuring out and chopping),
|
||||
and setting them all near each other. Setting up mise en place before
|
||||
cooking is another top tip for home cooks, as it seriously helps with
|
||||
organization. It’ll pretty much guarantee you never forget to add an
|
||||
ingredient and save you time from running back and forth from the
|
||||
pantry ten times.
|
||||
</Paragraph>
|
||||
<Button style={styles.close} compact onPress={navigation.goBack}>
|
||||
Okay
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const SimpleStack = createStackNavigator<SimpleStackParams>();
|
||||
|
||||
type Props = Partial<React.ComponentProps<typeof SimpleStack.Navigator>> & {
|
||||
navigation: StackNavigationProp<ParamListBase>;
|
||||
};
|
||||
|
||||
export default function SimpleStackScreen({ navigation, ...rest }: Props) {
|
||||
navigation.setOptions({
|
||||
headerShown: false,
|
||||
});
|
||||
|
||||
return (
|
||||
<SimpleStack.Navigator mode="modal" {...rest}>
|
||||
<SimpleStack.Screen
|
||||
name="Article"
|
||||
component={ArticleScreen}
|
||||
initialParams={{ author: 'Gandalf' }}
|
||||
/>
|
||||
<SimpleStack.Screen
|
||||
name="Dialog"
|
||||
component={DialogScreen}
|
||||
options={{
|
||||
headerShown: false,
|
||||
cardStyle: { backgroundColor: 'transparent' },
|
||||
cardOverlayEnabled: true,
|
||||
cardStyleInterpolator: ({ current: { progress } }) => ({
|
||||
cardStyle: {
|
||||
opacity: progress.interpolate({
|
||||
inputRange: [0, 0.5, 0.9, 1],
|
||||
outputRange: [0, 0.25, 0.7, 1],
|
||||
}),
|
||||
transform: [
|
||||
{
|
||||
scale: progress.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0.9, 1],
|
||||
extrapolate: 'clamp',
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
overlayStyle: {
|
||||
opacity: progress.interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0, 0.5],
|
||||
extrapolate: 'clamp',
|
||||
}),
|
||||
},
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
</SimpleStack.Navigator>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
buttons: {
|
||||
flexDirection: 'row',
|
||||
padding: 8,
|
||||
},
|
||||
button: {
|
||||
margin: 8,
|
||||
},
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
dialog: {
|
||||
padding: 16,
|
||||
width: '90%',
|
||||
maxWidth: 400,
|
||||
borderRadius: 3,
|
||||
},
|
||||
close: {
|
||||
alignSelf: 'flex-end',
|
||||
},
|
||||
});
|
||||
@@ -2,23 +2,41 @@
|
||||
|
||||
import * as React from 'react';
|
||||
import {
|
||||
View,
|
||||
Image,
|
||||
Dimensions,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
ScrollViewProps,
|
||||
Dimensions,
|
||||
Platform,
|
||||
} from 'react-native';
|
||||
import { useScrollToTop } from '@react-navigation/native';
|
||||
|
||||
const COVERS = [
|
||||
require('../../assets/album-art-1.jpg'),
|
||||
require('../../assets/album-art-2.jpg'),
|
||||
require('../../assets/album-art-3.jpg'),
|
||||
require('../../assets/album-art-4.jpg'),
|
||||
require('../../assets/album-art-5.jpg'),
|
||||
require('../../assets/album-art-6.jpg'),
|
||||
require('../../assets/album-art-7.jpg'),
|
||||
require('../../assets/album-art-8.jpg'),
|
||||
require('../../assets/album-art-01.jpg'),
|
||||
require('../../assets/album-art-02.jpg'),
|
||||
require('../../assets/album-art-03.jpg'),
|
||||
require('../../assets/album-art-04.jpg'),
|
||||
require('../../assets/album-art-05.jpg'),
|
||||
require('../../assets/album-art-06.jpg'),
|
||||
require('../../assets/album-art-07.jpg'),
|
||||
require('../../assets/album-art-08.jpg'),
|
||||
require('../../assets/album-art-09.jpg'),
|
||||
require('../../assets/album-art-10.jpg'),
|
||||
require('../../assets/album-art-11.jpg'),
|
||||
require('../../assets/album-art-12.jpg'),
|
||||
require('../../assets/album-art-13.jpg'),
|
||||
require('../../assets/album-art-14.jpg'),
|
||||
require('../../assets/album-art-15.jpg'),
|
||||
require('../../assets/album-art-16.jpg'),
|
||||
require('../../assets/album-art-17.jpg'),
|
||||
require('../../assets/album-art-18.jpg'),
|
||||
require('../../assets/album-art-19.jpg'),
|
||||
require('../../assets/album-art-20.jpg'),
|
||||
require('../../assets/album-art-21.jpg'),
|
||||
require('../../assets/album-art-22.jpg'),
|
||||
require('../../assets/album-art-23.jpg'),
|
||||
require('../../assets/album-art-24.jpg'),
|
||||
];
|
||||
|
||||
export default function Albums(props: Partial<ScrollViewProps>) {
|
||||
@@ -27,34 +45,46 @@ export default function Albums(props: Partial<ScrollViewProps>) {
|
||||
useScrollToTop(ref);
|
||||
|
||||
return (
|
||||
<ScrollView
|
||||
ref={ref}
|
||||
style={styles.container}
|
||||
contentContainerStyle={styles.content}
|
||||
{...props}
|
||||
>
|
||||
<ScrollView ref={ref} contentContainerStyle={styles.content} {...props}>
|
||||
{COVERS.map((source, i) => (
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
<Image key={i} source={source} style={styles.cover} />
|
||||
))}
|
||||
{COVERS.map((source, i) => (
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
<Image key={i + 'F'} source={source} style={styles.cover} />
|
||||
<View key={i} style={styles.item}>
|
||||
<Image source={source} style={styles.photo} />
|
||||
</View>
|
||||
))}
|
||||
</ScrollView>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: '#000',
|
||||
},
|
||||
content: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
},
|
||||
cover: {
|
||||
width: '50%',
|
||||
height: Dimensions.get('window').width / 2,
|
||||
...Platform.select({
|
||||
web: {
|
||||
content: {
|
||||
display: 'grid' as 'none',
|
||||
gridTemplateColumns: 'repeat(auto-fill, minmax(150px, 1fr))',
|
||||
},
|
||||
item: {
|
||||
width: '100%',
|
||||
},
|
||||
},
|
||||
default: {
|
||||
content: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
},
|
||||
item: {
|
||||
height: Dimensions.get('window').width / 2,
|
||||
width: '50%',
|
||||
},
|
||||
},
|
||||
}),
|
||||
photo: {
|
||||
flex: 1,
|
||||
resizeMode: 'cover',
|
||||
paddingTop: '100%',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
StatusBar,
|
||||
I18nManager,
|
||||
} from 'react-native';
|
||||
import RNRestart from 'react-native-restart';
|
||||
import { MaterialIcons } from '@expo/vector-icons';
|
||||
import {
|
||||
Provider as PaperProvider,
|
||||
@@ -40,6 +41,7 @@ import LinkingPrefixes from './LinkingPrefixes';
|
||||
import SimpleStack from './Screens/SimpleStack';
|
||||
import NativeStack from './Screens/NativeStack';
|
||||
import ModalPresentationStack from './Screens/ModalPresentationStack';
|
||||
import StackTransparent from './Screens/StackTransparent';
|
||||
import StackHeaderCustomization from './Screens/StackHeaderCustomization';
|
||||
import BottomTabs from './Screens/BottomTabs';
|
||||
import MaterialTopTabsScreen from './Screens/MaterialTopTabs';
|
||||
@@ -70,6 +72,10 @@ const SCREENS = {
|
||||
title: 'Modal Presentation Stack',
|
||||
component: ModalPresentationStack,
|
||||
},
|
||||
StackTransparent: {
|
||||
title: 'Transparent Stack',
|
||||
component: StackTransparent,
|
||||
},
|
||||
StackHeaderCustomization: {
|
||||
title: 'Header Customization in Stack',
|
||||
component: StackHeaderCustomization,
|
||||
@@ -111,22 +117,27 @@ export default function App() {
|
||||
// To test deep linking on, run the following in the Terminal:
|
||||
// Android: adb shell am start -a android.intent.action.VIEW -d "exp://127.0.0.1:19000/--/simple-stack"
|
||||
// iOS: xcrun simctl openurl booted exp://127.0.0.1:19000/--/simple-stack
|
||||
// Android (bare): adb shell am start -a android.intent.action.VIEW -d "rne://127.0.0.1:19000/--/simple-stack"
|
||||
// iOS (bare): xcrun simctl openurl booted rne://127.0.0.1:19000/--/simple-stack
|
||||
// The first segment of the link is the the scheme + host (returned by `Linking.makeUrl`)
|
||||
const { getInitialState } = useLinking(containerRef, {
|
||||
prefixes: LinkingPrefixes,
|
||||
config: {
|
||||
Root: Object.keys(SCREENS).reduce<{ [key: string]: string }>(
|
||||
(acc, name) => {
|
||||
// Convert screen names such as SimpleStack to kebab case (simple-stack)
|
||||
acc[name] = name
|
||||
.replace(/([A-Z]+)/g, '-$1')
|
||||
.replace(/^-/, '')
|
||||
.toLowerCase();
|
||||
Root: {
|
||||
path: 'root',
|
||||
screens: Object.keys(SCREENS).reduce<{ [key: string]: string }>(
|
||||
(acc, name) => {
|
||||
// Convert screen names such as SimpleStack to kebab case (simple-stack)
|
||||
acc[name] = name
|
||||
.replace(/([A-Z]+)/g, '-$1')
|
||||
.replace(/^-/, '')
|
||||
.toLowerCase();
|
||||
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
),
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -142,7 +153,7 @@ export default function App() {
|
||||
try {
|
||||
let state = await getInitialState();
|
||||
|
||||
if (state === undefined) {
|
||||
if (Platform.OS !== 'web' && state === undefined) {
|
||||
const savedState = await AsyncStorage.getItem(
|
||||
NAVIGATION_PERSISTENCE_KEY
|
||||
);
|
||||
@@ -248,7 +259,12 @@ export default function App() {
|
||||
value={I18nManager.isRTL}
|
||||
onValueChange={() => {
|
||||
I18nManager.forceRTL(!I18nManager.isRTL);
|
||||
Updates.reloadFromCache();
|
||||
// @ts-ignore
|
||||
if (global.Expo) {
|
||||
Updates.reloadFromCache();
|
||||
} else {
|
||||
RNRestart.Restart();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Divider />
|
||||
@@ -270,7 +286,7 @@ export default function App() {
|
||||
<List.Item
|
||||
key={name}
|
||||
title={SCREENS[name].title}
|
||||
onPress={() => navigation.push(name)}
|
||||
onPress={() => navigation.navigate(name)}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
|
||||
@@ -10,6 +10,8 @@ const packages = path.resolve(__dirname, '..', 'packages');
|
||||
module.exports = async function(env, argv) {
|
||||
const config = await createExpoWebpackConfigAsync(env, argv);
|
||||
|
||||
config.context = path.resolve(__dirname, '..');
|
||||
|
||||
config.module.rules.push({
|
||||
test: /\.(js|ts|tsx)$/,
|
||||
include: /(packages|example)\/.+/,
|
||||
|
||||
@@ -64,7 +64,8 @@
|
||||
],
|
||||
"moduleNameMapper": {
|
||||
"@react-navigation/([^/]+)": "<rootDir>/packages/$1/src"
|
||||
}
|
||||
},
|
||||
"preset": "react-native"
|
||||
},
|
||||
"prettier": {
|
||||
"tabWidth": 2,
|
||||
|
||||
@@ -3,6 +3,39 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.42](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.39...@react-navigation/bottom-tabs@5.0.0-alpha.42) (2020-02-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.40](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.39...@react-navigation/bottom-tabs@5.0.0-alpha.40) (2020-02-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.39](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.38...@react-navigation/bottom-tabs@5.0.0-alpha.39) (2020-01-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* use layout instead of dimensions for determining tab bar layout ([f1fe951](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/commit/f1fe951cf9d602e1b6d4932e3c6c77bbeaaec5c0))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.38](https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs/compare/@react-navigation/bottom-tabs@5.0.0-alpha.37...@react-navigation/bottom-tabs@5.0.0-alpha.38) (2020-01-23)
|
||||
|
||||
|
||||
|
||||
21
packages/bottom-tabs/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 React Navigation Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -10,7 +10,7 @@
|
||||
"android",
|
||||
"tab"
|
||||
],
|
||||
"version": "5.0.0-alpha.38",
|
||||
"version": "5.0.0-alpha.42",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/bottom-tabs",
|
||||
"main": "lib/commonjs/index.js",
|
||||
@@ -30,7 +30,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.26",
|
||||
"@react-navigation/routers": "^5.0.0-alpha.30",
|
||||
"color": "^3.1.2",
|
||||
"react-native-iphone-x-helper": "^1.2.1"
|
||||
},
|
||||
|
||||
@@ -99,6 +99,12 @@ export type BottomTabNavigationOptions = {
|
||||
* Renders `TouchableWithoutFeedback` by default.
|
||||
*/
|
||||
tabBarButton?: (props: BottomTabBarButtonProps) => React.ReactNode;
|
||||
|
||||
/**
|
||||
* Whether this screen should be unmounted when navigating away from it.
|
||||
* Defaults to `false`.
|
||||
*/
|
||||
unmountOnBlur?: boolean;
|
||||
};
|
||||
|
||||
export type BottomTabDescriptor = Descriptor<
|
||||
@@ -118,11 +124,6 @@ export type BottomTabNavigationConfig = {
|
||||
* Set it to `false` if you want to render all screens on initial render.
|
||||
*/
|
||||
lazy?: boolean;
|
||||
/**
|
||||
* Whether a screen should be unmounted when navigating away from it.
|
||||
* Defaults to `false`.
|
||||
*/
|
||||
unmountInactiveScreens?: boolean;
|
||||
/**
|
||||
* Function that returns a React element to display as the tab bar.
|
||||
*/
|
||||
@@ -176,14 +177,9 @@ export type BottomTabBarOptions = {
|
||||
tabStyle?: StyleProp<ViewStyle>;
|
||||
/**
|
||||
* Whether the label is renderd below the icon or beside the icon.
|
||||
* When a function is passed, it receives the device dimensions to render the label differently.
|
||||
* By default, in `vertical` orinetation, label is rendered below and in `horizontal` orientation, it's renderd beside.
|
||||
*/
|
||||
labelPosition?:
|
||||
| LabelPosition
|
||||
| ((options: {
|
||||
dimensions: { height: number; width: number };
|
||||
}) => LabelPosition);
|
||||
labelPosition?: LabelPosition;
|
||||
/**
|
||||
* Whether the label position should adapt to the orientation.
|
||||
*/
|
||||
|
||||
@@ -50,7 +50,10 @@ export default function BottomTabBar({
|
||||
const { colors } = useTheme();
|
||||
|
||||
const [dimensions, setDimensions] = React.useState(Dimensions.get('window'));
|
||||
const [layout, setLayout] = React.useState({ height: 0, width: 0 });
|
||||
const [layout, setLayout] = React.useState({
|
||||
height: 0,
|
||||
width: dimensions.width,
|
||||
});
|
||||
const [keyboardShown, setKeyboardShown] = React.useState(false);
|
||||
|
||||
const [visible] = React.useState(() => new Animated.Value(0));
|
||||
@@ -124,27 +127,15 @@ export default function BottomTabBar({
|
||||
};
|
||||
|
||||
const shouldUseHorizontalLabels = () => {
|
||||
const isLandscape = dimensions.width > dimensions.height;
|
||||
|
||||
if (labelPosition) {
|
||||
let position;
|
||||
|
||||
if (typeof labelPosition === 'string') {
|
||||
position = labelPosition;
|
||||
} else {
|
||||
position = labelPosition({ dimensions });
|
||||
}
|
||||
|
||||
if (position) {
|
||||
return position === 'beside-icon';
|
||||
}
|
||||
return labelPosition === 'beside-icon';
|
||||
}
|
||||
|
||||
if (!adaptive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dimensions.width >= 768) {
|
||||
if (layout.width >= 768) {
|
||||
// Screen size matches a tablet
|
||||
let maxTabItemWidth = DEFAULT_MAX_TAB_ITEM_WIDTH;
|
||||
|
||||
@@ -158,8 +149,10 @@ export default function BottomTabBar({
|
||||
}
|
||||
}
|
||||
|
||||
return routes.length * maxTabItemWidth <= dimensions.width;
|
||||
return routes.length * maxTabItemWidth <= layout.width;
|
||||
} else {
|
||||
const isLandscape = dimensions.width > dimensions.height;
|
||||
|
||||
return isLandscape;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -92,7 +92,7 @@ export default class BottomTabView extends React.Component<Props, State> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { state, descriptors, lazy, unmountInactiveScreens } = this.props;
|
||||
const { state, descriptors, lazy } = this.props;
|
||||
const { routes } = state;
|
||||
const { loaded } = this.state;
|
||||
|
||||
@@ -101,17 +101,19 @@ export default class BottomTabView extends React.Component<Props, State> {
|
||||
<View style={styles.container}>
|
||||
<ScreenContainer style={styles.pages}>
|
||||
{routes.map((route, index) => {
|
||||
if (unmountInactiveScreens && index !== state.index) {
|
||||
const descriptor = descriptors[route.key];
|
||||
const { unmountOnBlur } = descriptor.options;
|
||||
const isFocused = state.index === index;
|
||||
|
||||
if (unmountOnBlur && !isFocused) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (lazy && !loaded.includes(index)) {
|
||||
if (lazy && !loaded.includes(index) && !isFocused) {
|
||||
// Don't render a screen if we've never navigated to it
|
||||
return null;
|
||||
}
|
||||
|
||||
const isFocused = state.index === index;
|
||||
|
||||
return (
|
||||
<ResourceSavingScene
|
||||
key={route.key}
|
||||
@@ -119,7 +121,7 @@ export default class BottomTabView extends React.Component<Props, State> {
|
||||
isVisible={isFocused}
|
||||
>
|
||||
<SceneContent isFocused={isFocused}>
|
||||
{descriptors[route.key].render()}
|
||||
{descriptor.render()}
|
||||
</SceneContent>
|
||||
</ResourceSavingScene>
|
||||
);
|
||||
|
||||
@@ -3,6 +3,38 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.31](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.28...@react-navigation/compat@5.0.0-alpha.31) (2020-02-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
|
||||
* throw when assigning or accessing the router property in compat ([944fa35](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/commit/944fa35ed4778ebc7fa7cd50092719cbd5bf3caf))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.29](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.28...@react-navigation/compat@5.0.0-alpha.29) (2020-02-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
|
||||
* throw when assigning or accessing the router property in compat ([944fa35](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/commit/944fa35ed4778ebc7fa7cd50092719cbd5bf3caf))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.28](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.27...@react-navigation/compat@5.0.0-alpha.28) (2020-01-24)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/compat
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.27](https://github.com/react-navigation/navigation-ex/tree/master/packages/compat/compare/@react-navigation/compat@5.0.0-alpha.26...@react-navigation/compat@5.0.0-alpha.27) (2020-01-23)
|
||||
|
||||
|
||||
|
||||
21
packages/compat/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 React Navigation Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@react-navigation/compat",
|
||||
"description": "Compatibility layer to write navigator definitions in static configuration format",
|
||||
"version": "5.0.0-alpha.27",
|
||||
"version": "5.0.0-alpha.31",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/compat",
|
||||
"main": "lib/commonjs/index.js",
|
||||
@@ -21,7 +21,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.26"
|
||||
"@react-navigation/routers": "^5.0.0-alpha.30"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^16.9.17",
|
||||
|
||||
@@ -19,7 +19,7 @@ export function replace({
|
||||
key?: string;
|
||||
newKey?: string;
|
||||
action?: never;
|
||||
}): CommonActions.Action {
|
||||
}): StackActionType {
|
||||
if (action !== undefined) {
|
||||
throw new Error(
|
||||
'Sub-actions are not supported for `replace`. Remove the `action` key from the options.'
|
||||
|
||||
@@ -165,7 +165,25 @@ export default function createCompatNavigatorFactory<
|
||||
return Navigator;
|
||||
};
|
||||
|
||||
createCompatNavigator.isCompat = true;
|
||||
Object.defineProperties(createCompatNavigator, {
|
||||
isCompat: {
|
||||
get() {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
router: {
|
||||
get() {
|
||||
throw new Error(
|
||||
"It's no longer possible to access the router with the 'router' property."
|
||||
);
|
||||
},
|
||||
set() {
|
||||
throw new Error(
|
||||
"It's no longer possible to override the router by assigning the 'router' property."
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return createCompatNavigator;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,59 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.40](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.37...@react-navigation/core@5.0.0-alpha.40) (2020-02-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
|
||||
* add warning when passing inline function to component prop ([fa4a959](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/fa4a959549ccd9dc2f9bd2ea495e99abdedc9f94))
|
||||
* tweak error messages for validation ([2243b45](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/2243b45cc1addf83727166d82736d214f181b1fb))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add `screens` prop for nested configs ([#308](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/issues/308)) ([b931ae6](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/b931ae62dfb2c5253c94ea5ace73e9070ec17c4a))
|
||||
* add useIsDrawerOpen hook ([#299](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/issues/299)) ([ecd68af](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/ecd68afb46a4c56200748da5e5fb284fa5a839db))
|
||||
* integrate with history API on web ([5a3f835](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/5a3f8356b05bff7ed20893a5db6804612da3e568))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.38](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.37...@react-navigation/core@5.0.0-alpha.38) (2020-02-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
|
||||
* add warning when passing inline function to component prop ([fa4a959](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/fa4a959549ccd9dc2f9bd2ea495e99abdedc9f94))
|
||||
* tweak error messages for validation ([2243b45](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/2243b45cc1addf83727166d82736d214f181b1fb))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add `screens` prop for nested configs ([#308](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/issues/308)) ([b931ae6](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/b931ae62dfb2c5253c94ea5ace73e9070ec17c4a))
|
||||
* add useIsDrawerOpen hook ([#299](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/issues/299)) ([ecd68af](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/ecd68afb46a4c56200748da5e5fb284fa5a839db))
|
||||
* integrate with history API on web ([5a3f835](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/5a3f8356b05bff7ed20893a5db6804612da3e568))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.37](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.36...@react-navigation/core@5.0.0-alpha.37) (2020-01-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add error message when trying to use v4 API with v5 ([179e807](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/179e807a64a7d031d671c2c4b12edaee3c3440c5))
|
||||
* validate screen configs ([2f1f0af](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/2f1f0af862ef8625da4c2aaf463d45fe17a4ac88))
|
||||
* warn if non-serializable values found in state ([5751e7f](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/commit/5751e7f97a1731a5c71862174dfd931b6ffe13e2))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.36](https://github.com/react-navigation/navigation-ex/tree/master/packages/core/compare/@react-navigation/core@5.0.0-alpha.35...@react-navigation/core@5.0.0-alpha.36) (2020-01-23)
|
||||
|
||||
|
||||
|
||||
21
packages/core/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 React Navigation Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -6,7 +6,7 @@
|
||||
"react-native",
|
||||
"react-navigation"
|
||||
],
|
||||
"version": "5.0.0-alpha.36",
|
||||
"version": "5.0.0-alpha.40",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/core",
|
||||
"main": "lib/commonjs/index.js",
|
||||
@@ -27,6 +27,7 @@
|
||||
"dependencies": {
|
||||
"escape-string-regexp": "^2.0.0",
|
||||
"query-string": "^6.9.0",
|
||||
"react-is": "^16.12.0",
|
||||
"shortid": "^2.2.15",
|
||||
"use-subscription": "^1.3.0"
|
||||
},
|
||||
@@ -34,6 +35,7 @@
|
||||
"@babel/core": "^7.7.7",
|
||||
"@react-native-community/bob": "^0.8.0",
|
||||
"@types/react": "^16.9.17",
|
||||
"@types/react-is": "^16.7.1",
|
||||
"@types/shortid": "^0.0.29",
|
||||
"@types/use-subscription": "^1.0.0",
|
||||
"del-cli": "^3.0.0",
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import shortid from 'shortid';
|
||||
import { CommonAction, NavigationState, PartialState } from './types';
|
||||
|
||||
/**
|
||||
@@ -11,35 +10,6 @@ const BaseRouter = {
|
||||
action: CommonAction
|
||||
): State | PartialState<State> | null {
|
||||
switch (action.type) {
|
||||
case 'REPLACE': {
|
||||
const index = action.source
|
||||
? state.routes.findIndex(r => r.key === action.source)
|
||||
: state.index;
|
||||
|
||||
if (index === -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { name, key, params } = action.payload;
|
||||
|
||||
if (!state.routeNames.includes(name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
routes: state.routes.map((route, i) =>
|
||||
i === index
|
||||
? {
|
||||
key: key !== undefined ? key : `${name}-${shortid()}`,
|
||||
name,
|
||||
params,
|
||||
}
|
||||
: route
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
case 'SET_PARAMS': {
|
||||
const index = action.source
|
||||
? state.routes.findIndex(r => r.key === action.source)
|
||||
|
||||
@@ -14,12 +14,6 @@ export type Action =
|
||||
source?: string;
|
||||
target?: string;
|
||||
}
|
||||
| {
|
||||
type: 'REPLACE';
|
||||
payload: { name: string; key?: string; params?: object };
|
||||
source?: string;
|
||||
target?: string;
|
||||
}
|
||||
| {
|
||||
type: 'RESET';
|
||||
payload: PartialState<NavigationState>;
|
||||
@@ -59,10 +53,6 @@ export function navigate(...args: any): Action {
|
||||
}
|
||||
}
|
||||
|
||||
export function replace(name: string, params?: object): Action {
|
||||
return { type: 'REPLACE', payload: { name, params } };
|
||||
}
|
||||
|
||||
export function reset(state: PartialState<NavigationState>): Action {
|
||||
return { type: 'RESET', payload: state };
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ import * as React from 'react';
|
||||
import * as CommonActions from './CommonActions';
|
||||
import EnsureSingleNavigator from './EnsureSingleNavigator';
|
||||
import NavigationBuilderContext from './NavigationBuilderContext';
|
||||
import ResetRootContext from './ResetRootContext';
|
||||
import useFocusedListeners from './useFocusedListeners';
|
||||
import useDevTools from './useDevTools';
|
||||
import useStateGetters from './useStateGetters';
|
||||
import isSerializable from './isSerializable';
|
||||
|
||||
import {
|
||||
Route,
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
NavigationContainerRef,
|
||||
NavigationContainerProps,
|
||||
} from './types';
|
||||
import useEventEmitter from './useEventEmitter';
|
||||
|
||||
type State = NavigationState | PartialState<NavigationState> | undefined;
|
||||
|
||||
@@ -45,6 +46,8 @@ export const NavigationStateContext = React.createContext<{
|
||||
},
|
||||
});
|
||||
|
||||
let hasWarnedForSerialization = false;
|
||||
|
||||
/**
|
||||
* Remove `key` and `routeNames` from the state objects recursively to get partial state.
|
||||
*
|
||||
@@ -203,6 +206,8 @@ const Container = React.forwardRef(function NavigationContainer(
|
||||
return getStateForRoute('root');
|
||||
}, [getStateForRoute]);
|
||||
|
||||
const emitter = useEventEmitter();
|
||||
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
...(Object.keys(CommonActions) as (keyof typeof CommonActions)[]).reduce<
|
||||
any
|
||||
@@ -216,6 +221,7 @@ const Container = React.forwardRef(function NavigationContainer(
|
||||
);
|
||||
return acc;
|
||||
}, {}),
|
||||
...emitter.create('root'),
|
||||
resetRoot,
|
||||
dispatch,
|
||||
canGoBack,
|
||||
@@ -242,6 +248,25 @@ const Container = React.forwardRef(function NavigationContainer(
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (
|
||||
state !== undefined &&
|
||||
!isSerializable(state) &&
|
||||
!hasWarnedForSerialization
|
||||
) {
|
||||
hasWarnedForSerialization = true;
|
||||
|
||||
console.warn(
|
||||
"We found non-serializable values in the navigation state, which can break usage such as persisting and restoring state. This might happen if you passed non-serializable values such as function, class instances etc. in params. If you need to use functions in your options, you can use 'navigation.setOptions' instead."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
emitter.emit({
|
||||
type: 'state',
|
||||
data: { state },
|
||||
});
|
||||
|
||||
if (skipTrackingRef.current) {
|
||||
skipTrackingRef.current = false;
|
||||
} else {
|
||||
@@ -256,14 +281,12 @@ const Container = React.forwardRef(function NavigationContainer(
|
||||
}
|
||||
|
||||
isFirstMountRef.current = false;
|
||||
}, [state, onStateChange, trackState, getRootState]);
|
||||
}, [state, onStateChange, trackState, getRootState, emitter]);
|
||||
|
||||
return (
|
||||
<NavigationBuilderContext.Provider value={builderContext}>
|
||||
<NavigationStateContext.Provider value={context}>
|
||||
<ResetRootContext.Provider value={resetRoot}>
|
||||
<EnsureSingleNavigator>{children}</EnsureSingleNavigator>
|
||||
</ResetRootContext.Provider>
|
||||
<EnsureSingleNavigator>{children}</EnsureSingleNavigator>
|
||||
</NavigationStateContext.Provider>
|
||||
</NavigationBuilderContext.Provider>
|
||||
);
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import { NavigationState, PartialState } from './types';
|
||||
|
||||
/**
|
||||
* Context which holds the method to reset root navigator state.
|
||||
*/
|
||||
const ResetRootContext = React.createContext<
|
||||
(state: PartialState<NavigationState> | NavigationState) => void
|
||||
>(() => {
|
||||
throw new Error(
|
||||
"We couldn't find a way to reset root state. Have you wrapped your app with 'NavigationContainer'?"
|
||||
);
|
||||
});
|
||||
|
||||
export default ResetRootContext;
|
||||
@@ -16,64 +16,6 @@ const STATE = {
|
||||
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
||||
};
|
||||
|
||||
it('replaces focused screen with REPLACE', () => {
|
||||
const result = BaseRouter.getStateForAction(
|
||||
STATE,
|
||||
CommonActions.replace('qux', { answer: 42 })
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
stale: false,
|
||||
type: 'test',
|
||||
key: 'root',
|
||||
index: 1,
|
||||
routes: [
|
||||
{ key: 'foo', name: 'foo' },
|
||||
{ key: 'qux-test', name: 'qux', params: { answer: 42 } },
|
||||
{ key: 'baz', name: 'baz' },
|
||||
],
|
||||
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
||||
});
|
||||
});
|
||||
|
||||
it('replaces source screen with REPLACE', () => {
|
||||
const result = BaseRouter.getStateForAction(STATE, {
|
||||
...CommonActions.replace('qux', { answer: 42 }),
|
||||
source: 'baz',
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
stale: false,
|
||||
type: 'test',
|
||||
key: 'root',
|
||||
index: 1,
|
||||
routes: [
|
||||
{ key: 'foo', name: 'foo' },
|
||||
{ key: 'bar', name: 'bar', params: { fruit: 'orange' } },
|
||||
{ key: 'qux-test', name: 'qux', params: { answer: 42 } },
|
||||
],
|
||||
routeNames: ['foo', 'bar', 'baz', 'qux'],
|
||||
});
|
||||
});
|
||||
|
||||
it("doesn't handle REPLACE if source key isn't present", () => {
|
||||
const result = BaseRouter.getStateForAction(STATE, {
|
||||
...CommonActions.replace('qux', { answer: 42 }),
|
||||
source: 'magic',
|
||||
});
|
||||
|
||||
expect(result).toBe(null);
|
||||
});
|
||||
|
||||
it("doesn't handle REPLACE if screen to replace with isn't present", () => {
|
||||
const result = BaseRouter.getStateForAction(
|
||||
STATE,
|
||||
CommonActions.replace('nonexistent', { answer: 42 })
|
||||
);
|
||||
|
||||
expect(result).toBe(null);
|
||||
});
|
||||
|
||||
it('sets params for the focused screen with SET_PARAMS', () => {
|
||||
const result = BaseRouter.getStateForAction(
|
||||
STATE,
|
||||
|
||||
@@ -233,8 +233,8 @@ it('handle dispatching with ref', () => {
|
||||
<Screen name="foo2">
|
||||
{() => (
|
||||
<ChildNavigator>
|
||||
<Screen name="qux" component={() => null} />
|
||||
<Screen name="lex" component={() => null} />
|
||||
<Screen name="qux">{() => null}</Screen>
|
||||
<Screen name="lex">{() => null}</Screen>
|
||||
</ChildNavigator>
|
||||
)}
|
||||
</Screen>
|
||||
@@ -242,8 +242,8 @@ it('handle dispatching with ref', () => {
|
||||
<Screen name="baz">
|
||||
{() => (
|
||||
<ChildNavigator>
|
||||
<Screen name="qux" component={() => null} />
|
||||
<Screen name="lex" component={() => null} />
|
||||
<Screen name="qux">{() => null}</Screen>
|
||||
<Screen name="lex">{() => null}</Screen>
|
||||
</ChildNavigator>
|
||||
)}
|
||||
</Screen>
|
||||
@@ -254,9 +254,7 @@ it('handle dispatching with ref', () => {
|
||||
render(element).update(element);
|
||||
|
||||
act(() => {
|
||||
if (ref.current != null) {
|
||||
ref.current.dispatch({ type: 'REVERSE' });
|
||||
}
|
||||
ref.current?.dispatch({ type: 'REVERSE' });
|
||||
});
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(1);
|
||||
@@ -309,8 +307,8 @@ it('handle resetting state with ref', () => {
|
||||
<Screen name="foo2">
|
||||
{() => (
|
||||
<TestNavigator>
|
||||
<Screen name="qux" component={() => null} />
|
||||
<Screen name="lex" component={() => null} />
|
||||
<Screen name="qux">{() => null}</Screen>
|
||||
<Screen name="lex">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
)}
|
||||
</Screen>
|
||||
@@ -318,8 +316,8 @@ it('handle resetting state with ref', () => {
|
||||
<Screen name="baz">
|
||||
{() => (
|
||||
<TestNavigator>
|
||||
<Screen name="qux" component={() => null} />
|
||||
<Screen name="lex" component={() => null} />
|
||||
<Screen name="qux">{() => null}</Screen>
|
||||
<Screen name="lex">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
)}
|
||||
</Screen>
|
||||
@@ -350,9 +348,7 @@ it('handle resetting state with ref', () => {
|
||||
};
|
||||
|
||||
act(() => {
|
||||
if (ref.current != null) {
|
||||
ref.current.resetRoot(state);
|
||||
}
|
||||
ref.current?.resetRoot(state);
|
||||
});
|
||||
|
||||
expect(onStateChange).toBeCalledTimes(1);
|
||||
@@ -383,7 +379,7 @@ it('handle resetting state with ref', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('handle getRootState', () => {
|
||||
it('handles getRootState', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||
|
||||
@@ -398,12 +394,12 @@ it('handle getRootState', () => {
|
||||
<Screen name="foo">
|
||||
{() => (
|
||||
<TestNavigator>
|
||||
<Screen name="qux" component={() => null} />
|
||||
<Screen name="lex" component={() => null} />
|
||||
<Screen name="qux">{() => null}</Screen>
|
||||
<Screen name="lex">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
)}
|
||||
</Screen>
|
||||
<Screen name="bar" component={() => null} />
|
||||
<Screen name="bar">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
@@ -440,3 +436,68 @@ it('handle getRootState', () => {
|
||||
type: 'test',
|
||||
});
|
||||
});
|
||||
it('emits state events when the state changes', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
const { state, descriptors } = useNavigationBuilder(MockRouter, props);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{state.routes.map(route => descriptors[route.key].render())}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const ref = React.createRef<NavigationContainerRef>();
|
||||
|
||||
const element = (
|
||||
<NavigationContainer ref={ref}>
|
||||
<TestNavigator>
|
||||
<Screen name="foo">{() => null}</Screen>
|
||||
<Screen name="bar">{() => null}</Screen>
|
||||
<Screen name="baz">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
render(element).update(element);
|
||||
|
||||
const listener = jest.fn();
|
||||
|
||||
ref.current?.addListener('state', listener);
|
||||
|
||||
expect(listener).not.toHaveBeenCalled();
|
||||
|
||||
act(() => {
|
||||
ref.current?.navigate('bar');
|
||||
});
|
||||
|
||||
expect(listener.mock.calls[0][0].data.state).toEqual({
|
||||
type: 'test',
|
||||
stale: false,
|
||||
index: 1,
|
||||
key: '9',
|
||||
routeNames: ['foo', 'bar', 'baz'],
|
||||
routes: [
|
||||
{ key: 'foo', name: 'foo' },
|
||||
{ key: 'bar', name: 'bar' },
|
||||
{ key: 'baz', name: 'baz' },
|
||||
],
|
||||
});
|
||||
|
||||
act(() => {
|
||||
ref.current?.navigate('baz', { answer: 42 });
|
||||
});
|
||||
|
||||
expect(listener.mock.calls[1][0].data.state).toEqual({
|
||||
type: 'test',
|
||||
stale: false,
|
||||
index: 2,
|
||||
key: '9',
|
||||
routeNames: ['foo', 'bar', 'baz'],
|
||||
routes: [
|
||||
{ key: 'foo', name: 'foo' },
|
||||
{ key: 'bar', name: 'bar' },
|
||||
{ key: 'baz', name: 'baz', params: { answer: 42 } },
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
12
packages/core/src/__tests__/createNavigatorFactory.test.tsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import createNavigatorFactory from '../createNavigatorFactory';
|
||||
|
||||
it('throws descriptive error if an argument is passed', () => {
|
||||
const createDummyNavigator = createNavigatorFactory(() => null);
|
||||
|
||||
expect(() => createDummyNavigator()).not.toThrowError();
|
||||
|
||||
// @ts-ignore
|
||||
expect(() => createDummyNavigator({})).toThrowError(
|
||||
"Creating a navigator doesn't take an argument."
|
||||
);
|
||||
});
|
||||
@@ -116,10 +116,13 @@ it("doesn't add query param for empty params", () => {
|
||||
});
|
||||
|
||||
it('handles state with config with nested screens', () => {
|
||||
const path = '/few/bar/sweet/apple/baz/jane?answer=42&count=10&valid=true';
|
||||
const path = '/foe/bar/sweet/apple/baz/jane?answer=42&count=10&valid=true';
|
||||
const config = {
|
||||
Foo: {
|
||||
Foe: 'few',
|
||||
path: 'foo',
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
},
|
||||
},
|
||||
Bar: 'bar/:type/:fruit',
|
||||
Baz: {
|
||||
@@ -178,10 +181,13 @@ it('handles state with config with nested screens', () => {
|
||||
});
|
||||
|
||||
it('handles state with config with nested screens and unused configs', () => {
|
||||
const path = '/few/baz/jane?answer=42&count=10&valid=true';
|
||||
const path = '/foe/baz/jane?answer=42&count=10&valid=true';
|
||||
const config = {
|
||||
Foo: {
|
||||
Foe: 'few',
|
||||
path: 'foo',
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
},
|
||||
},
|
||||
Baz: {
|
||||
path: 'baz/:author',
|
||||
@@ -230,19 +236,31 @@ it('handles state with config with nested screens and unused configs', () => {
|
||||
});
|
||||
|
||||
it('handles nested object with stringify in it', () => {
|
||||
const path = '/bar/sweet/apple/few/bis/jane?answer=42&count=10&valid=true';
|
||||
const path = '/bar/sweet/apple/foe/bis/jane?answer=42&count=10&valid=true';
|
||||
const config = {
|
||||
Foo: {
|
||||
Foe: 'few',
|
||||
path: 'foo',
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
},
|
||||
},
|
||||
Bar: 'bar/:type/:fruit',
|
||||
Baz: {
|
||||
Bos: 'bos',
|
||||
Bis: {
|
||||
path: 'bis/:author',
|
||||
stringify: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toLowerCase()),
|
||||
path: 'baz',
|
||||
screens: {
|
||||
Bos: 'bos',
|
||||
Bis: {
|
||||
path: 'bis/:author',
|
||||
stringify: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toLowerCase()),
|
||||
},
|
||||
parse: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -292,7 +310,7 @@ it('handles nested object with stringify in it', () => {
|
||||
};
|
||||
|
||||
expect(getPathFromState(state, config)).toBe(path);
|
||||
expect(getPathFromState(getStateFromPath(path))).toBe(path);
|
||||
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||
});
|
||||
|
||||
it('handles nested object for second route depth', () => {
|
||||
@@ -300,9 +318,14 @@ it('handles nested object for second route depth', () => {
|
||||
const config = {
|
||||
Foo: {
|
||||
path: 'foo',
|
||||
Foe: 'foe',
|
||||
Bar: {
|
||||
Baz: 'baz',
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
Bar: {
|
||||
path: 'bar',
|
||||
screens: {
|
||||
Baz: 'baz',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -326,7 +349,7 @@ it('handles nested object for second route depth', () => {
|
||||
};
|
||||
|
||||
expect(getPathFromState(state, config)).toBe(path);
|
||||
expect(getPathFromState(getStateFromPath(path))).toBe(path);
|
||||
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||
});
|
||||
|
||||
it('handles nested object for second route depth and and path and stringify in roots', () => {
|
||||
@@ -337,16 +360,20 @@ it('handles nested object for second route depth and and path and stringify in r
|
||||
stringify: {
|
||||
id: (id: number) => `id=${id}`,
|
||||
},
|
||||
Foe: 'foe',
|
||||
Bar: {
|
||||
path: 'bar/:id',
|
||||
stringify: {
|
||||
id: (id: number) => `id=${id}`,
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
Bar: {
|
||||
path: 'bar/:id',
|
||||
stringify: {
|
||||
id: (id: number) => `id=${id}`,
|
||||
},
|
||||
parse: {
|
||||
id: Number,
|
||||
},
|
||||
screens: {
|
||||
Baz: 'baz',
|
||||
},
|
||||
},
|
||||
parse: {
|
||||
id: Number,
|
||||
},
|
||||
Baz: 'baz',
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -370,5 +397,5 @@ it('handles nested object for second route depth and and path and stringify in r
|
||||
};
|
||||
|
||||
expect(getPathFromState(state, config)).toBe(path);
|
||||
expect(getPathFromState(getStateFromPath(path))).toBe(path);
|
||||
expect(getPathFromState(getStateFromPath(path, config), config)).toBe(path);
|
||||
});
|
||||
|
||||
@@ -35,9 +35,9 @@ it('converts path string to initial state', () => {
|
||||
});
|
||||
|
||||
it('converts path string to initial state with config', () => {
|
||||
const path = '/few/bar/sweet/apple/baz/jane?count=10&answer=42&valid=true';
|
||||
const path = '/foo/bar/sweet/apple/baz/jane?count=10&answer=42&valid=true';
|
||||
const config = {
|
||||
Foo: 'few',
|
||||
Foo: 'foo',
|
||||
Bar: 'bar/:type/:fruit',
|
||||
Baz: {
|
||||
path: 'baz/:author',
|
||||
@@ -141,10 +141,13 @@ it('handles route without param', () => {
|
||||
});
|
||||
|
||||
it('converts path string to initial state with config with nested screens', () => {
|
||||
const path = '/few/bar/sweet/apple/baz/jane?count=10&answer=42&valid=true';
|
||||
const path = '/foe/bar/sweet/apple/baz/jane?count=10&answer=42&valid=true';
|
||||
const config = {
|
||||
Foo: {
|
||||
Foe: 'few',
|
||||
path: 'foo',
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
},
|
||||
},
|
||||
Bar: 'bar/:type/:fruit',
|
||||
Baz: {
|
||||
@@ -203,10 +206,13 @@ it('converts path string to initial state with config with nested screens', () =
|
||||
});
|
||||
|
||||
it('converts path string to initial state with config with nested screens and unused parse functions', () => {
|
||||
const path = '/few/baz/jane?count=10&answer=42&valid=true';
|
||||
const path = '/foe/baz/jane?count=10&answer=42&valid=true';
|
||||
const config = {
|
||||
Foo: {
|
||||
Foe: 'few',
|
||||
path: 'foo',
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
},
|
||||
},
|
||||
Baz: {
|
||||
path: 'baz/:author',
|
||||
@@ -254,21 +260,31 @@ it('converts path string to initial state with config with nested screens and un
|
||||
});
|
||||
|
||||
it('handles nested object with unused configs and with parse in it', () => {
|
||||
const path = '/bar/sweet/apple/few/bis/jane?count=10&answer=42&valid=true';
|
||||
const path = '/bar/sweet/apple/foe/bis/jane?count=10&answer=42&valid=true';
|
||||
const config = {
|
||||
Foo: {
|
||||
Foe: 'few',
|
||||
path: 'foo',
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
},
|
||||
},
|
||||
Bar: 'bar/:type/:fruit',
|
||||
Baz: {
|
||||
Bos: 'bos',
|
||||
Bis: {
|
||||
path: 'bis/:author',
|
||||
parse: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
path: 'baz',
|
||||
screens: {
|
||||
Bos: 'bos',
|
||||
Bis: {
|
||||
path: 'bis/:author',
|
||||
stringify: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toLowerCase()),
|
||||
},
|
||||
parse: {
|
||||
author: (author: string) =>
|
||||
author.replace(/^\w/, c => c.toUpperCase()),
|
||||
count: Number,
|
||||
valid: Boolean,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -328,9 +344,14 @@ it('handles parse in nested object for second route depth', () => {
|
||||
const config = {
|
||||
Foo: {
|
||||
path: 'foo',
|
||||
Foe: 'foe',
|
||||
Bar: {
|
||||
Baz: 'baz',
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
Bar: {
|
||||
path: 'bar',
|
||||
screens: {
|
||||
Baz: 'baz',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -370,16 +391,20 @@ it('handles parse in nested object for second route depth and and path and parse
|
||||
stringify: {
|
||||
id: (id: number) => `id=${id}`,
|
||||
},
|
||||
Foe: 'foe',
|
||||
Bar: {
|
||||
path: 'bar/:id',
|
||||
parse: {
|
||||
id: Number,
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
Bar: {
|
||||
path: 'bar/:id',
|
||||
parse: {
|
||||
id: Number,
|
||||
},
|
||||
stringify: {
|
||||
id: (id: number) => `id=${id}`,
|
||||
},
|
||||
screens: {
|
||||
Baz: 'baz',
|
||||
},
|
||||
},
|
||||
stringify: {
|
||||
id: (id: number) => `id=${id}`,
|
||||
},
|
||||
Baz: 'baz',
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -407,3 +432,34 @@ it('handles parse in nested object for second route depth and and path and parse
|
||||
state
|
||||
);
|
||||
});
|
||||
|
||||
it('returns undefined if path is empty', () => {
|
||||
const config = {
|
||||
Foo: {
|
||||
path: 'foo/:id',
|
||||
starting: true,
|
||||
stringify: {
|
||||
id: (id: number) => `id=${id}`,
|
||||
},
|
||||
screens: {
|
||||
Foe: 'foe',
|
||||
Bar: {
|
||||
path: 'bar/:id',
|
||||
parse: {
|
||||
id: Number,
|
||||
},
|
||||
stringify: {
|
||||
id: (id: number) => `id=${id}`,
|
||||
},
|
||||
screens: {
|
||||
Baz: 'baz',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const path = '';
|
||||
|
||||
expect(getStateFromPath(path, config)).toEqual(undefined);
|
||||
});
|
||||
|
||||
@@ -936,3 +936,138 @@ it('switches rendered navigators', () => {
|
||||
'Another navigator is already registered for this container.'
|
||||
);
|
||||
});
|
||||
|
||||
it('throws if no name is passed to Screen', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
useNavigationBuilder(MockRouter, props);
|
||||
return null;
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name={undefined as any} component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
'Got an invalid name (undefined) for the screen. It must be a non-empty string.'
|
||||
);
|
||||
});
|
||||
|
||||
it('throws if invalid name is passed to Screen', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
useNavigationBuilder(MockRouter, props);
|
||||
return null;
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name={[] as any} component={jest.fn()} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
'Got an invalid name ([]) for the screen. It must be a non-empty string.'
|
||||
);
|
||||
});
|
||||
|
||||
it('throws if both children and component are passed', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
useNavigationBuilder(MockRouter, props);
|
||||
return null;
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={jest.fn()}>
|
||||
{jest.fn()}
|
||||
</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
"Got both 'component' and 'children' props for the screen 'foo'. You must pass only one of them."
|
||||
);
|
||||
});
|
||||
|
||||
it('throws descriptive error for undefined screen component', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
useNavigationBuilder(MockRouter, props);
|
||||
return null;
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={undefined as any} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
"Couldn't find a 'component' or 'children' prop for the screen 'foo'"
|
||||
);
|
||||
});
|
||||
|
||||
it('throws descriptive error for invalid screen component', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
useNavigationBuilder(MockRouter, props);
|
||||
return null;
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={{} as any} />
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
"Got an invalid value for 'component' prop for the screen 'foo'. It must be a a valid React Component."
|
||||
);
|
||||
});
|
||||
|
||||
it('throws descriptive error for invalid children', () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
useNavigationBuilder(MockRouter, props);
|
||||
return null;
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo">{[] as any}</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).toThrowError(
|
||||
"Got an invalid value for 'children' prop for the screen 'foo'. It must be a function returning a React Element."
|
||||
);
|
||||
});
|
||||
|
||||
it("doesn't throw if children is null", () => {
|
||||
const TestNavigator = (props: any) => {
|
||||
useNavigationBuilder(MockRouter, props);
|
||||
return null;
|
||||
};
|
||||
|
||||
const element = (
|
||||
<NavigationContainer>
|
||||
<TestNavigator>
|
||||
<Screen name="foo" component={jest.fn()}>
|
||||
{null as any}
|
||||
</Screen>
|
||||
</TestNavigator>
|
||||
</NavigationContainer>
|
||||
);
|
||||
|
||||
expect(() => render(element).update(element)).not.toThrowError();
|
||||
});
|
||||
|
||||
@@ -592,7 +592,7 @@ it('returns true for canGoBack when parent router handles GO_BACK', () => {
|
||||
<Screen name="qux">
|
||||
{() => (
|
||||
<OverrodeNavigator>
|
||||
<Screen name="qux" component={() => null} />
|
||||
<Screen name="qux">{() => null}</Screen>
|
||||
</OverrodeNavigator>
|
||||
)}
|
||||
</Screen>
|
||||
|
||||
@@ -181,8 +181,8 @@ it("lets children handle the action if parent didn't", () => {
|
||||
<Screen name="baz">
|
||||
{() => (
|
||||
<ChildNavigator>
|
||||
<Screen name="qux" component={() => null} />
|
||||
<Screen name="lex" component={() => null} />
|
||||
<Screen name="qux">{() => null}</Screen>
|
||||
<Screen name="lex">{() => null}</Screen>
|
||||
</ChildNavigator>
|
||||
)}
|
||||
</Screen>
|
||||
@@ -291,8 +291,8 @@ it("action doesn't bubble if target is specified", () => {
|
||||
<Screen name="baz">
|
||||
{() => (
|
||||
<ChildNavigator>
|
||||
<Screen name="qux" component={() => null} />
|
||||
<Screen name="lex" component={() => null} />
|
||||
<Screen name="qux">{() => null}</Screen>
|
||||
<Screen name="lex">{() => null}</Screen>
|
||||
</ChildNavigator>
|
||||
)}
|
||||
</Screen>
|
||||
@@ -356,8 +356,8 @@ it('logs error if no navigator handled the action', () => {
|
||||
<Screen name="baz">
|
||||
{() => (
|
||||
<TestNavigator>
|
||||
<Screen name="qux" component={() => null} />
|
||||
<Screen name="lex" component={() => null} />
|
||||
<Screen name="qux">{() => null}</Screen>
|
||||
<Screen name="lex">{() => null}</Screen>
|
||||
</TestNavigator>
|
||||
)}
|
||||
</Screen>
|
||||
|
||||
@@ -13,11 +13,17 @@ export default function createNavigatorFactory<
|
||||
ScreenOptions extends object,
|
||||
NavigatorComponent extends React.ComponentType<any>
|
||||
>(Navigator: NavigatorComponent) {
|
||||
return <ParamList extends ParamListBase>(): TypedNavigator<
|
||||
return function<ParamList extends ParamListBase>(): TypedNavigator<
|
||||
ParamList,
|
||||
ScreenOptions,
|
||||
typeof Navigator
|
||||
> => {
|
||||
> {
|
||||
if (arguments[0] !== undefined) {
|
||||
throw new Error(
|
||||
"Creating a navigator doesn't take an argument. Maybe you are trying to use React Navigation 4 API with React Navigation 5?"
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
Navigator,
|
||||
Screen,
|
||||
|
||||
@@ -8,8 +8,11 @@ type StringifyConfig = Record<string, (value: any) => string>;
|
||||
type Options = {
|
||||
[routeName: string]:
|
||||
| string
|
||||
| { path: string; stringify?: StringifyConfig }
|
||||
| Options;
|
||||
| {
|
||||
path: string;
|
||||
stringify?: StringifyConfig;
|
||||
screens?: Options;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -43,6 +46,9 @@ export default function getPathFromState(
|
||||
state?: State,
|
||||
options: Options = {}
|
||||
): string {
|
||||
if (state === undefined) {
|
||||
throw Error('NavigationState not passed');
|
||||
}
|
||||
let path = '/';
|
||||
|
||||
let current: State | undefined = state;
|
||||
@@ -50,7 +56,7 @@ export default function getPathFromState(
|
||||
while (current) {
|
||||
let index = typeof current.index === 'number' ? current.index : 0;
|
||||
let route = current.routes[index] as Route<string> & {
|
||||
state?: State | undefined;
|
||||
state?: State;
|
||||
};
|
||||
let currentOptions = options;
|
||||
let pattern = route.name;
|
||||
@@ -64,10 +70,14 @@ export default function getPathFromState(
|
||||
pattern = (currentOptions[route.name] as { path: string }).path;
|
||||
break;
|
||||
} else {
|
||||
currentOptions = currentOptions[route.name] as Options;
|
||||
if (!(currentOptions[route.name] as { screens?: Options }).screens) {
|
||||
throw Error('Wrong Options object passed');
|
||||
}
|
||||
currentOptions = (currentOptions[route.name] as { screens: Options })
|
||||
.screens;
|
||||
index = typeof route.state.index === 'number' ? route.state.index : 0;
|
||||
route = route.state.routes[index] as Route<string> & {
|
||||
state?: State | undefined;
|
||||
state?: State;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,13 @@ import { NavigationState, PartialState, InitialState } from './types';
|
||||
type ParseConfig = Record<string, (value: string) => any>;
|
||||
|
||||
type Options = {
|
||||
[routeName: string]: string | { path: string; parse?: ParseConfig } | Options;
|
||||
[routeName: string]:
|
||||
| string
|
||||
| {
|
||||
path: string;
|
||||
parse?: ParseConfig;
|
||||
screens?: Options;
|
||||
};
|
||||
};
|
||||
|
||||
type RouteConfig = {
|
||||
@@ -42,6 +48,9 @@ export default function getStateFromPath(
|
||||
path: string,
|
||||
options: Options = {}
|
||||
): ResultState | undefined {
|
||||
if (path === '') {
|
||||
return undefined;
|
||||
}
|
||||
// Create a normalized configs array which will be easier to use
|
||||
const configs = ([] as RouteConfig[]).concat(
|
||||
...Object.keys(options).map(key => createNormalizedConfigs(key, options))
|
||||
@@ -65,7 +74,7 @@ export default function getStateFromPath(
|
||||
|
||||
// If our regex matches, we need to extract params from the path
|
||||
if (match) {
|
||||
routeNames = config.routeNames;
|
||||
routeNames = [...config.routeNames];
|
||||
|
||||
const paramPatterns = config.pattern
|
||||
.split('/')
|
||||
@@ -164,7 +173,7 @@ export default function getStateFromPath(
|
||||
const route = current.routes[0];
|
||||
|
||||
const params = queryString.parse(query);
|
||||
const parseFunction = findParseConfigForRoute(route.name, options);
|
||||
const parseFunction = findParseConfigForRoute(route.name, configs);
|
||||
|
||||
if (parseFunction) {
|
||||
Object.keys(params).forEach(name => {
|
||||
@@ -185,7 +194,7 @@ function createNormalizedConfigs(
|
||||
routeConfig: Options,
|
||||
routeNames: string[] = []
|
||||
): RouteConfig[] {
|
||||
const configs = [];
|
||||
const configs: RouteConfig[] = [];
|
||||
|
||||
routeNames.push(key);
|
||||
|
||||
@@ -196,30 +205,19 @@ function createNormalizedConfigs(
|
||||
configs.push(createConfigItem(routeNames, value));
|
||||
} else if (typeof value === 'object') {
|
||||
// if an object is specified as the value (e.g. Foo: { ... }),
|
||||
// it could have config object and optionally nested config
|
||||
Object.keys(value).forEach(nestedKey => {
|
||||
if (nestedKey === 'path') {
|
||||
configs.push(
|
||||
createConfigItem(
|
||||
routeNames,
|
||||
value[nestedKey] as string,
|
||||
value.parse ? (value.parse as ParseConfig) : undefined
|
||||
)
|
||||
);
|
||||
} else if (nestedKey === 'parse') {
|
||||
// We handle custom parse function when a `path` is specified (in nestedKey === path)
|
||||
} else {
|
||||
// If the name of the key is not `path` or `parse`, it's a nested config for route
|
||||
// So we need to traverse into it and collect the configs
|
||||
// it has `path` property and
|
||||
// it could have `screens` prop which has nested configs
|
||||
configs.push(createConfigItem(routeNames, value.path, value.parse));
|
||||
if (value.screens) {
|
||||
Object.keys(value.screens).forEach(nestedConfig => {
|
||||
const result = createNormalizedConfigs(
|
||||
nestedKey,
|
||||
routeConfig[key] as Options,
|
||||
nestedConfig,
|
||||
value.screens as Options,
|
||||
routeNames
|
||||
);
|
||||
|
||||
configs.push(...result);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
routeNames.pop();
|
||||
@@ -247,21 +245,12 @@ function createConfigItem(
|
||||
|
||||
function findParseConfigForRoute(
|
||||
routeName: string,
|
||||
config: Options
|
||||
flatConfig: RouteConfig[]
|
||||
): ParseConfig | undefined {
|
||||
if (config[routeName]) {
|
||||
return (config[routeName] as { parse?: ParseConfig }).parse;
|
||||
}
|
||||
|
||||
for (const name in config) {
|
||||
if (typeof config[name] === 'object') {
|
||||
const parse = findParseConfigForRoute(routeName, config[name] as Options);
|
||||
|
||||
if (parse) {
|
||||
return parse;
|
||||
}
|
||||
for (const config of flatConfig) {
|
||||
if (routeName === config.routeNames[config.routeNames.length - 1]) {
|
||||
return config.parse;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
34
packages/core/src/isSerializable.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
export default function isSerializable(o: { [key: string]: any }): boolean {
|
||||
if (
|
||||
o === undefined ||
|
||||
o === null ||
|
||||
typeof o === 'boolean' ||
|
||||
typeof o === 'number' ||
|
||||
typeof o === 'string'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
Object.prototype.toString.call(o) !== '[object Object]' &&
|
||||
!Array.isArray(o)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Array.isArray(o)) {
|
||||
for (const it of o) {
|
||||
if (!isSerializable(it)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const key in o) {
|
||||
if (!isSerializable(o[key])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -16,6 +16,10 @@ export type NavigationState = {
|
||||
* List of valid route names as defined in the screen components.
|
||||
*/
|
||||
routeNames: string[];
|
||||
/**
|
||||
* Alternative entries for history.
|
||||
*/
|
||||
history?: unknown[];
|
||||
/**
|
||||
* List of rendered routes.
|
||||
*/
|
||||
@@ -212,10 +216,10 @@ export type EventMapBase = Record<
|
||||
{ data?: any; canPreventDefault?: boolean }
|
||||
>;
|
||||
|
||||
export type EventMapCore = {
|
||||
export type EventMapCore<State extends NavigationState> = {
|
||||
focus: { data: undefined };
|
||||
blur: { data: undefined };
|
||||
state: { data: { state: NavigationState } };
|
||||
state: { data: { state: State } };
|
||||
};
|
||||
|
||||
export type EventArg<
|
||||
@@ -365,13 +369,6 @@ type NavigationHelpersCommon<
|
||||
*/
|
||||
reset(state: PartialState<State> | State): void;
|
||||
|
||||
/**
|
||||
* Reset the navigation state of the root navigator to the provided state.
|
||||
*
|
||||
* @param state Navigation state object.
|
||||
*/
|
||||
resetRoot(state?: PartialState<NavigationState> | NavigationState): void;
|
||||
|
||||
/**
|
||||
* Go back to the previous route in history.
|
||||
*/
|
||||
@@ -465,7 +462,7 @@ export type NavigationProp<
|
||||
* Note that this method doesn't re-render screen when the result changes. So don't use it in `render`.
|
||||
*/
|
||||
dangerouslyGetState(): State;
|
||||
} & EventConsumer<EventMap & EventMapCore> &
|
||||
} & EventConsumer<EventMap & EventMapCore<State>> &
|
||||
PrivateValueStore<ParamList, RouteName, EventMap>;
|
||||
|
||||
export type RouteProp<
|
||||
@@ -586,15 +583,21 @@ export type RouteConfig<
|
||||
);
|
||||
|
||||
export type NavigationContainerRef =
|
||||
| (NavigationHelpers<ParamListBase> & {
|
||||
/**
|
||||
* Reset the navigation state of the root navigator to the provided state.
|
||||
*
|
||||
* @param state Navigation state object.
|
||||
*/
|
||||
resetRoot(state?: PartialState<NavigationState> | NavigationState): void;
|
||||
getRootState(): NavigationState;
|
||||
})
|
||||
| (NavigationHelpers<ParamListBase> &
|
||||
EventConsumer<{ state: { data: { state: NavigationState } } }> & {
|
||||
/**
|
||||
* Reset the navigation state of the root navigator to the provided state.
|
||||
*
|
||||
* @param state Navigation state object.
|
||||
*/
|
||||
resetRoot(
|
||||
state?: PartialState<NavigationState> | NavigationState
|
||||
): void;
|
||||
/**
|
||||
* Get the rehydrated navigation state of the navigation tree.
|
||||
*/
|
||||
getRootState(): NavigationState;
|
||||
})
|
||||
| undefined
|
||||
| null;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { isValidElementType } from 'react-is';
|
||||
import { NavigationStateContext } from './NavigationContainer';
|
||||
import NavigationRouteContext from './NavigationRouteContext';
|
||||
import Screen from './Screen';
|
||||
@@ -53,8 +54,8 @@ const isArrayEqual = (a: any[], b: any[]) =>
|
||||
*/
|
||||
const getRouteConfigsFromChildren = <ScreenOptions extends object>(
|
||||
children: React.ReactNode
|
||||
) =>
|
||||
React.Children.toArray(children).reduce<
|
||||
) => {
|
||||
const configs = React.Children.toArray(children).reduce<
|
||||
RouteConfig<ParamListBase, string, ScreenOptions>[]
|
||||
>((acc, child) => {
|
||||
if (React.isValidElement(child)) {
|
||||
@@ -85,6 +86,56 @@ const getRouteConfigsFromChildren = <ScreenOptions extends object>(
|
||||
);
|
||||
}, []);
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
configs.forEach(config => {
|
||||
const { name, children, component } = config as any;
|
||||
|
||||
if (typeof name !== 'string' || !name) {
|
||||
throw new Error(
|
||||
`Got an invalid name (${JSON.stringify(
|
||||
name
|
||||
)}) for the screen. It must be a non-empty string.`
|
||||
);
|
||||
}
|
||||
|
||||
if (children != null || component !== undefined) {
|
||||
if (children != null && component !== undefined) {
|
||||
throw new Error(
|
||||
`Got both 'component' and 'children' props for the screen '${name}'. You must pass only one of them.`
|
||||
);
|
||||
}
|
||||
|
||||
if (children != null && typeof children !== 'function') {
|
||||
throw new Error(
|
||||
`Got an invalid value for 'children' prop for the screen '${name}'. It must be a function returning a React Element.`
|
||||
);
|
||||
}
|
||||
|
||||
if (component !== undefined && !isValidElementType(component)) {
|
||||
throw new Error(
|
||||
`Got an invalid value for 'component' prop for the screen '${name}'. It must be a a valid React Component.`
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof component === 'function' && component.name === 'component') {
|
||||
// Inline anonymous functions passed in the `component` prop will have the name of the prop
|
||||
// It's relatively safe to assume that it's not a component since it should also have PascalCase name
|
||||
// We won't catch all scenarios here, but this should catch a good chunk of incorrect use.
|
||||
console.warn(
|
||||
`Looks like you're passing an inline function for 'component' prop for the screen '${name}' (e.g. component={() => <SomeComponent />}). Passing an inline function will cause the component state to be lost on re-render and cause perf issues since it's re-created every render. You can pass the function as children to 'Screen' instead to achieve the desired behaviour.`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
`Couldn't find a 'component' or 'children' prop for the screen '${name}'. This can happen if you passed 'undefined'. You likely forgot to export your component from the file it's defined in, or mixed up default import and named import when importing.`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return configs;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook for building navigators.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import * as CommonActions from './CommonActions';
|
||||
import NavigationContext from './NavigationContext';
|
||||
import ResetRootContext from './ResetRootContext';
|
||||
import { NavigationStateContext } from './NavigationContainer';
|
||||
import { NavigationEventEmitter } from './useEventEmitter';
|
||||
import {
|
||||
@@ -37,7 +36,6 @@ export default function useNavigationHelpers<
|
||||
Action extends NavigationAction,
|
||||
EventMap extends Record<string, any>
|
||||
>({ onAction, getState, emitter, router }: Options<State, Action>) {
|
||||
const resetRoot = React.useContext(ResetRootContext);
|
||||
const parentNavigationHelpers = React.useContext(NavigationContext);
|
||||
const { performTransaction } = React.useContext(NavigationStateContext);
|
||||
|
||||
@@ -76,7 +74,6 @@ export default function useNavigationHelpers<
|
||||
return {
|
||||
...parentNavigationHelpers,
|
||||
...helpers,
|
||||
resetRoot,
|
||||
dispatch,
|
||||
emit: emitter.emit,
|
||||
isFocused: parentNavigationHelpers
|
||||
@@ -100,7 +97,6 @@ export default function useNavigationHelpers<
|
||||
router,
|
||||
getState,
|
||||
parentNavigationHelpers,
|
||||
resetRoot,
|
||||
emitter.emit,
|
||||
performTransaction,
|
||||
onAction,
|
||||
|
||||
@@ -3,6 +3,57 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.44](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/compare/@react-navigation/drawer@5.0.0-alpha.41...@react-navigation/drawer@5.0.0-alpha.44) (2020-02-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
|
||||
* fix drawerType=back when drawer is on right ([9198597](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/9198597b7f0a34fbe3844ec86a8b82171036f8ed)), closes [#316](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/issues/316)
|
||||
* handle back button in drawer itself ([0e8fda3](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/0e8fda319685a34090cfe82da08084c156eb5783))
|
||||
* screens integration on Android ([#294](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/issues/294)) ([9bfb295](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/9bfb29562020c61b4d5c9bee278bcb1c7bdb8b67))
|
||||
* update screens for native stack ([5411816](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/54118161885738a6d20b062c7e6679f3bace8424))
|
||||
* wrap navigators in gesture handler root ([41a5e1a](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/41a5e1a385aa5180abc3992a4c67077c37b998b9))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add useIsDrawerOpen hook ([#299](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/issues/299)) ([ecd68af](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/ecd68afb46a4c56200748da5e5fb284fa5a839db))
|
||||
* integrate with history API on web ([5a3f835](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/5a3f8356b05bff7ed20893a5db6804612da3e568))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.42](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/compare/@react-navigation/drawer@5.0.0-alpha.41...@react-navigation/drawer@5.0.0-alpha.42) (2020-02-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
|
||||
* fix drawerType=back when drawer is on right ([9198597](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/9198597b7f0a34fbe3844ec86a8b82171036f8ed)), closes [#316](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/issues/316)
|
||||
* handle back button in drawer itself ([0e8fda3](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/0e8fda319685a34090cfe82da08084c156eb5783))
|
||||
* screens integration on Android ([#294](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/issues/294)) ([9bfb295](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/9bfb29562020c61b4d5c9bee278bcb1c7bdb8b67))
|
||||
* update screens for native stack ([5411816](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/54118161885738a6d20b062c7e6679f3bace8424))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add useIsDrawerOpen hook ([#299](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/issues/299)) ([ecd68af](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/ecd68afb46a4c56200748da5e5fb284fa5a839db))
|
||||
* integrate with history API on web ([5a3f835](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/commit/5a3f8356b05bff7ed20893a5db6804612da3e568))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.41](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/compare/@react-navigation/drawer@5.0.0-alpha.40...@react-navigation/drawer@5.0.0-alpha.41) (2020-01-24)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/drawer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.40](https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer/compare/@react-navigation/drawer@5.0.0-alpha.39...@react-navigation/drawer@5.0.0-alpha.40) (2020-01-23)
|
||||
|
||||
|
||||
|
||||
21
packages/drawer/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 React Navigation Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -11,7 +11,7 @@
|
||||
"material",
|
||||
"drawer"
|
||||
],
|
||||
"version": "5.0.0-alpha.40",
|
||||
"version": "5.0.0-alpha.44",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/drawer",
|
||||
"main": "lib/commonjs/index.js",
|
||||
@@ -31,7 +31,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.26",
|
||||
"@react-navigation/routers": "^5.0.0-alpha.30",
|
||||
"color": "^3.1.2",
|
||||
"react-native-iphone-x-helper": "^1.2.1"
|
||||
},
|
||||
@@ -42,10 +42,10 @@
|
||||
"del-cli": "^3.0.0",
|
||||
"react": "~16.9.0",
|
||||
"react-native": "~0.61.5",
|
||||
"react-native-gesture-handler": "^1.5.3",
|
||||
"react-native-gesture-handler": "^1.5.5",
|
||||
"react-native-reanimated": "^1.4.0",
|
||||
"react-native-safe-area-context": "^0.6.2",
|
||||
"react-native-screens": "^2.0.0-alpha.25",
|
||||
"react-native-screens": "^2.0.0-alpha.33",
|
||||
"typescript": "^3.7.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -55,7 +55,7 @@
|
||||
"react-native-gesture-handler": "^1.0.0",
|
||||
"react-native-reanimated": "^1.0.0",
|
||||
"react-native-safe-area-context": "^0.6.0",
|
||||
"react-native-screens": "^1.0.0-alpha.0 || ^2.0.0-alpha.0"
|
||||
"react-native-screens": "^2.0.0-alpha.33"
|
||||
},
|
||||
"@react-native-community/bob": {
|
||||
"source": "src",
|
||||
|
||||
@@ -17,6 +17,8 @@ export { default as DrawerContentScrollView } from './views/DrawerContentScrollV
|
||||
*/
|
||||
export { default as DrawerGestureContext } from './utils/DrawerGestureContext';
|
||||
|
||||
export { default as useIsDrawerOpen } from './utils/useIsDrawerOpen';
|
||||
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
|
||||
@@ -63,11 +63,6 @@ export type DrawerNavigationConfig<T = DrawerContentOptions> = {
|
||||
* Set it to `false` if you want to render all screens on initial render.
|
||||
*/
|
||||
lazy?: boolean;
|
||||
/**
|
||||
* Whether a screen should be unmounted when navigating away from it.
|
||||
* Defaults to `false`.
|
||||
*/
|
||||
unmountInactiveScreens?: boolean;
|
||||
/**
|
||||
* Function that returns React element to render as the content of the drawer, for example, navigation items.
|
||||
* Defaults to `DrawerContent`.
|
||||
@@ -117,6 +112,11 @@ export type DrawerNavigationOptions = {
|
||||
* Defaults to `true`
|
||||
*/
|
||||
gestureEnabled?: boolean;
|
||||
/**
|
||||
* Whether this screen should be unmounted when navigating away from it.
|
||||
* Defaults to `false`.
|
||||
*/
|
||||
unmountOnBlur?: boolean;
|
||||
};
|
||||
|
||||
export type DrawerContentComponentProps<T = DrawerContentOptions> = T & {
|
||||
@@ -128,10 +128,6 @@ export type DrawerContentComponentProps<T = DrawerContentOptions> = T & {
|
||||
* `0` is closed, `1` is open.
|
||||
*/
|
||||
progress: Animated.Node<number>;
|
||||
/**
|
||||
* Position of the drawer on the screen.
|
||||
*/
|
||||
drawerPosition: 'left' | 'right';
|
||||
};
|
||||
|
||||
export type DrawerContentOptions = {
|
||||
|
||||
3
packages/drawer/src/utils/DrawerPositionContext.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export default React.createContext<'left' | 'right' | undefined>(undefined);
|
||||
38
packages/drawer/src/utils/useIsDrawerOpen.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import * as React from 'react';
|
||||
import { useNavigation, ParamListBase } from '@react-navigation/native';
|
||||
import { DrawerNavigationProp } from '../types';
|
||||
|
||||
/**
|
||||
* Hook to detect if the drawer is open in a parent navigator.
|
||||
*/
|
||||
export default function useIsDrawerOpen() {
|
||||
const navigation = useNavigation();
|
||||
|
||||
let drawer = navigation as DrawerNavigationProp<ParamListBase>;
|
||||
|
||||
// The screen might be inside another navigator such as stack nested in drawer
|
||||
// We need to find the closest drawer navigator and add the listener there
|
||||
while (drawer && drawer.dangerouslyGetState().type !== 'drawer') {
|
||||
drawer = drawer.dangerouslyGetParent();
|
||||
}
|
||||
|
||||
const [isDrawerOpen, setIsDrawerOpen] = React.useState(() =>
|
||||
drawer
|
||||
? Boolean(
|
||||
drawer.dangerouslyGetState().history.find(it => it.type === 'drawer')
|
||||
)
|
||||
: false
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
const unsubscribe = drawer.addListener('state', e => {
|
||||
setIsDrawerOpen(
|
||||
Boolean(e.data.state.history.find(it => it.type === 'drawer'))
|
||||
);
|
||||
});
|
||||
|
||||
return unsubscribe;
|
||||
}, [drawer, isDrawerOpen]);
|
||||
|
||||
return isDrawerOpen;
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
State,
|
||||
} from 'react-native-gesture-handler';
|
||||
import Animated from 'react-native-reanimated';
|
||||
import Overlay from './Overlay';
|
||||
|
||||
const {
|
||||
Clock,
|
||||
@@ -25,7 +26,6 @@ const {
|
||||
clockRunning,
|
||||
startClock,
|
||||
stopClock,
|
||||
interpolate,
|
||||
spring,
|
||||
abs,
|
||||
add,
|
||||
@@ -52,8 +52,6 @@ const FALSE = 0;
|
||||
const NOOP = 0;
|
||||
const UNSET = -1;
|
||||
|
||||
const PROGRESS_EPSILON = 0.05;
|
||||
|
||||
const DIRECTION_LEFT = 1;
|
||||
const DIRECTION_RIGHT = -1;
|
||||
|
||||
@@ -525,21 +523,29 @@ export default class DrawerView extends React.PureComponent<Props> {
|
||||
gestureHandlerProps,
|
||||
} = this.props;
|
||||
|
||||
const right = drawerPosition === 'right';
|
||||
const isRight = drawerPosition === 'right';
|
||||
|
||||
const contentTranslateX = drawerType === 'front' ? 0 : this.translateX;
|
||||
const drawerTranslateX =
|
||||
drawerType === 'back'
|
||||
? I18nManager.isRTL
|
||||
? multiply(this.drawerWidth, DIRECTION_RIGHT)
|
||||
: this.drawerWidth
|
||||
? multiply(
|
||||
sub(this.containerWidth, this.drawerWidth),
|
||||
isRight ? 1 : -1
|
||||
)
|
||||
: 0
|
||||
: this.translateX;
|
||||
|
||||
const offset = I18nManager.isRTL ? '100%' : multiply(this.drawerWidth, -1);
|
||||
const offset =
|
||||
drawerType === 'back'
|
||||
? 0
|
||||
: I18nManager.isRTL
|
||||
? '100%'
|
||||
: multiply(this.drawerWidth, -1);
|
||||
|
||||
// FIXME: Currently hitSlop is broken when on Android when drawer is on right
|
||||
// https://github.com/kmagiera/react-native-gesture-handler/issues/569
|
||||
const hitSlop = right
|
||||
const hitSlop = isRight
|
||||
? // Extend hitSlop to the side of the screen when drawer is closed
|
||||
// This lets the user drag the drawer from the side of the screen
|
||||
{ right: 0, width: open ? undefined : swipeEdgeWidth }
|
||||
@@ -577,26 +583,7 @@ export default class DrawerView extends React.PureComponent<Props> {
|
||||
{renderSceneContent({ progress: this.progress })}
|
||||
</View>
|
||||
<TapGestureHandler onHandlerStateChange={this.handleTapStateChange}>
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.overlay,
|
||||
{
|
||||
opacity: interpolate(this.progress, {
|
||||
inputRange: [PROGRESS_EPSILON, 1],
|
||||
outputRange: [0, 1],
|
||||
}),
|
||||
// We don't want the user to be able to press through the overlay when drawer is open
|
||||
// One approach is to adjust the pointerEvents based on the progress
|
||||
// But we can also send the overlay behind the screen, which works, and is much less code
|
||||
zIndex: cond(
|
||||
greaterThan(this.progress, PROGRESS_EPSILON),
|
||||
0,
|
||||
-1
|
||||
),
|
||||
},
|
||||
overlayStyle,
|
||||
]}
|
||||
/>
|
||||
<Overlay progress={this.progress} style={overlayStyle} />
|
||||
</TapGestureHandler>
|
||||
</Animated.View>
|
||||
<Animated.Code
|
||||
@@ -615,7 +602,7 @@ export default class DrawerView extends React.PureComponent<Props> {
|
||||
onLayout={this.handleDrawerLayout}
|
||||
style={[
|
||||
styles.container,
|
||||
right ? { right: offset } : { left: offset },
|
||||
isRight ? { right: offset } : { left: offset },
|
||||
{
|
||||
transform: [{ translateX: drawerTranslateX }],
|
||||
opacity: this.drawerOpacity,
|
||||
@@ -641,10 +628,6 @@ const styles = StyleSheet.create({
|
||||
width: '80%',
|
||||
maxWidth: '100%',
|
||||
},
|
||||
overlay: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
},
|
||||
content: {
|
||||
flex: 1,
|
||||
},
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import * as React from 'react';
|
||||
import { ScrollView, StyleSheet, ScrollViewProps } from 'react-native';
|
||||
import { useSafeArea } from 'react-native-safe-area-context';
|
||||
import DrawerPositionContext from '../utils/DrawerPositionContext';
|
||||
|
||||
type Props = ScrollViewProps & {
|
||||
drawerPosition: 'left' | 'right';
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
export default function DrawerContentScrollView({
|
||||
contentContainerStyle,
|
||||
style,
|
||||
drawerPosition,
|
||||
children,
|
||||
...rest
|
||||
}: Props) {
|
||||
const drawerPosition = React.useContext(DrawerPositionContext);
|
||||
const insets = useSafeArea();
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
View,
|
||||
Dimensions,
|
||||
StyleSheet,
|
||||
I18nManager,
|
||||
Platform,
|
||||
ScaledSize,
|
||||
BackHandler,
|
||||
NativeEventSubscription,
|
||||
} from 'react-native';
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import { ScreenContainer } from 'react-native-screens';
|
||||
import { PanGestureHandler } from 'react-native-gesture-handler';
|
||||
import {
|
||||
PanGestureHandler,
|
||||
GestureHandlerRootView,
|
||||
} from 'react-native-gesture-handler';
|
||||
import {
|
||||
DrawerNavigationState,
|
||||
DrawerActions,
|
||||
@@ -26,6 +32,7 @@ import {
|
||||
DrawerNavigationHelpers,
|
||||
DrawerContentComponentProps,
|
||||
} from '../types';
|
||||
import DrawerPositionContext from '../utils/DrawerPositionContext';
|
||||
|
||||
type Props = DrawerNavigationConfig & {
|
||||
state: DrawerNavigationState;
|
||||
@@ -54,6 +61,8 @@ const getDefaultDrawerWidth = ({
|
||||
return Math.min(smallerAxisSize - appBarHeight, maxWidth);
|
||||
};
|
||||
|
||||
const GestureHandlerWrapper = GestureHandlerRootView ?? View;
|
||||
|
||||
/**
|
||||
* Component that renders the drawer.
|
||||
*/
|
||||
@@ -77,7 +86,6 @@ export default function DrawerView({
|
||||
gestureHandlerProps,
|
||||
minSwipeDistance,
|
||||
sceneContainerStyle,
|
||||
unmountInactiveScreens,
|
||||
}: Props) {
|
||||
const [loaded, setLoaded] = React.useState([state.index]);
|
||||
const [drawerWidth, setDrawerWidth] = React.useState(() =>
|
||||
@@ -88,6 +96,47 @@ export default function DrawerView({
|
||||
|
||||
const { colors } = useTheme();
|
||||
|
||||
const isDrawerOpen = Boolean(state.history.find(it => it.type === 'drawer'));
|
||||
|
||||
const handleDrawerOpen = React.useCallback(() => {
|
||||
navigation.dispatch({
|
||||
...DrawerActions.openDrawer(),
|
||||
target: state.key,
|
||||
});
|
||||
}, [navigation, state.key]);
|
||||
|
||||
const handleDrawerClose = React.useCallback(() => {
|
||||
navigation.dispatch({
|
||||
...DrawerActions.closeDrawer(),
|
||||
target: state.key,
|
||||
});
|
||||
}, [navigation, state.key]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isDrawerOpen) {
|
||||
navigation.emit({ type: 'drawerOpen' });
|
||||
} else {
|
||||
navigation.emit({ type: 'drawerClose' });
|
||||
}
|
||||
}, [isDrawerOpen, navigation]);
|
||||
|
||||
React.useEffect(() => {
|
||||
let subscription: NativeEventSubscription | undefined;
|
||||
|
||||
if (isDrawerOpen) {
|
||||
// We only add the subscription when drawer opens
|
||||
// This way we can make sure that the subscription is added as late as possible
|
||||
// This will make sure that our handler will run first when back button is pressed
|
||||
subscription = BackHandler.addEventListener('hardwareBackPress', () => {
|
||||
handleDrawerClose();
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
return () => subscription?.remove();
|
||||
}, [handleDrawerClose, isDrawerOpen, navigation, state.key]);
|
||||
|
||||
React.useEffect(() => {
|
||||
const updateWidth = ({ window }: { window: ScaledSize }) => {
|
||||
setDrawerWidth(getDefaultDrawerWidth(window));
|
||||
@@ -102,51 +151,37 @@ export default function DrawerView({
|
||||
setLoaded([...loaded, state.index]);
|
||||
}
|
||||
|
||||
const handleDrawerOpen = () => {
|
||||
navigation.dispatch({
|
||||
...DrawerActions.openDrawer(),
|
||||
target: state.key,
|
||||
});
|
||||
|
||||
navigation.emit({ type: 'drawerOpen' });
|
||||
};
|
||||
|
||||
const handleDrawerClose = () => {
|
||||
navigation.dispatch({
|
||||
...DrawerActions.closeDrawer(),
|
||||
target: state.key,
|
||||
});
|
||||
|
||||
navigation.emit({ type: 'drawerClose' });
|
||||
};
|
||||
|
||||
const renderNavigationView = ({ progress }: any) => {
|
||||
return drawerContent({
|
||||
...drawerContentOptions,
|
||||
progress: progress,
|
||||
state: state,
|
||||
navigation: navigation,
|
||||
descriptors: descriptors,
|
||||
drawerPosition: drawerPosition,
|
||||
});
|
||||
return (
|
||||
<DrawerPositionContext.Provider value={drawerPosition}>
|
||||
{drawerContent({
|
||||
...drawerContentOptions,
|
||||
progress: progress,
|
||||
state: state,
|
||||
navigation: navigation,
|
||||
descriptors: descriptors,
|
||||
})}
|
||||
</DrawerPositionContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
const renderContent = () => {
|
||||
return (
|
||||
<ScreenContainer style={styles.content}>
|
||||
{state.routes.map((route, index) => {
|
||||
if (unmountInactiveScreens && index !== state.index) {
|
||||
const descriptor = descriptors[route.key];
|
||||
const { unmountOnBlur } = descriptor.options;
|
||||
const isFocused = state.index === index;
|
||||
|
||||
if (unmountOnBlur && !isFocused) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (lazy && !loaded.includes(index) && index !== state.index) {
|
||||
if (lazy && !loaded.includes(index) && !isFocused) {
|
||||
// Don't render a screen if we've never navigated to it
|
||||
return null;
|
||||
}
|
||||
|
||||
const isFocused = state.index === index;
|
||||
const descriptor = descriptors[route.key];
|
||||
|
||||
return (
|
||||
<ResourceSavingScene
|
||||
key={route.key}
|
||||
@@ -165,40 +200,42 @@ export default function DrawerView({
|
||||
const { gestureEnabled } = descriptors[activeKey].options;
|
||||
|
||||
return (
|
||||
<SafeAreaProviderCompat>
|
||||
<DrawerGestureContext.Provider value={drawerGestureRef}>
|
||||
<Drawer
|
||||
open={state.isDrawerOpen}
|
||||
gestureEnabled={gestureEnabled !== false}
|
||||
onOpen={handleDrawerOpen}
|
||||
onClose={handleDrawerClose}
|
||||
onGestureRef={ref => {
|
||||
// @ts-ignore
|
||||
drawerGestureRef.current = ref;
|
||||
}}
|
||||
gestureHandlerProps={gestureHandlerProps}
|
||||
drawerType={drawerType}
|
||||
drawerPosition={drawerPosition}
|
||||
sceneContainerStyle={[
|
||||
{ backgroundColor: colors.background },
|
||||
sceneContainerStyle,
|
||||
]}
|
||||
drawerStyle={[
|
||||
{ width: drawerWidth, backgroundColor: colors.card },
|
||||
drawerStyle,
|
||||
]}
|
||||
overlayStyle={{ backgroundColor: overlayColor }}
|
||||
swipeEdgeWidth={edgeWidth}
|
||||
swipeDistanceThreshold={minSwipeDistance}
|
||||
hideStatusBar={hideStatusBar}
|
||||
statusBarAnimation={statusBarAnimation}
|
||||
renderDrawerContent={renderNavigationView}
|
||||
renderSceneContent={renderContent}
|
||||
keyboardDismissMode={keyboardDismissMode}
|
||||
drawerPostion={drawerPosition}
|
||||
/>
|
||||
</DrawerGestureContext.Provider>
|
||||
</SafeAreaProviderCompat>
|
||||
<GestureHandlerWrapper style={styles.content}>
|
||||
<SafeAreaProviderCompat>
|
||||
<DrawerGestureContext.Provider value={drawerGestureRef}>
|
||||
<Drawer
|
||||
open={isDrawerOpen}
|
||||
gestureEnabled={gestureEnabled !== false}
|
||||
onOpen={handleDrawerOpen}
|
||||
onClose={handleDrawerClose}
|
||||
onGestureRef={ref => {
|
||||
// @ts-ignore
|
||||
drawerGestureRef.current = ref;
|
||||
}}
|
||||
gestureHandlerProps={gestureHandlerProps}
|
||||
drawerType={drawerType}
|
||||
drawerPosition={drawerPosition}
|
||||
sceneContainerStyle={[
|
||||
{ backgroundColor: colors.background },
|
||||
sceneContainerStyle,
|
||||
]}
|
||||
drawerStyle={[
|
||||
{ width: drawerWidth, backgroundColor: colors.card },
|
||||
drawerStyle,
|
||||
]}
|
||||
overlayStyle={{ backgroundColor: overlayColor }}
|
||||
swipeEdgeWidth={edgeWidth}
|
||||
swipeDistanceThreshold={minSwipeDistance}
|
||||
hideStatusBar={hideStatusBar}
|
||||
statusBarAnimation={statusBarAnimation}
|
||||
renderDrawerContent={renderNavigationView}
|
||||
renderSceneContent={renderContent}
|
||||
keyboardDismissMode={keyboardDismissMode}
|
||||
drawerPostion={drawerPosition}
|
||||
/>
|
||||
</DrawerGestureContext.Provider>
|
||||
</SafeAreaProviderCompat>
|
||||
</GestureHandlerWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
51
packages/drawer/src/views/Overlay.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import * as React from 'react';
|
||||
import { Platform, StyleSheet } from 'react-native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
|
||||
const { interpolate, cond, greaterThan } = Animated;
|
||||
|
||||
const PROGRESS_EPSILON = 0.05;
|
||||
|
||||
type Props = React.ComponentProps<typeof Animated.View> & {
|
||||
progress: Animated.Node<number>;
|
||||
};
|
||||
|
||||
const Overlay = React.forwardRef(function Overlay(
|
||||
{ progress, style, ...props }: Props,
|
||||
ref: React.Ref<Animated.View>
|
||||
) {
|
||||
const animatedStyle = {
|
||||
opacity: interpolate(progress, {
|
||||
inputRange: [PROGRESS_EPSILON, 1],
|
||||
outputRange: [0, 1],
|
||||
}),
|
||||
// We don't want the user to be able to press through the overlay when drawer is open
|
||||
// One approach is to adjust the pointerEvents based on the progress
|
||||
// But we can also send the overlay behind the screen, which works, and is much less code
|
||||
zIndex: cond(greaterThan(progress, PROGRESS_EPSILON), 0, -1),
|
||||
};
|
||||
|
||||
return (
|
||||
<Animated.View
|
||||
{...props}
|
||||
ref={ref}
|
||||
style={[styles.overlay, animatedStyle, style]}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
overlay: {
|
||||
...StyleSheet.absoluteFillObject,
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||
...Platform.select({
|
||||
web: {
|
||||
// Disable touch highlight on mobile Safari.
|
||||
WebkitTapHighlightColor: 'transparent',
|
||||
},
|
||||
default: {},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
export default Overlay;
|
||||
@@ -3,6 +3,36 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.39](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.0.0-alpha.36...@react-navigation/material-bottom-tabs@5.0.0-alpha.39) (2020-02-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.37](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.0.0-alpha.36...@react-navigation/material-bottom-tabs@5.0.0-alpha.37) (2020-02-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.36](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.0.0-alpha.35...@react-navigation/material-bottom-tabs@5.0.0-alpha.36) (2020-01-24)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-bottom-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.35](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs/compare/@react-navigation/material-bottom-tabs@5.0.0-alpha.34...@react-navigation/material-bottom-tabs@5.0.0-alpha.35) (2020-01-23)
|
||||
|
||||
|
||||
|
||||
21
packages/material-bottom-tabs/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 React Navigation Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -11,7 +11,7 @@
|
||||
"material",
|
||||
"tab"
|
||||
],
|
||||
"version": "5.0.0-alpha.35",
|
||||
"version": "5.0.0-alpha.39",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/react-navigation/navigation-ex/tree/master/packages/material-bottom-tabs",
|
||||
"main": "lib/commonjs/index.js",
|
||||
@@ -31,7 +31,7 @@
|
||||
"clean": "del lib"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-navigation/routers": "^5.0.0-alpha.26"
|
||||
"@react-navigation/routers": "^5.0.0-alpha.30"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@react-native-community/bob": "^0.8.0",
|
||||
|
||||
@@ -3,6 +3,37 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [5.0.0-alpha.38](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.0.0-alpha.35...@react-navigation/material-top-tabs@5.0.0-alpha.38) (2020-02-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
|
||||
* wrap navigators in gesture handler root ([41a5e1a](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs/commit/41a5e1a385aa5180abc3992a4c67077c37b998b9))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.36](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.0.0-alpha.35...@react-navigation/material-top-tabs@5.0.0-alpha.36) (2020-02-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add licenses ([0c159db](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs/commit/0c159db4c9bc85e83b5cfe6819ab2562669a4d8f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.35](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.0.0-alpha.34...@react-navigation/material-top-tabs@5.0.0-alpha.35) (2020-01-24)
|
||||
|
||||
**Note:** Version bump only for package @react-navigation/material-top-tabs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [5.0.0-alpha.34](https://github.com/react-navigation/navigation-ex/tree/master/packages/material-top-tabs/compare/@react-navigation/material-top-tabs@5.0.0-alpha.33...@react-navigation/material-top-tabs@5.0.0-alpha.34) (2020-01-23)
|
||||
|
||||
|
||||
|
||||
21
packages/material-top-tabs/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 React Navigation Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||